stm32专题二十一:FSMC模拟8080时序

       ILI9341的8080通讯接口时序可以由STM32使用普通 I/O 接口进行模拟,但这样效率太低,STM32 提供了一种特别的控制方法,使用FSMC接口实现8080时序。

       由于 FSMC 外设可以用于控制扩展的外部存储器,而 MCU 对液晶屏的操作实际上就是把显示数据写入到显存中,与控制SRAM 存储器非常类似,且 8080 接口的通讯时序完全可以使用 FSMC 外设产生,因而非常适合使用 FSMC控制液晶屏。

FSMC结构框图:

stm32专题二十一:FSMC模拟8080时序_第1张图片

LCD — 液晶显示:

stm32专题二十一:FSMC模拟8080时序_第2张图片

stm32专题二十一:FSMC模拟8080时序_第3张图片

NADV引脚是专门拥堵地址 / 数据线复用时做锁存信号,如下。当我们不需要地址 / 数据线复用时,NADV就不用管。

stm32专题二十一:FSMC模拟8080时序_第4张图片

NADV由以下寄存器位来配置:

液晶屏使用模式B的写操作时序:

stm32专题二十一:FSMC模拟8080时序_第5张图片

模式B读操作时序:

stm32专题二十一:FSMC模拟8080时序_第6张图片

根据 STM32 对寻址空间的地址映射,地址 0x6000 0000 ~0x9FFF FFFF 是映射到外部存储器的,而其中的 0x6000 0000 ~0x6FFF FFFF 则是分配给 NOR FLASH、PSRAM这类可直接寻址的器件。
当 FSMC 外设被配置成正常工作,并且外部接了 NOR FLASH 时,若向 0x60000000地址写入数据如 0xABCD,FSMC 会自动在各信号线上产生相应的电平信号,写入数据。FSMC 会控制片选信号 NE1 选择相应的 NOR 芯片,然后使用地址线 A[25:0]输出0x60000000,在 NWE 写使能信号线上发出低电平的写使能信号,而要写入的数据信号0xABCD 则从数据线 D[15:0]输出,然后数据就被保存到 NOR FLASH 中了。

使用FSMC模拟8080时序:

stm32专题二十一:FSMC模拟8080时序_第7张图片

stm32专题二十一:FSMC模拟8080时序_第8张图片

stm32专题二十一:FSMC模拟8080时序_第9张图片

一个非常重要的问题:就是地址对齐。

回想之前在SRAM中使用到的一个函数:

  /* 向整个SRAM写入数据  16位 */
  for (counter = 0; counter < IS62WV51216_SIZE/2; counter++)
  {
    *(__IO uint16_t*) (Bank1_SRAM3_ADDR + 2*counter) = (uint16_t)(uhWritedata_16b + counter);
  }

这个函数能够正常运行,没有问题。但是,值得注意的是,SRAM的数据线为16位,也就是说每个地址对应2个字节。这里在代码中直接写的是Bank1_SRAM3_ADDR + 2*counter,那么就会递增两个地址(4字节),是不是出了问题??应该只递增1地址才对啊?但是,无论是这个代码 or 下面的代码,都能够正确运行,非常奇怪。

/**
  * @brief  以“字”为单位向sdram写入数据 
  * @param  pBuffer: 指向数据的指针 
  * @param  uwWriteAddress: 要写入的SRAM内部地址
  * @param  uwBufferSize: 要写入数据大小
  * @retval None.
  */
void SRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize)
{
  __IO uint32_t write_pointer = (uint32_t)uwWriteAddress;
 

  /* 循环写入数据 */
  for (; uwBufferSize != 0; uwBufferSize--) 
  {
    /* 发送数据到SRAM */
    *(uint32_t *) (Bank1_SRAM3_ADDR + write_pointer) = *pBuffer++;

    /* 地址自增*/
    write_pointer += 4;
  }
}

这里竟然地址递增了4,应该会跳过8字节,但程序依然正常运行。问题出在这里:

stm32专题二十一:FSMC模拟8080时序_第10张图片

这里感觉很不好理解,简单地分析如下:

对于16位SRAM,FSMC地址线要向右移一位(非常重要)。

