STM32之FSMC驱动LCD深入理解

目前市场上的LCD种类繁多,驱动方式也多种多样。
一般都是液晶面板,液晶控制器,触摸控制器三种器件进行组合的。
在这里插入图片描述
现在的LCD驱动框图如下:
带液晶驱动器的LCD一般都内置显存,采用8080/SPI接口。
不带液晶驱动器的LCD一般都采用RGB接口。

在这里插入图片描述
现在深入理解一下用FSMC/FMC模拟8080接口驱动:

8080接口FSMC/FMC功能
CSXNex片选信号
WRXNWR写使能
RDXNOE读使能
D[15:0]D[15:0]数据信号
D/CXA[x] 某一位地址线数据/指令选择

在这里插入图片描述

LCD常见的驱动芯片ILI9341用8080接口进行驱动的话,只要满足它的驱动时序就可以驱动LCD了,只是用普通的IO进行时序模拟比较复杂罢了。常见的方式是采用FSMC进行模拟,而FSMC和8080信号线和时序看起来基本一致,只是FSMC多了许多地址线而已。
从FSMC时序图来看,在一个写入周期内,除了地址信号,其它信号都是一致的,而地址信号A[25:0]在整个写入周期内都在生效,但是8080接口没有地址信号只有D/CX(数据/指令切换)信号,而D/CX信号只需要一个IO,那我们就可以将A[25:0]中的一个IO当作D/CX信号来用。

那么D/CX信号怎么实现呢?

D/CX信号高电平表示图像数据,低电平表示指令数据。
对于8080接口来说它一个周期需要D[15:0]+D/CX共17位数据就可以进行数据解析了,
而对于FSMC接口来说它一个周期需要发送A[25:0]+D[15:0]共42位数据。
在这里插入图片描述
数据宽度是16位的话就要注意FSMC_A地址信号和内部存储地址的对应关系,FSMC_A0对应内存地址的bit1,依次类推,FSMC_A24对应内存地址的bit25

我们以FSMC_Bank1_NORSRAM1作为片选内存进行分析:
在这里插入图片描述

地址数据二进制
0x6000 00000x010000 0001
0x6000 00010xa01010 0000
0x6000 00030x1b0001 1011
0x6000 00000x240010 0100

FSMC_Bank1_NORSRAM1首地址是0x6000 0000,那么FSMC的地址寻址从0x6000 0000开始,假设FSMC要从首地址发数据,那它的A[25:0]就是0x6000 0000的低26位数据,它的D[15:0]就是0x01 0xa0 (0000 0001 1010 0000)。
假如我们的8080接口连的是FSMC_A1这个地址线,那么我们要发送指令的话A1这个IO就需要一直是0才可以,而A1对应内存地址的bit2,我们从地址0x6000 0000开始随便找一个bit2是0的地址,就可以通过这个地址发送指令数据了(只要不超出NORSRAM1的地址范围就行),比如0x6000 0000或0x6000 0001或0x6000 0002…,这些地址bit2都是0,给这些地址写数据就相当于发送指令数据了。
如果我们要发送图像数据,那么A1这个IO就需要一直是1才可以,那我们就需要从地址0x6000 0000开始随便找一个bit2是1的地址,就可以通过这个地址发送图像数据了(只要不超出NORSRAM1的地址范围就行),比如0x6000 0004或0x6000 0005或0x6000 0006…,这些地址bit2都是1,给这些地址写数据就相当于发送图像数据了。

因此FSMC模拟8080接口的指令地址和图像数据地址不是唯一的,只要满足时序要求的地址都可以进行数据传输。

一般我们都是从片选内存的首地址开始寻找指令地址和图像数据地址,这时候就用到置0和置1的方法了。
置0:Addr&=~(1<<n)
置1:Addr|=(1<<n)
16位数据宽度的FSMC_A[24:0]和内存地址的对应关系是:FSMC_A0对应内存地址的bit1,依次类推,FSMC_A24对应内存地址的bit25。
Addr是内存的首地址,n=FSMC_Ax+1。A0的话n=1,A1的话n=2…

Addr=0x6000 0000
指令地址:0x6000 0000&=~(1<<2) ----->0x6000 0000
图像数据地址:0x6000 0000|=(1<<2)---->0x6000 0004

其实也没有那么难理解了,地址随便猜了,总有正确的,O(∩_∩)O

### STM32F4 FSMC 驱动 LCD 示例代码与教程 #### 初始化 FSMCLCD 控制器 为了使 STM32F4 能够通过 FSMC 接口驱动 TFTLCD,需要先初始化 FSMC 外设并设置相应的参数。具体来说,TFTLCD 可以被当作 SRAM 来控制,因此会使用相同的地址和数据总线[^1]。 ```c void FSMC_LCD_Init(void) { __HAL_RCC_FSMC_CLK_ENABLE(); // 启用 FSMC 时钟 GPIO_InitTypeDef GPIO_InitStruct = {0}; /* FSMC NE4 连接到 PE7 */ __HAL_RCC_GPIOE_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF12_FSMC; // 设置为 FSMC 功能模式 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); } ``` #### 配置 FSMC NOR/SRAM Bank 接下来要配置 FSMC 的 NOR/SRAM Bank,这一步骤决定了如何访问连接到该银行的外部存储器或显示器: ```c static void MX_FSMC_NORSRAM1_Init(void){ FMC_NORSRAM_TimingTypeDef Timing = {0}; /** Perform the SRAM1 memory initialization sequence*/ hsram1.Instance = FMC_NORSRAM_DEVICE; hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE; /* Init the NORSRAM controller */ Timing.AddressSetupTime = 6; Timing.AddressHoldTime = 15; Timing.DataSetupTime = 8; Timing.BusTurnAroundDuration = 0; Timing.CLKDivision = 16; Timing.DataLatency = 17; Timing.AccessMode = FMC_ACCESS_MODE_A; if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK) { Error_Handler( ); } } ``` #### 编写简单的绘图函数 一旦完成了硬件层面的基础工作之后就可以编写一些基本图形绘制的功能来测试显示屏是否正常运作了。这里给出一个简单填充矩形区域颜色的例子: ```c void FillRectangle(uint16_t xStart,uint16_t yStart,uint16_t width,uint16_t height,uint16_t color){ uint16_t i,j; for(i=0;i<height;i++){ for(j=0;j<width;j++){ WritePixel(xStart+j,yStart+i,color); // 使用之前定义好的像素点写入方法 } } } // 写入单个像素的颜色值 void WritePixel(int16_t x,int16_t y,uint16_t color){ if((x >= 0)&&(y >= 0)&&(x < LCD_WIDTH)&&(y < LCD_HEIGHT)){ *(uint16_t*)(FramebufferBaseAddress+(y*LCD_WIDTH+x)*2)=color; } } ``` 上述代码片段展示了如何利用 FSMC 总线向外部设备发送命令序列以及传输图像数据的方法[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值