STM32CubeMX实战教程(七)

您所在的位置:网站首页 液晶显示芯片防水吗为什么 STM32CubeMX实战教程(七)

STM32CubeMX实战教程(七)

2024-07-14 18:59| 来源: 网络整理| 查看: 265

大家好,又见面了,我是你们的朋友全栈君。

液晶显示前言材料TFT_LCDFSMC接口原理图工程配置进入代码驱动程序引入代码分析TFTLCD_InitLCD_DrawxxxLCD_FillLCD_Showxxxx功能实现下载验证结语前言

想来想去,也不知道更新什么内容比较好了,犹豫了好久还是先跟大家讲讲液晶显示的配置吧,毕竟我觉得这个在很多项目中都非常实用,我个人是比较喜欢用一块TFT液晶来做显示终端的,大大的屏幕显示什么都方便,接到产品上面也显得特别高端,当然在考虑成本的情况下OLED和12864这些也是不错的选择。

材料STM32F4正点原子探索者开发板原理图TFT_LCD(我这里用的是4.3寸的液晶,芯片为ILI9341,但理论上本驱动程序支持的芯片包括ILI9341/ILI9325/RM68042/RM68021/ILI9320/ILI9328/LGDP4531/LGDP4535/SPFD5408/1505/B505/C505/NT35310/NT35510/SSD1963等)LCD驱动芯片的手册(这里用的是ILI9341)有手就行TFT_LCD

由于TFT_LCD的知识,比较多,我这里尽量简明扼要地讲讲我认为开发中需要用的部分

FSMC接口

FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和16位PC存储器卡连接,STM32的FSMC接口支持包括SRAM、NAND FLASH、NOR FLASH和PSRAM等存储器。 FSMC的框图如下图所示:

在这里插入图片描述在这里插入图片描述

TFTLCD通过RS信号来决定传送的数据是数据还是命令,本质上可以理解为一个地址信号,比如我们把RS接在A0上面,那么当FSMC控制器写地址0的时候,会使得A0变为0,对TFTLCD来说,就是写命令。而FSMC写地址1的时候,A0将会变为1,对TFTLCD来说,就是写数据了。这样,就把数据和命令区分开了,他们其实就是对应SRAM操作的两个连续地址。当然RS也可以接在其他地址线上,而这个板子是把RS接在A6上面。 这里需要注意:FSMC接口驱动LCD时,其实是将LCD当作一个外部的SRAM来驱动的,唯一不同就是TFTLCD有RS信号,但是没有地址信号 FSMC驱动外部SRAM时,外部SRAM的控制一般有:地址线(如A0-A25)、数据线(如D0-D15)、写信号(WE,即WR)、读信号(OE,即RD)、片选信号(CS),如果SRAM支持字节控制,那么还有UB/LB信号。

STM32的FSMC支持8/16/32位数据宽度,我们这里用到的LCD是16位宽度的,所以在设置的时候,选择16位宽就OK了。FSMC的外部设备地址映像,STM32的FSMC将外部存储器划分为固定大小为256M字节的四个存储块。

在这里插入图片描述在这里插入图片描述

STM32的FSMC存储块1(Bank1)用于驱动NOR FLASH/SRAM/PSRAM,被分为4个区,每个区管理64M字节空间,每个区都有独立的寄存器对所连接的存储器进行配置。Bank1的256M字节空间由28根地址线(HADDR[27:0])寻址。 这里HADDR,是内部AHB地址总线,其中,HADDR[25:0]来自外部存储器地址FSMC_A[25:0],而HADDR[26:27]对4个区进行寻址。如下表所示:

在这里插入图片描述在这里插入图片描述

当Bank1接的是16位宽度存储器的时候:HADDR[25:1]-> FSMC_A[24:0] 当Bank1接的是8位宽度存储器的时候:HADDR[25:0]->FSMC_A[25:0]

不论外部接8位/16位宽设备,FSMC_A[0]永远接在外部设备地址A[0] STM32的FSMC存储块1 支持的异步突发访问模式包括:模式1、模式A~D等多种时序模型,驱动SRAM时一般使用模式1或者模式 A,这里我们使用模式A来驱动LCD(当SRAM用)

模式A读时序图模式A读时序图模式A写时序图模式A写时序图原理图

这里跟之前的实验一样是用的正点原子探索者开发板,MCU为STM32F407ZGT6,其中原理图的LCD部分如下:

LCDLCD

对应芯片中的引脚呢,是这样的(有点多): 其中部分引脚的功能呢,前面也已经讲到了,这里不再重复

NE4NE4NWENWE

复位脚和单片机的复位是接到一起的,也就是整个系统的复位,在程序中并没有额外操作

复位复位命令/数据控制命令/数据控制数据脚数据脚数据脚数据脚数据脚数据脚数据脚数据脚

背光电源脚,开了屏幕才能亮

背光电源背光电源

剩下几个脚是触摸屏才需要用到的,这里先不详说 ps:找到这些引脚的目的是在STM32CubeMX中进行比对,确保生成代码的引脚是对应的,要是引脚都对不上的话肯定驱动不起来咯,代码跑不了的第一步也是检查底层硬件对应情况,是个好习惯。

工程配置

这次做的是LCD显示字符串的配置,老规矩,基础配置不多说了,直接上图

晶振晶振时钟树时钟树

我这边是开了一个LED灯作为系统运行指示的,LED配置具体也不说了哈,前面的 《STM32CubeMX实战教程(二)——按键点个灯》有详细介绍了。

