首先在明白操作LCD真正用到的引脚有:
1)数据或命令 RS
2)数据传输线: D0-D15
3)写信号: WR
4)读信号: RD
5)片选信号: CS

LCD的操作时序与SRAM控制类似,唯一不同的是是TFTCLD只有RS信号,没有地址信号,这里再次强调,SRAM有地址控制信号,而TFTLCD没有!原则上SRAM的地址信号对

TFTLCD没有什么作用,对TFTLCD来说我只需找到一个引脚,这个引脚用来控制RS(即是写命令还是写数据)即可。那既然SRAM中的地址线已经引出来了,那么我们就用呗

,“随便”选一根来用!那就选A10(对于STM32F1)或A6(对于STM32F4),那么我们怎样才能使它变高或变低呢?(就是如何才能对它写1或写0?)又因为它是地址线中

的某一根线,而对于TFTLCD来说,我们要使用的是SRAM中的A模式中的4区,也就是寻址的地址从0x6C00 0000 开始,到0x6CFF FFFF止,那么我们试着看看能不能从这些地

址中找到能满足某种条件的这么一个地址:使地址线A[0]–A[25]中的A[10]变为0?或使A[10]变为1?(这里只对STM32F1来说)当然能找到,而且还很多:只要在这25根

地址线上传输信号能满足A[10]这一位是0或是1就可啦,即:如果地址线上传输的数据是这种格式:0x0110 1100 XXXX XXXX XXXX X0XX XXXX XXXX,即bit10位为0也就是A

[10]为0!注意要从0x6C00 0000 开始不然就找到别的区里去啦!我们就可以拉低RS,就是传命令了;同理:只要满足这种格式:0x0110 1100 XXXX XXXX XXXX X1XX XXXX

XXXX即bit10位为1,也就是A[10]为1就是传数据了!于是我们就可以这样定义两个地址,一个用来传命令(含A[10]为0),一个用来传数据(含A[10]为1):

#define LCD_REG (u32)0x6C00 0000
#define LCD_RAM (u32)0x6C00 0400


为了让它们好看点,我们再去找这么一个地址:两个地址相邻,一个能让A[10]默认为0,而加1之后又使A[10]变成了1?有没有这么两个相邻的地址?当然有!它就是:

0x6C00 0000|0x00 07FE和0x6C00 0000|0x0000 07FF(注意最后一位的区别,于是我们就可以这么定义:

#define LCD_REG  (u32)0x6C00 0000|0x0000 07FE
#define LCD_RAM  (u32)0x6C00 0000|0x0000 07FF

但要注意,这两个定义只是定义了地址数据,如果要往这个地址上写数据时还要这样处理:
(uint16_t)LCD_REG = cmd;
(uint16_t)LCD_RAM = data;
这样写有点麻烦,还有点难懂,这时我们还可以这么定义:

#define LCD_REG __attribute__((at (0X6C0007FE)))
#define LCD_REG __attribute__((at(0X6C0007FF)))

这里用了关键字arrtibute来指定某一个变量的地址,这个地址正好在SRAM那里,所以往这个地址上写数据的时候CPU就会过内部的数据总线(AHB)将地址和数据一起传送给

FSMC(片上外设),FSMC以我们设定好的时序(就是FSMC的读或写时序)对外部存储设备或LCD设备等进行数据交换,从而达到控制外部设备的目的。
我们知道结构体成员在内存中都是相邻存储的,所以还可以将上边两个定义再优化一下:使它们变成一个结构体:

typedef struct
{u16 LCD_REG;u16 LCD_RAM;
} LCD_TypeDef;

然后再这样定义:

#define LCD_BASE        ((u32)(0x6C000000 | 0x000007FE))
#define LCD             ((LCD_TypeDef *) LCD_BASE)

这就是正点原子文档里边的用到的结构体!强制将LCD_BASE这个数据转换为结构体LCD_TypeDef的入口地址,然后将这个入口地址重新命名为LCD,LCD_REG正好就是

0X0x6C0007FE,LCD_RAM正好是0X6C0007FFF.为了一根信号线能够输出0或1,费了这般劲,不容易呀!我们往这个地址上写数据的时候就可以这么做:

LCD->LCD_REG = cmd;
LCD->LCD_RAM = data;

这样就变得好看多了!
这时,我想到OLED:
做过OLED实验的人都知道,IIC驱动的OLED它的片选地址是0x78,写命令指令0x00,写数据指令是0x40,大家看出其中规律了没有?看不出来?
好吧,我们把这俩个16进制的数据变成二进制:0x00就是:0000 0000, 0x40就是:0100 0000,到这里看出规律了没有?第6位是写命令或写数据位!如果不相信的话你可

心大胆地做一下实验,将两个数据更改一下,只要保证它的第6位正确,那么它就能正常工作!神奇吧?
而TFTLCD与OLED类似,都是数据线和地址线共用SRAM正好相反,数据线和地址线分开!但不影响TFTLCD呀,我们又不用地址线。
至于为什么要右移一位,其实不明白也没关系,刚才说了,我们又不用地址线,而花那么多时间精力去理解,我们也只是为了解决A[10]这一位能够让它准确地表达在RS上

!其实理解起来也很简单:
因为SRAM是以一个字节为一个地址的,而TFTLCD数据宽度是16位的,就是说它要用FSMC的两个地址上的数据,才能表达出它本身一个地址上的值!我们为了让它们能够重

新一一对应起来,只有将FSMC内的地址“重新编号“,将它们编号缩小一半,再简单一点来就是就将地址1和地址2合并成一个地址,并叫它为地址1,那宽度就是16位了对

吧?那这样的话HADDR的26根地址线(A[25:0])可以访问的字节元素个数变成了原来的1/2!但是它的宽度变成了原来的2倍(原来是8位,现在是16位)。因此才出现了当传

输线的宽度为16位时,我们要将HADDR右移一们以对应FSMC_A[24:0]。不防大胆地去设想:那要是32位呢?再移一位就好了。总之就是可访问的地址值要比原来的缩小一半

!那就是除以2了,除以2不就是往右边移一位嘛!要记住这一点:HADDR最终改变的是FSMC的地址。而FSMC的A[0]永远对应着外部设备的A[0]!HADDR就是AHB数据总线,它

上边的数据就是我们写入并要传给FSMC的数据!再次强调:在这里费了老半天劲,我们要的效果也仅仅是为了能够使A[10]能够准确地表达在RS这根命令/数据线上而已!
不相信?
我们再回到LCD_REG和LCDRAM这两人定义:

#define LCD_REG  (u32)0x6C00 0000|0x0000 07FE
#define LCD_RAM  (u32)0x6C00 0000|0x0000 07FF

其中0x00 07FE展开来就是:0000 0000 0000 0111 1111 1110。我们要写的本来是这个数据,但是经过FSMC传到TFTLCD的时候却变成这个:0000 0000 0000 0011 1111

1111,A[10]为0有没有?再加1A[10]就变成1,有没有?再深入一点去说就是HADDR访问的地址一定是SFMC上的偶地址!(这里是对于16位来说的),换一种说法吧,16位数

据地址宽度的外设与8位数据的地址MCU连接,那么你就得两个地址两个地址给我传,才能凑成16位,我(指16位)的地址0是你的(指8位)地址0,我的地址1却变成了你的地

址2了,我的地址2却变成了你的地址4.……你也许会问:那我8位地址8位地址地给你传行不行?然后再将两个地址上的数据合并成16位就成了你的地址上的数据了!这样

也行,某些设备也确实是这样做了,但是只能通过软件去干这件事,(通过先传高位字节,再传低位字节),硬件可不懂!再说了,放着那么多根地址线你不用?(28根!

),却去自找苦头吃?我跟我朋友说过这一件事,他开玩笑地说:“没错了,因为我比你长!我要访问你的地址1其实是访问了你的地址2!我要访问你的地址4其实是要访

问你的址8!”
不理解就PASS吧,没关系的,反正TFTLCD又不用这些地址线!大不了换个引脚当RS。

解决了地址偏移问题,那剩下的就和OLED没有太大的区别了,只是TFTLCD的内容丰富了点而已(多了RGB颜色),FSMC的存在就当做是为了给TFTLCD创造合适TFTLCD的某种

时序,或者可以把它理解成IIC或SPI都可以,(只不过FSMC是并口而已!)其它的应该也就没有什么了吧!
对于TFTLCD来说真正用到FSMC的只有两个结构体,一个是FSMC基本配置结构体:FSMC_NORSRAMInitTypeDef,另一个是读写时序结构体:FSMC_NORSRAMTimingInitTypeDef
由于一些外设本身的原因,导致读和写的速度不一样,对于TFTLCD,如果芯片是ILI9341,那么它的写速度将近是读速度的两倍之多,所以我们可以在FSMC的基本配置中将

读和写时序分开来设置,这样就是使能FSMC_NORSRAMInitTypeDef结构体成员:FSMC_ExtendedMode让它变成Enable,这样我们又要多配置另一个结构体数据了,分别是读

时序,写时序。
对于FSMC来说真正要配置的成员其实就那7个:

1)FSMC_Bank
2)FSMC_ExtendedMode
3)FSMC_MemoryDataWidth
4)FSMC_MemoryType
5)FSMC_WriteOperation
6)FSMC_ReadWriteTimingStruct
7)FSMC_WriteTimingStruct

