MCU:STM32F103VET6
开发环境:STM32CubeMX+MDK5
目录
STM32液晶屏LCD(ILI9341)
LCD液晶显示
液晶控制原理
ILI9341液晶控制器简介
8080写时序
8080读时序
FSMC模拟8080时序
液晶屏的信号线
STM32CubeMX配置FSMC
测试部分
知识点分析
STM32液晶屏LCD(ILI9341)
本文章使用STM32F103VET6,野火指南者的3.2寸电阻屏,进行学习。
LCD液晶显示
针对野火指南者配套资料:3.2寸 LCD电阻屏,屏幕里自带ILI9341液晶控制器芯片,该控制器芯片中存在GRAM(即显存)。该液晶控制器使用8080接口与单片机通讯,液晶面板引出来的FPC信号线为8080接口,单片机把要显示的数据通过引出的8080接口发送到液晶控制器,要显示的数据存储到它内部的显存中,然后液晶控制器不断把显存的内容刷新到液晶面板,显示内容。
还有个电阻触摸屏的控制器XPT2046,实际上是一个ADC芯片,通过检测电压值来计算触摸坐标。
液晶屏的每个像素点都是数据,在实际应用中需要把每个像素点的数据缓存起来,再传输给液晶屏,一般会使用SRAM和SDRAM性质的存储器,而这些专门用于存储显示数据的存储器,被称为显存。显存一般至少要能存储一帧显示数据,如分辨率为800*480的液晶屏,若使用RGB888格式显示,一帧数据大小 = 3 * 800 * 480 = 1152000字节;若使用RGB565格式显示,一帧数据大小 = 2 * 800 * 480 = 768000字节。
一般来说,外置的液晶控制器会自带显存,而像STM32F429等集成液晶控制器的芯片可使用内部SRAM或外扩SDRAM用于显存空间。
液晶控制原理
因为控制液晶面板需要比较多的资源,所以大部分低级微处理器都不能直接控制液晶面板,需要额外配套一个专用液晶控制器来处理显示过程,外部微控制器只要把它希望显示的数据直接交给液晶控制器即可。而不带液晶控制器的PCB底板,只有小部分的电源管理电路,液晶面板的信号线与外部微控制器相连,直接控制。
STM32F429系列的芯片不需要额外的液晶控制器,即它把专用液晶控制器的功能集成到STM32F429芯片内部了,节省了额外的控制器成本。而STM32F1系列的芯片由于没有继承液晶控制器到芯片内部,所以只能驱动只带控制器的屏幕。
ILI9341液晶控制器简介
内部结构复杂。芯片中含有GRAM(即显存),GRAM中每个存储单元都对应液晶面板的一个像素点。通过液晶控制器内部各种模块共同作用把GRAM存储单元的数据转化为液晶面板的控制信号,使像素点呈现特定的颜色,而像素点组合起来则成为了一幅完整的图像。
ILI9341液晶控制器根据自身的IM[3:0]信号线电平决定了它与MCU的通讯方式,支持SPI、8080通讯方式。野火指南者中固定搭配8080(内部硬件电路处理),使用16根数据线的RGB565格式。即当IM[3:0]=0x8时,MCU接口模式为8080 MCU 16-bit bus interface II。
8080写时序
8080读时序
FSMC模拟8080时序
因为8080时序与FSMC(SRAM,NorFlash等)时序类似,所以只需将ILI9341液晶控制器当成一个存储器来使用。这样STM32就可以通过FSMC外设与ILI9341液晶控制器通信。
Tips:
百度上都是使用NorFlash的FSMC模式B时序模拟8080时序,但是其实SRAM的FSMC模式A时序模拟8080时序也是可行的。如果有读者有详细的说法可以在评论区更详细的展开。
液晶屏的信号线
FSCM_D[15:0]:数据信号。
FSMC_NE1:片选信号,低电平有效。
FSMC_NOE:读数据信号,低电平有效。
FSMC_NWE:写数据信号,低电平有效。
FSMC_RS:数据/命令信号。
高电平时,D[15:0]表示的是数据(RGB像素数据或命令数据)
低电平时,D[15:0]表示的是控制命令
LCD_RST:复位信号,低电平有效。
LCD_BL:背光信号,低电平有效。
LCD_TP:用于触摸屏的,它们是直接连接到xpt2046(触摸控制芯片),此处不讲。
STM32CubeMX配置FSMC
常规配置不展开,配置主频为72MHz。记住额外配置引脚(推挽输出):PE1-LCD_RST、PD12-LCD_BL。
HCLK周期:HCLK配置为72MHz,即一个HCLK周期为1/72us = 13.8ns
13.8 * 26 = 358.8 > 355ns
13.8 * 1 = 13.8 > 10ns
测试部分
添加工程主目录下添加UserCode文件夹,将野火《液晶显示》的bsp_ili9341.c、bsp_ili9341.h、fonts.c和fonts.h文件放入文件夹中。
ILI9341_Init函数中注释掉ILI9341_GPIO_Config();ILI9341_FSMC_Config();
然后main函数中调用ILI9341_Init();
然后在添加测试函数:LCD_Test();
Tips:需要把编译优化等级跳-O0或-O1才能正常显示。-O2会出现碎花屏,-O3会出现白屏。
实验现象:
知识点分析
在FSMC中,Bank1一个存储块有4个区,每个区可以扩展SRAM或者NorFlash存储器,相当于一个Bank1可以扩展4个SRAM或者NorFlash存储器。
实验中使用了FSNC_NE1作为片选引脚。即选择了FSMC的Bank1的第一区,地址范围是0x6000 0000 - 0x63FF FFFF。
使用了D0~D15数据线,数据宽度16bit。即HADDR[25:1]与FSMC_A[24:0]对应连接,HADDR[0]未接。
相当于:
FSMC的地址为1时,对应HADDR的地址为10。
FSMC的地址为10时,对应HADDR的地址为100。
可发现,相对于FSMC地址,HADDR左移一位,即*2。
FSMC_A16接LCD的D/C引脚。
当A16高电平时,D[15:0]为数据。所以控制地址线A16输出1,则0x6000 0000 | (1<<17) = 0x6002 0000。这相当于数据地址。
当A16低电平时,D[15:0]为命令。所以控制地址线A16输出0,则0x6000 0000 | (0<<17) = 0x6000 0000。这相当于命令地址。
因此,
/*************************************************************************************** 2^26 =0X0400 0000 = 64MB,每个 BANK 有4*64MB = 256MB 64MB:FSMC_Bank1_NORSRAM1:0X6000 0000 ~ 0X63FF FFFF 64MB:FSMC_Bank1_NORSRAM2:0X6400 0000 ~ 0X67FF FFFF 64MB:FSMC_Bank1_NORSRAM3:0X6800 0000 ~ 0X6BFF FFFF 64MB:FSMC_Bank1_NORSRAM4:0X6C00 0000 ~ 0X6FFF FFFF ****************************************************************************************/ /******************************* ILI9341 显示屏的 FSMC 参数定义 ***************************/ //FSMC_Bank1_NORSRAM用于LCD命令操作的地址 #define FSMC_Addr_ILI9341_CMD ( ( uint32_t ) 0x60000000 ) //FSMC_Bank1_NORSRAM用于LCD数据操作的地址 #define FSMC_Addr_ILI9341_DATA ( ( uint32_t ) 0x60020000 ) /** * @brief 向ILI9341写入命令 * @param usCmd :要写入的命令(寄存器地址) * @retval 无 */ void ILI9341_Write_Cmd(uint16_t usCmd) { * (__IO uint16_t *)(FSMC_Addr_ILI9341_CMD) = usCmd; } /** * @brief 向ILI9341写入数据 * @param usData :要写入的数据 * @retval 无 */ void ILI9341_Write_Data(uint16_t usData) { * (__IO uint16_t *)(FSMC_Addr_ILI9341_DATA) = usData; } /** * @brief 从ILI9341读取数据 * @param 无 * @retval 读取到的数据 */ uint16_t ILI9341_Read_Data(void) { return (* (__IO uint16_t *)(FSMC_Addr_ILI9341_DATA)); }