以0x6800  0000这个地址为例,它分解成二进制是0110 1000 0000 0000 0000 0000 0000 0000,由于一个BANK是64M的地址空间,而2^25=64M,故0x6800 0000的位[25:0]是FSMC向外部SRAM传递的真实地址,对于0x6800 0000,FSMC向外部SRAM发的地址是位[25:0],即00 0000 0000 0000 0000 0000 0000。

同理,对于0x6800 0002,FSMC向外部SRAM发送的地址是00 00000000 0000 0000 0000 0010。若FSMC不自动右移一位,这个地址明显发错了,因为期望读取的SRAM地址为0x0000 0001中的数据。

为了解决这一问题,当在初始化FSMC时,若选择外部SRAM为16位,则FSMC在向外部SRAM发地址时,会自动右移一位,例如刚才的0x6800 0002,FSMC在向外部发SRAM地址时,00 0000 0000 0000 0000 0000 0010会自动右移一位,变成00 0000 00000000 0000 0000 0001,即0x0000 0001,该地址正好是期望的外部SRAM地址。接着,外部SRAM从地址为0x0000 0001中取出16位数据传送给FSMC,由FSMC将这个16位数据保存在以映射地址0x6800 0002起始的两个8位存储单元中。

stm32专题二十一:FSMC模拟8080时序_第11张图片

地址映射如下:

stm32专题二十一:FSMC模拟8080时序_第12张图片

这样的话,当16位数据宽度时,地址的问题解决了,还有一个问题,是往高字节写入还是低字节写入呢?

这也就是NBL0和NBL1的作用了,如果你要进行字节操作 :
如stm32发送地址0x0001读取一个字节。右移一位对应的是sram地址0x0000处的16位数据, FSMC会根据A0(最后一根地址线)来控制NBL0和NBL1。当A0 = 1时,读取高字节数据(仅NBL1有效);A0 = 0时,读取低字节数据仅NBL0有效),当进行16位读写时,NBL0和NBL1都有效。

**********************************************************************************************************************************************

经过了上面的分析,再来重新观察数据的写入过程:

当地址为0x6800  0000,会访问到SRAM的第0个16位地址,而此时A0 = 0(低字节有效),实际会访问的是16位 0地址的低字节;当地址为0x6800  0001时,A0 = 1,访问16位 0地址的高字节。依次。

因此,想让地址线的最后一位产生0或1,应该在前一位做出改变(stm32会自动右移):

stm32专题二十一:FSMC模拟8080时序_第13张图片

结论:

本工程中使用 FSMC_A16 地址线作为命令/数据选择线 RS 信号,所以在地址范围内,再选择出使得 FSMC_A16 输出高电平的地址,即可控制表示数据,选择出使得FSMC_A16输出低电平的地址,即可控制表示命令。

要使 FSMC_A16 地址线为高电平,实质是访问内部 HADDR 地址的第(16+1)位为1 即可:

使用 0X6000 0000~0X63FF FFFF内的任意地址,作如下运算:
       使 FSMC_A16地址线为高电平:0X6000 0000 |= (1<<(16+1)) = 0x6002 0000
要使 FSMC_A16 地址线为低电平,实质是访问内部 HADDR 地址的第(16+1)位为0 即可:

使用 0X6000 0000~0X63FF FFFF内的任意地址,作如下运算:
       使 FSMC_A16地址线为低电平: 0X6000 0000 &= ~ (1<<(16+1)) = 0x6000 0000

*************************************************************************************************************************************************

根据最终的计算结果,总结如下:当 STM32 访问内部的 0x6002 0000 地址时,FSMC自动输出时序,且使得与液晶屏的数据/命令选择线 RS(即 D/CX)相连的 FSMC_A16 输出高电平,使得液晶屏会把传输过程理解为数据传输;     类似地,当 STM32 访问内部的 0X6000 0000 地址时,FSMC 自动输出时序,且使得与液晶屏的数据/命令选择线 RS(即 D/CX)相连的 FSMC_A16输出低电平,使得液晶屏会把传输过程理解为命令传输。

使用这两个地址发送命令和数据:

stm32专题二十一:FSMC模拟8080时序_第14张图片

stm32专题二十一:FSMC模拟8080时序_第15张图片

 

你可能感兴趣的:(stm32专栏)