前言

在学习STM32的过程中,刚好学到了LCD屏,我使用的是STM32F103ZET6,屏幕是正点原子的。但是在我自己新建工程点亮显示LCD屏时遇到了很多问题。解决之后分享在此,希望能帮助到遇到此困惑的朋友。 想要快速驱动LCD屏请直接跳转到CubeMX配置

FSMC简单介绍

FSMC全名叫可变静态存储控制器(Flexible Static Memory Controller,FSMC)是单片机的一种接口,它能够连接同步或异步存储器、16位PC存储卡和LCD模块。FSMC连接的所有外部存储器共享地址、数据和控制信号,但有各自的片选信号,所以,FSMC一次只能访问一个外部器件。 FSMC接口用于驱动外部存储器,也可以用于驱动8080接口的TFT LCD。 从FSMC的角度来看,外部存储器被划分为4个固定大小的存储区域,每个存储区域大小为256MB,各个区域的作用描述如下。 Bank1可连接多达4个NOR Flash或PSRAM/SRAM存储器件,因为它被分为4个子区(subbank),每个子区容量为64MB,有专用的片选信号。这些子区适合于连接TFT LCD。 Bank 1 -NOR/PSRAM 1,片选信号NE1。 Bank 1 -NOR/PSRAM 2,片选信号NE2。 Bank 1 -NOR/PSRAM 3,片选信号NE3。(开发板上用于连接外部SRAM) Bank 1 -NOR/PSRAM 4,片选信号NE4。(开发板上用于连接TFT LCD)

Bank2 和 Bank3用于访问NAND Flash存储器,每个存储区域连接一个设备。

Bank4 用于连接PC卡设备。

TFT LCD简单介绍

TFT LCD 即薄膜晶体管(Thin Film Transistor)LCD,具有辐射低、功耗低、全彩色等优点, 是各种电子设备常用的一种显示设备。TFT LCD(后面也会简称为LCD)通常使用标准的8080并口,这种接口有16位数据线,还有几根控制线。TFTLCD的8080并行接口线的功能如下图所示。

CubeMX配置

FSMC子区配置 开发板上LCD原理图 通过原理图也可知要将子区配置为NE4。 LCD_Register Select寄存器根据原理图RS位可知设为A10.。 同时要将LCD_BL对应的引脚设置为输出模式即可(背光引脚)。(我这里对应的是PB0) FSMC相关参数配置 RCC时钟配置 配置时钟树时默认将HCLK配置为72MHz(最大)即可。

LCD驱动程序改写

因为每块开发板对应的LCD历程会有所不一样,且为了保证不同芯片驱动的LCD都能够点亮。所以请下载正点原子资料下载中心的STM32F103最小系统板的TFT LCDHAL库历程进行改写。

将LCD相关文件导入到新建的例程中。

头文件的替换

(1)lcd.c文件中包含lcd.h、font.h和main.h即可 (2)lcd.h文件中只需包含main.h即可

基础数据类型的替换

使用快捷健CTRL+F来到替换界面。两个文件中将u8、u16和u32替换成uint8_t、uint16_t和uint32_t。 再将vuint16_t替换成__IO uint16_t。

函数的替换

采用上一点的方法将所有的delay_ms和delay_us替换成HAL_Delay(实测不影响程序运行)。

注释lcd.c中重复的代码

此环节说是重复代码注释,其实主要目的是为了便于移植程序。因为fsmc. 文件和原始的lcd.c文件中会有相同的初始化部分。 1.注释LCD_Init()函数最开始的fsmc初始化部分 即将以下部分的代码全部注释(此部分在MX_FSMC_Init()函数中已执行过)。

// GPIO_InitTypeDef GPIO_Initure;

// FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim;

// FSMC_NORSRAM_TimingTypeDef FSMC_WriteTim;

// __HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟

// GPIO_Initure.Pin=GPIO_PIN_0; //PB0,背光控制

// GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出

// GPIO_Initure.Pull=GPIO_PULLUP; //上拉

// GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速

// HAL_GPIO_Init(GPIOB,&GPIO_Initure);

// TFTSRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;

// TFTSRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;

// TFTSRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK4; //使用NE4

// TFTSRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE; //地址/数据线不复用

// TFTSRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM; //SRAM

// TFTSRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16; //16位数据宽度

// TFTSRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE; //是否使能突发访问,仅对同步突发存储器有效,此处未用到

// TFTSRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW; //等待信号的极性,仅在突发模式访问下有用

// TFTSRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS; //存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT

// TFTSRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE; //存储器写使能

// TFTSRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE; //等待使能位,此处未用到

// TFTSRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_ENABLE; //读写使用不同的时序

// TFTSRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE; //是否使能同步传输模式下的等待信号,此处未用到

// TFTSRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE; //禁止突发写

//

// //FMC读时序控制寄存器

// FSMC_ReadWriteTim.AddressSetupTime=0x06; //地址建立时间(ADDSET)为7个HCLK 13.8ns*7=96.6ns

// FSMC_ReadWriteTim.AddressHoldTime=0;

// FSMC_ReadWriteTim.DataSetupTime=26; //数据保存时间为27个HCLK =13.8*27=372.6ns

// FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式A

// //FMC写时序控制寄存器

// FSMC_WriteTim.BusTurnAroundDuration=0; //总线周转阶段持续时间为0,此变量不赋值的话会莫名其妙的自动修改为4。导致程序运行正常

// FSMC_WriteTim.AddressSetupTime=3; //地址建立时间(ADDSET)为4个HCLK =55.2ns

// FSMC_WriteTim.AddressHoldTime=0;

// FSMC_WriteTim.DataSetupTime=0x06; //数据保存时间为13.8ns*7个HCLK=96.6ns

// FSMC_WriteTim.AccessMode=FSMC_ACCESS_MODE_A; //模式A

// HAL_SRAM_Init(&TFTSRAM_Handler,&FSMC_ReadWriteTim,&FSMC_WriteTim);

// HAL_Delay(50); // delay 50 ms

2.注释函数void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram) 此函数是对fsmc相关的引脚进行GPIO配置。

收尾工作

1.将LCD_Init()函数最后面的代码注释(如下)。

LCD_LED = 1;

改为一下代码点亮背光(让屏幕亮起来)。

HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,1);

2.将LCD_Init()函数中的printf代码行注释,如下。

printf(" LCD ID:%x\r\n", lcddev.id); //打印LCD ID

因为原历程使用串口一进行串口调试,要是没有初始化串口一的话,运行时会一直卡在这里。 3.最后在主函数中包含lcd.h头文件,添加以下代码即可运行。

LCD_Init();

LCD_ShowString(100,100,100,24,24,"114514");

4.大家以后要移植LCD程序时,复制相关文件到对应工程,包含头文件,调用初始化函数即可使用。节省时间! 源码我放在网盘了,有需要的可以自取: 链接:https://pan.baidu.com/s/1EfmoR1q8q69twGvVbt93_Q?pwd=g8tk 提取码:g8tk

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: