LCD
目录
LCD
回顾
应用
- 1、首先将该LCD屏官方写好的三个文件添加进工程中的api文件夹中
- 2、找到LCD的初始化函数
- 3、在LCD屏幕上显示字符串
- 4、在LCD屏幕上显示图片
- 5、在LCD屏幕上显示汉字
例:在LCD屏幕上显示温湿度,时间代码
LCD屏幕 --了解
上述总结来说
FSMC 模拟 8080 时序信号
LCD屏幕代码的实现
-- 学会看时序图
回顾
- RTC
- 使用了官方代码,和咱们之前写的格式不一样,代码看不懂、比较乱。 Rtc 代码编写框架
- 使能后备区域访问、
- 时钟源/分频系数
- 给计数器赋初值
- 中断(秒中断/闹钟中断) RTC 相关的(写操作)函数,在执行完之后,都会有等待函数
- 闹钟中断
应用
-- 这里把LCD屏幕的介绍放在本文后面,因为我们主要学的是软件,理论上说只用学会如果用LCD的代码即可,不需要了解LCD的硬件原理,但为了让大家能看懂代码,所以简单了解即可,不懂也没关系
- 1、首先将该LCD屏官方写好的三个文件添加进工程中的api文件夹中
-- 添加过后,编译工程,会出现错误和警告,不用担心,是因为延时函数写的不一样导致
-- 找到130行的延时函数,
-- 点击CTRL+F,会出现替换的边框,注意一定要在要替换的文件中,点击CTRL+F,除了延时的us出现问题,ms也可能出现问题,所以两个都要替换,替换成自己写的延时函数即可
--
- 2、找到LCD的初始化函数
-- 这里可以设置竖屏和横屏显示,点亮背光,将这个函数放在main函数中
-- 效果就是在屏幕的横坐标是10,纵坐标是10的位置,显示一个点
- 3、在LCD屏幕上显示字符串
在main.c中添加如下代码
LCD_ShowString(0,0,80,16,16,"123456qwer"); //宽度字符是汉字的一半,是8,汉字是16,8*10
-- 前两个参数是坐标,后两个参数是显示的宽度和高度,16是字体大小,最后是显示的字符串。
这里因为汉字的宽度是16,字符的宽度是汉字的一半,所以宽度是8,而一共写入10个字符,10*8=80,所以宽度是80.
-- 效果图
- 4、在LCD屏幕上显示图片
-- 首先,打开图片取模软件。
-- 选择图片,点击打开,配置,然后保存的工程中,他会将这个文件跳出来,关闭即可
-- 1.h如图所示
将1.h的数组名添加到显示图片的代码最后一个参数。
- 注意:这里的列坐标要变一下,因为第一行已经有数据了
LCD_ShowPhoto(0,16,240,135,(uint8_t *)gImage_1);
-- 注意:
要在main.h中加上头文件
-- 效果图
- 5、在LCD屏幕上显示汉字
-- 首先,打开数字取模软件
-- 更改相关参数
-- 生成相应的字模
- 编写代码
-- 相关代码
uint8_t xiang[]=
{0x08,0x80,0x08,0x80,0x08,0x80,0x11,0xFE,0x11,0x02,0x32,0x04,0x34,0x20,0x50,0x20,
0x91,0x28,0x11,0x24,0x12,0x24,0x12,0x22,0x14,0x22,0x10,0x20,0x10,0xA0,0x10,0x40};/*"你",0*/
//1对应的黑色
uint16_t cnttt = 0;
for(uint8_t i=0;i<32;i++) {
for(uint8_t j=0;j<8;j++) {
if((xiang[i] & (1<<(7-j))) != 0) {
LCD_DrawPoint(cnttt%16, cnttt/16);
}
cnttt++;
}
}
例:在LCD屏幕上显示温湿度,时间代码
int main()
{
//pwm_init();
dht11_init();
SysTick_Config(72000);
usart_init();
key_init();
uint16_t b=100;
uint8_t keyflag = 0;
adc_init();
relay_init();
rtc_init();
LCD_Init();//屏幕初始化一定要写到串口初始化后面
LCD_DrawPoint(10,10);
LCD_ShowString(0,0,80,16,16,"123456qwer"); //宽度字符是汉字的一半,是8,汉字是16,8*10
//LCD_ShowPhoto(0,16,240,135,(uint8_t *)gImage_1);//必须是
//摄氏度字模
uint8_t xiang[]=
{0x60,0x00,0x91,0xF4,0x96,0x0C,0x6C,0x04,0x08,0x04,0x18,0x00,0x18,0x00,0x18,0x00,
0x18,0x00,0x18,0x00,0x18,0x00,0x08,0x00,0x0C,0x04,0x06,0x08,0x01,0xF0,0x00,0x00};/*"℃",0*/
//1对应的黑色
uint16_t cnttt = 0;
for(uint8_t i=0;i<32;i++) {
for(uint8_t j=0;j<8;j++) {
if((xiang[i] & (1<<(7-j))) != 0) {
LCD_DrawPoint(cnttt%16+80, cnttt/16+16);
}
cnttt++;
}
}
while(1)
{
if(dhtime >=2000)
{
dhtime =0 ;
get_dht11_val();
sprintf(D_wen, "tem: %.2f℃",dht.tem);
sprintf(D_shi, "hum: %.2f%RH", dht.hum);
//printf("tem:%.2f℃\r\n",dht.tem);
LCD_ShowString(0,16,120,16,16,D_wen);
LCD_ShowString(0,32,120,16,16,D_shi);
}
if(rtctime >=999)
{
rtctime = 0;
get_time();
sprintf(D_time, "%04d/%02d/%02d %02d:%02d:%02d",a.tm_year+1900,a.tm_mon+1,a.tm_mday,a.tm_hour+8,a.tm_min,a.tm_sec);
LCD_ShowString(0,48,180,16,16,D_time);
}
}
}
-- 注意:这里的摄氏度字符放在字符串是显示不出来的,需要生成字模,然后显示在LCD屏上
LCD屏幕 --了解
-- 了解
像素:像素是组成图像的最基本单元要素,显示器的像素指它成像最小的点,即前面讲解液晶原理中提到的一个显示单元。 分辨率:一些嵌入式设备的显示器常常以“行像素值 x 列像素值”表示屏幕的分辨率。如分辨 率 800x480 表示该显示器的每一行有 800 个像素点,每一列有 480 个像素点,也可理 解为有 800 列, 480 行
色彩深度:色彩深度指显示器的每个像素点能表示多少种颜色,一般用“位” (bit)来表示。如单色屏的每个像素点能表示亮或灭两种状态(即实际上能显示 2 种颜色),用 1 个数据位就可以表示像素点的所有状态,所以它的色彩深度为 1bit,其它常见的显示屏色深为 16bit RGB565、 24bit RGB888 。0(白) 1(黑) 红色:1111 1000 0000 0000
红色:1111 1111 0000 0000 0000 0000
显示器尺寸:显示器的大小一般以英寸表示,如 5 英寸、 21 英寸、 24 英寸等,这个长度是指屏幕对角线的长度, 通过显示器的对角线长度及长宽比可确定显示器的实际长宽尺寸。
点距:点距指两个相邻像素点之间的距离, 它会影响画质的细腻度及观看距离,相同尺寸的屏幕,若分辨率越高,则点距越小,画质越细腻。如现在有些手机的屏幕分辨率比电脑显示器的还大,这是手机屏幕点距小的
原因; LED 点阵显示屏的点距一般都比较大,所以适合远距离观看。
- 常见 LCD 屏幕的构成
显示屏由液晶显示面板、触摸面板以及 PCB 底板构成。
图中的触摸面板带有触摸控制芯片,该芯片处理触摸信号并通过引出的信号线与外部器件通讯,触摸面板中间是透明的,它贴在液晶面板上面,一起构成屏幕的主体,触摸面板与液晶面板引出的排线连接到 PCB 底板上,根据实际需要,PCB 底板上可能会带有“液晶控制器芯片”,因为控制液晶面板需要比较多的资源,所以大部分低级微控制器都不能直接控制液晶面板,需要额外配套一个专用液晶控制器来处理显示过程,外部微控制器只要把它希望显示的数据直接交给液晶控制器即可。而不带液晶控制器的 PCB 底板,只有小部分的电源管理电路,液晶面板的信号线与外部微控制器相连,直接控制。
有些芯片不需要额外的液晶控制器,也就是说芯片把专用液晶控制器的功能集成到内部了,可以理解为电脑 的 CPU 集成显卡,它节约了额外的控制器成本。而 STM32F1 系列的芯片由于没有集成液晶控制器到芯片内部, 所以它只能驱动自带控制器的屏幕,可以理解为电脑的外置显卡。
- 液晶显示器的控制信号线
-- 液晶面板的控制信号线液晶面板引出的 FPC 排线,液晶面板通过这些信号线与液晶控制器通讯,使用这种 通讯信号的被称为 RGB 接口。
RGB 信号线:RGB 信号线各有 8 根,分别用于表示液晶屏一个像素点的红、绿、蓝颜色分量。使用红绿蓝颜色分量来表示颜色是一种通用的做法。常见的颜色表示会在“RGB”后面附带各个颜色分量值的数据位数,如RGB565 表示红绿蓝的数据线数分别为 5、 6、 5 根,一共为 16 个数据位,可表示 2^16 种颜色;而有些液晶屏的种颜色分量的数据线都有 8 根,所以它支持 RGB888 格式,一共 24 位数据线,可表示的颜色为 2^24 种。
同步时钟信号 CLK:液晶屏与外部使用同步通讯方式,以 CLK 信号作为同步时钟,在同步时钟的驱动下,每个时钟传输一个像素点数据。
水平同步信号 HSYNC:水平同步信号 HSYNC(Horizontal Sync)用于表示液晶屏一行像素数据的传输结束,每传输完成液晶屏的一行像素数据时, HSYNC 会发生电平跳变,如分辨率为 800x480 的显示屏(800 列, 480行),传输一帧的图像 HSYNC 的电平会跳变 480 次。
垂直同步信号 VSYNC:垂直同步信号 VSYNC(Vertical Sync)用于表示液晶屏一帧像素数据的传输结束,每传输完成一帧像素数据时, VSYNC 会发生电平跳变。其中“帧”是图像的单位,一幅图像称为一帧,在液晶屏中,一帧指一个完整屏液晶像素点。人们常常用“帧/秒”来表示液晶屏的刷新特性,即液晶屏每秒可以显示多少帧图像,如液晶屏以 60 帧/秒的速率运行时, VSYNC 每秒钟电平会跳变 60 次。
数据使能信号 DE:数据使能信号 DE(Data Enable)用于表示数据的有效性,当 DE 信号线为高电平时,RGB信号线表示的数据有效
- 显存
液晶屏中的每个像素点都是数据,在实际应用中需要把每个像素点的数据缓存起来,再传输给液晶屏,一般会使用 SRAM 或 SDRAM 性质的存储器,而这些专门用于存储显示数据的存储器, 则被称为显存。
显存一般至少要能存储液晶屏的一帧显示数据,如分辨率为 800x480 的 液 晶 屏 , 使 用 RGB888 格 式 显 示 , 它的 一 帧 显 示 数 据 大 小 为 :3x800x480=1152000 字 节 ; 若 使 用 RGB565 格 式 显 示 , 一 帧 显 示 数 据 大 小 为 :2x800x480=768000 字节。
-- 这里RGB888为什么是3*800,因为他是24位的,而1个字节是8位,所以3个字节表示一个像素点。同理RGB565是16位的
- 我们的液晶屏—ILI9341
液晶屏内部包含有一个液晶控制芯片 ILI9341。该芯片最主核心部分是位于中间的 GRAM(Graphics RAM), 它就是显存。
GRAM 中每个存储单元都对应着液晶面板的一个像素点。它右侧的各种模块共同作用把 GRAM 存储单元的数据转化成液晶面板的控制信号,使像素点呈现特定的颜色,而像素点组合起来则成为一幅完整的图 像。
框图的左上角为 ILI9341 的主要控制信号线和配置引脚,根据其不同状态设置可以使芯片工作在不同的模 式,如每个像素点的位数是 6、 16 还是 18 位;可配置使用 SPI 接口、8080 接口还是 RGB 接口与 MCU 进 行通讯。
MCU 通过 SPI、 8080 接口或 RGB 接口与 ILI9341 进行通讯,从而访问它的控制寄存器(CR)、地址 计数器(AC)、及 GRAM。在 GRAM 的左侧还有一个 LED 控制器(LED Controller)。LCD 为非发光性的显示装置, 它需要借助背光源才能达到显示功能, LED 控制器就是用来控制液晶屏中的 LED 背光源。
- 液晶屏的信号线及 8080 时序
ILI9341 控制器根据自身的 IM[3:0]信号线电平决定它与 MCU 的通讯方式,它本身支持 SPI 及 8080 通讯 方式,液晶屏的 ILI9341 控制器在出厂前就已经按固定配置好(内部已连接硬件电路),它被配置为通过 8080 接 口通讯,使用 16 根数据线的 RGB565 格式。内部硬件电路连接完, 剩下的其它信号线被引出到 FPC 排线, 最后该排线由 PCB 底板引出到排针,排针再与实验板上的 STM32 芯片连接。
这些信号线即 8080 通讯接口,带 X 的表示低电平有效, STM32 通过该接口与 ILI9341 芯片进行通讯, 实现对液晶屏的控制。通讯的内容主要包括命令和显存数据,显存数据即各个像素点的 RGB565 内容;命令是 指对 ILI9341 的控制指令, MCU 可通过 8080 接口发送命令编码控制 ILI9341 的工作方式,例如复位指令、 设置光标指令、睡眠模式指令等等,具体的指令在数据手册均有详细说明。
由图可知,写命令时序由片选信号 CSX 拉低开始,对数据/命令选择信号线 D/CX 也置低电平表示写入的 是命令地址(可理解为命令编码,如软件复位命令: 0x01),以写信号 WRX 为低,读信号 RDX 为高表示数据传 输方向为写入,同时,在数据线 D[17:0](或 D[15:0])输出命令地址,在第二个传输阶段传送的是命令的参数,所 以 D/CX 要置高电平,表示写入的是命令数据,命令数据是某些指令带有的参数,如复位指令编码为 0x01,它 后面可以带一个参数,该参数表示多少秒后复位(实际的复位命令不含参数,此处只是为了讲 解指令编码与参数的区别)。
-- 注:这里的片选信号类似于使能引脚,电平拉低,相当于使能,电平拉高,相当于失能
当需要把像素数据写入 GRAM 时,过程很类似,把片选信号 CSX 拉低后,再把数据/命令选择信号线 D/CX置为高电平,这时由 D[17:0]传输的数据则会被 ILI9341 保存至它的 GRAM 中。
上述总结来说
-- 对于 ILI9341 这个液晶驱动芯片,单片机对于他的驱动,针对显示而言。
- 0x2A(设置列地址:宽度)
- 0x2B(设置页地址:高度)
- 0x2C(写数据:像素点颜色)
-- 通过 8080 写时序,完成这三个指令的发送,用这三个指令就能实现屏幕的显示操作
- 现在他通信的话就需要一个8080的接口,但是该单片机上没有8080,下面讲fsmc模拟800时序
FSMC 模拟 8080 时序信号
-- FSMC介绍
STM32 控制器芯片内部有一定大小的 SRAM 及 FLASH 作为内存和程序存储空间,但当程序较大,内存和 程序空间不足时,就需要在 STM32 芯片的外部扩展存储器了。扩展内存时一般使用 SRAM 和 SDRAM 存储器, 但 STM32F1 系列的芯片不支持扩展 SDRAM(最新的一些系列芯片支持),它仅支持使用 FSMC 外设扩展 SRAM, 我们以 SRAM 为例讲解如何为 STM32 扩展内存。
- 总结来说FSMC就是来扩展内存的
LCD屏幕代码的实现
-
1、初始化 IO FSMC 是片上外设,只要是需要 FSMC 自动调节的全部为 复用
LCD_BL 背光 配置成通用推挽输出 -
2、配置 FSMC – SRAM
-
3、我们操作的是个屏幕,地址线没有实际意义 但是硬件已经确定了,A10 这个引脚有意义 DC 如果想要输出数据 DC – 1,那么我们往哪一个地址内写数据?只要符合 A10 输出 1、NE4 自动选中的地址即可。
-- 显示原理—设置一个区域然后逐个像素点的发送色彩
2A -- 设置开始列 和 结束列
2B 设置开始行 结束行
2C 写数据指令
2A 发送设置列的指令
X 开始列
X+W 结束列
2B 发送设置行的指令
Y 开始行
Y+H 结束行
2C 发送写数据指令
循环发送对应的颜色数据