LEDLED

然后这边最好开一个串口,并在程序中进行重定向,因为在驱动程序中需要打印一下LCD的ID,如果不开的话会卡在这里,具体会在后面程序分析的时候讲到,如果实在不想开启也可以将串口相关代码删掉,不影响系统运行。串口开启及重定向方法也可以参考 《STM32CubeMX实战教程(六)——串口通信(为啥你的中文会乱码)》

串口串口

在配置FSMC之前先把背光电源脚使能一下,这个不属于FSMC的内容,如果下载程序后屏幕亮不起来那么八成是这里出问题了。 根据原理图背光脚是PB15,配置为上拉高速,初始电平为低。

PB15PB15

下面是FSMC的配置,先上图

外设外设

外设中选择FSMC,配置如下:

外设配置外设配置

这边的选择根据在FSMC介绍的时候都已经详细讲到了,这里就只进行大致的说明。 1.NOR Flash/PSRAM/SRAM/ROM/LCD 1,这里选择这个也就是STM32的FSMC存储块1(Bank1)了 2. Chip Select,选择Bank1的第四区,是根据原理图的映射管脚进行选择的,这里选择不同区对应的引脚是不同的 3. Memory Type,存储类型,这里当然是选择LCD接口,那么里面还可以选择其他的存储类型,如果需要使用其他类型的存储设备也可以详细了解 4. LCD Register Select,这里是选择RS脚,也就是命令/数据选择位,同样是根据原理图得知这里应该选择A6 5. Data,数据位,很明显从原理图看出有16个数据引脚,这里选择16bits就好 接下来这里有一件事情需要大家注意一下,就是最好将目前为止的引脚使能情况跟原理图中的一一对应,也就是检查一遍,虽然花不了多少时间,但是由于使能了大量的引脚,一旦出错那么整个工程就是失败的

引脚对应引脚对应

参数配置如下:

参数配置参数配置

这里需要使能读写不同的时序,也就是Write operation,下面的参数分别是:

地址建立的时钟周期数据建立的时钟周期总线转阶段持续时间扩展地址建立时间扩展数据建立时间扩展总线建立时间 这里扩展的意思就是写时序,而上面几条是读时序。 参数设置的根据是LCD芯片手册中的驱动时序,不同的芯片需要根据不同的手册进行计算,但计算的方法都是一样的,时序如下:参数参数

其中红框中的部分就是我们需要的,显然,WR就是写时序,RD就是读时序,对ILI9341来说,数据保持时间,其实就是低电平持续时间,地址建立时间,相当于高电平持续时间。那么剩下就很简单了,由于F4的一个HCLK=6ns(1/168M),稍加计算就可以得到需要多少个HCLK了。 到这里所有的工程配置工作就结束了,接下来偷个懒就进代码吧,怎么生成代码这里就不多说了。

进入代码驱动程序引入

进来后第一件事当然是编译了,编译完后,需要加入一份驱动程序.,里面有头文件,.c文件和英文的字库,提取码为ljf5,是由正点原子的LCD驱动程序修改而来的,稍后我讲进行细致讲解。 我习惯将文件拷贝到工程目录的Drivers文件夹下,当然其他地方也是可以的,打开编译完成的工程,双击User目录,找到LCD文件夹里面,加入ILI93xx.c文件

加入.c文件加入.c文件

并在C/C++选项卡中加入头文件路径。

添加头文件路径添加头文件路径

然后如果是按照我之前的步骤配置过来的话,这个时候直接编译其实是没有任何问题的,非常简单(ps:串口重定向时需要在usart.h中包含头文件stdio.h,否则报错)

代码语言:javascript复制/* Includes ------------------------------------------------------------------*/ #include "main.h" /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */ extern UART_HandleTypeDef huart1;

如果没有使能串口USART的话,在TFTLCD_Init函数里面有一句话需要注释掉,就是printf打印的这一句,应该是在482行这个位置,这句话负责打印检测到的LCD ID号,可以直接用串口助手看到。

代码语言:javascript复制 if(lcddev.id==0X5761)lcddev.id=0X1963;//SSD1963读回的ID是5761H,为方便区分,我们强制设置为1963 } } } printf(" LCD ID:%x\r\n",lcddev.id); //打印LCD ID 未使能串口则注释掉 if(lcddev.id==0X9341) //9341初始化 { LCD_WR_REG(0xCF); LCD_WR_DATA(0x00); 代码分析

在完成整个工程之前我先将这份驱动代码稍加分析,以及对其功能进行介绍,不然白拿的东西也不是自己的。 首先,打开ILI93xx.h也就是头文件,前面的一些变量申明暂且不用理会,那是在ILI93xx.c中调用的。可以直接看到最下面的函数部分,这边我将几个常用的,没讲到的也可以自己调用试试,现象也是显而易见的。

TFTLCD_Init代码语言:javascript复制void TFTLCD_Init(void); //初始化

LCD的初始化函数,这个是屏幕初始化必须的,这个函数非常长,里面也有详细的注释,主要是初始化各种不同型号的屏幕,所以适用的LCD也是非常多的,至于每一句是什么意思,这里也不需要深究了,因为不太建议自己重新写一份驱动,工程量大不说,还容易出错。 另外背光引脚在这里是有用到的,也就是倒数第二句点亮背光,所以整个工程我们不需要再去额外地操作这个引脚,只需要将其使能即可。

代码语言:javascript复制 LCD_Display_Dir(0); //默认为竖屏 GPIOB->ODR |= 1


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3