其它的都是Disable就可以了!
理解了上边的内容,那么LCD的驱动应该问题不大了。

对于驱动TFTLCD,读这篇文章就够了!相关推荐

  1. VPP /什么是VPP?读这篇文章就够了

    目录 介绍 为什么称为向量处理? 用例示例:VPP作为vSwitch / vRouter VPP的主要特征 绩效期望 介绍 VPP平台是一个可扩展的框架,可提供开箱即用的生产质量交换机/路由器功能.它 ...

  2. Maven入门,读这篇文章就够了

    一年前,当我和小伙伴小龙一起做一个外包项目的时候,受到了严重的鄙视.我那时候还不知道 Maven,所以搭建项目用的还是最原始的方式,小龙不得已在导入项目的时候花了很长时间去下载项目依赖的开源类库. 出 ...

  3. 递归算法,读这篇文章或许更有启发

    递归是一种算法技巧,它允许在函数内部调用自己.递归算法通常用于解决分治问题,即将大问题分解为若干个小问题,然后递归地解决这些小问题.最后将所有小问题的答案合并得到大问题的答案.递归算法需要确定一个终止 ...

  4. 十年后2023年再读这篇文章,看看我将会怎么样?

    看到一篇文章不错[清华差生10年奋斗经历] ,写给将要工作的自己,十年后2023年再读这篇文章,看看我将会怎么样? 在2012年收关时刻,看到如此激励的文章,实在是我的幸运.文章讲述了所谓清华差生的奋 ...

  5. 十年后2023年再读这篇文章,看看我将会怎么样

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 看到一篇 ...

  6. 万字心得,PMP学习考试那些事儿,看这篇文章就够了

    声明:文章为原创,首发于知乎,链接:万字长文!PMP考试那些事儿,看这篇文章就够了 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/524966002 以下内 ...

  7. Android 8.0新特性(看这篇文章就够了)

    2019独角兽企业重金招聘Python工程师标准>>> 在刚结束不久的谷歌 I/O2017开发者大会上发布的第二个Android O(安卓8.0)开发者预览,并且向普通用户开放了第二 ...

  8. MySQL事务,这篇文章就够了

    原文链接:https://blog.ouyangsihai.cn/ >> MySQL事务,这篇文章就够了 在看这篇文章之前,我们回顾一下前面的几篇关于MySQL的系列文章,应该对你读下面的 ...

  9. Python-Excel 零基础学习xlwings,看这篇文章就够了

    零基础学习xlwings,看这篇文章就够了 | 一起大数据-技术文章心得 (17bigdata.com) 1.xlwings是什么 2.xlwings安装更新与卸载 3.xlwings详细使用 4.案 ...

最新文章

  1. bootstrap Table API和一些简单使用方法
  2. 不用等到2050年,现在已经有人跟机器人结婚了
  3. 机器学习入门--进阶资料和流程建议
  4. 最长重复子串(Rabin-Karp算法)
  5. loadView与viewDidLoad不同
  6. springboot定时任务
  7. 语言认知偏差_认知语言学可以教给开发人员什么
  8. 能行走如飞,会自己折叠:这个哈佛实验室有一群神奇的机器人
  9. Windows消息机制概述
  10. excel显著性检验_数据分析系列 10/32 | Excel方差分析之单因素方差分析
  11. airplay 协议开源资料整理
  12. 为什么更多APP开发者选择穿山甲作为游戏变现平台?
  13. thinkadmin模板渲染与赋值
  14. 关于编码问题的复制黏贴
  15. TL-BERT: A Novel Biomedical Relation Extraction Approach
  16. UV法测量cod原理及特点
  17. numpy.random.rand(d0,d1....,dn)和numpy.random.randint()
  18. 计算机健康小知识,日常生活养生小知识
  19. IIS 7.5 HTTP 错误 404.3 - Not Found错误的解决方法
  20. 【Windows】ping ip+端口

热门文章

  1. 小菜鸟带着梦想学chromium
  2. CE自带教程使用指南完整版过程(超详细)
  3. 湖南安全职院•美和易思举办第一届卓越项目发布会
  4. Vue 中利用 template标签遍历多维数组
  5. Java面试常见问题总结
  6. 如何参与Impala社区的讨论
  7. python秒表_使用Python创建秒表
  8. java 事件驱动原理_浅谈事件驱动机制
  9. 【D3.js实战】 品牌排名动态可视化
  10. MySQL笔试题整理(二)