STM32F4——TFT-LCD原理及FSMC
来源:互联网 发布:大数据 应用 编辑:程序博客网 时间:2024/05/22 12:55
TFT-LCD
一、简介:
TFT-LCD即薄膜晶体管液晶显示器,依据其尺寸、分辨率和驱动芯片的不同有很多分类,下边会依据2.8寸320X240分辨率以ILI9341芯片驱动的TFT-LCD做相关介绍。
二、接口:
模块采用16位并方式与外部连接,其相关接口图及信号线功能如下:
CS:TFTLCD片选信号。WR:向TFTLCD写数据。RD:从TFTLCD读取数据。D[15:0]:16位数据线。RS:命令/数据标示(0,读写命令;1,读写数据)。
三、驱动时序:
对于写时序:CS拉低做片选,RS表示是要写数据还是要写命令,在WR信号线的上升沿获取数据线D[0:15]上的数据,在写时序上RD信号线总是处于高电平。对于读时序同理。
四、驱动流程:
对于LCD的驱动流程可由下图表示:
首先通过LCD_RST引脚做复位,再进行初始化序列,由于本人现阶段水平有限,先不去研究相关初始化序列,所以就直接运用LCD商家给出的初始化序列代码。无论是读写指令,都需要设置好坐标,再做出读写GRAM的相关指令。在随后涉及到颜色数据的相关处理,下边就针对颜色数据做一下相关说明。
对于颜色的设定也有多种格式,在这里只是针对RGB565颜色格式做说明。RGB565这样看(Red)[5位](Green)[6位](Blue)[5位],组成16位颜色深度。
五、指令:
对于ILI9341的指令有很多,下边对ILI9341驱动芯片的个别指令做相关说明:1、0XD3:该指令用于读取芯片ID。由此可以依据不同的LCD做相关初始化,做到更好的兼容。2、OX36:存储器访问控制指令,可以在读写数据过程中控制GRAM指针的增长方向,简单说明就是控制像素的扫描方式。3、0X2A:用于设置列地址,也就是在从左到右从上到下的扫描方式下,设置x坐标。即用于设置x坐标的范围。4、0X2B:与OX2A类似,该指令用于设置y坐标。需要说明的是在OX2A和OX2B的控制下就可以在屏幕上开窗显示了。5、0X2C:该指令用于向GRAM中写入颜色数据。6、0X2E:读取GRAM中的颜色数据。
FSMC
一、简介:
FSMC即灵活静态存储控制器,用于静态存储器的扩展。对于TFT-LCD显示中将LCD当做一个SRAM来进行操作,下边会有所介绍。
二、框图结构:
对于FSMC的引脚已经在框图中有所标注,对于下边的存储块的图是FSMC对其存储器的管理方式,每个存储块大小为256M,由于LCD是要当做SRAM来处理的,那么就要有存储块1的扩展来使得LCD工作。存储块1由28根地址线(HADDR[27:0])寻址,由于每个存储块分为四个区,HADDR[27:26]用于做相关区域选择。注意:由于在这里LCD作为一个16位宽的存储器,而内部的存储是以字节为单位的,则需要HADDR[25:1]对应到FSMC[24:0],即相当于内部的存储地址除以2(右移1位),从而与外部地址对应上。
三、相关寄存器:
1、FSMC_BCRx:SRAM/NOR闪存片选控制寄存器。
相关位:EXTMOD:控制是否允许读写使用不同的时序。WREN:写使能。MWID[1:0]:设置数据总线宽。MTYP[1:0]:配置存储器类型。MBKEN:存储块使能。
2、FSMC_BTRx:SRAM/NOR闪存片选时序寄存器。
相关位:ACCMOD[1:0]:设置访问模式。DATAST[7:0]:数据保持时间。ADDSET[3:0]:地址建立时间设置。
3、FSMC_BWTRx:SRAM/NOR闪存写时序控制器。
相位位同FSMC_BTRx对应位相同。
TFT-LCD显示部分代码参考
一、LCD地址结构体分析
//LCD地址结构体typedef struct{u16 LCD_REG;u16 LCD_RAM;} LCD_TypeDef;//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A6作为数据命令区分线 //注意设置时STM32内部会右移一位对其! 111 1110=0X7E #define LCD_BASE ((u32)(0x6C000000 | 0x0000007E))#define LCD ((LCD_TypeDef *) LCD_BASE)
由于存储块1的第4区的起始地址为0X6C000000,又由于A6作为数据和命令的区分线,根据代码可得:LCD是将LCD_BASE地址经过强制类型转换,装换为结构体类型,由此知:LCD_REG表示的为写命令地址,LCD_RAM表示为写数据地址。
二、LCD重要参数结构体
//LCD重要参数集typedef struct { u16 width;//LCD 宽度u16 height;//LCD 高度u16 id;//LCD IDu8 dir;//横屏还是竖屏控制:0,竖屏;1,横屏。u16 wramcmd; //开始写gram指令u16 setxcmd; //设置x坐标指令u16 setycmd; //设置y坐标指令 }_lcd_dev;
三、读写寄存器或数据函数(底层接口函数)
//写寄存器函数//regval:寄存器值void LCD_WR_REG(vu16 regval){ regval=regval;//使用-O2优化的时候,必须插入的延时LCD->LCD_REG=regval; //写入要写的寄存器序号 }//写LCD数据//data:要写入的值void LCD_WR_DATA(vu16 data){ data=data;//使用-O2优化的时候,必须插入的延时LCD->LCD_RAM=data; }//读LCD数据//返回值:读到的值u16 LCD_RD_DATA(void){vu16 ram;//防止被优化ram=LCD->LCD_RAM;return ram; } //写寄存器//LCD_Reg:寄存器地址//LCD_RegValue:要写入的数据void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue){LCD->LCD_REG = LCD_Reg;//写入要写的寄存器序号 LCD->LCD_RAM = LCD_RegValue;//写入数据 } //读寄存器//LCD_Reg:寄存器地址//返回值:读到的数据u16 LCD_ReadReg(u16 LCD_Reg){ LCD_WR_REG(LCD_Reg);//写入要读的寄存器序号delay_us(5); return LCD_RD_DATA();//返回读到的值} //开始写GRAMvoid LCD_WriteRAM_Prepare(void){ LCD->LCD_REG=lcddev.wramcmd; } //LCD写GRAM//RGB_Code:颜色值void LCD_WriteRAM(u16 RGB_Code){ LCD->LCD_RAM = RGB_Code;//写十六位GRAM}
四、设置坐标(根据不同的芯片选择不同的设置方式)
//设置光标位置//Xpos:横坐标//Ypos:纵坐标void LCD_SetCursor(u16 Xpos, u16 Ypos){ if(lcddev.id==0X9341||lcddev.id==0X5310){ LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(Ypos>>8);LCD_WR_DATA(Ypos&0XFF); }else if(lcddev.id==0X6804){if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏时处理LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(Ypos>>8);LCD_WR_DATA(Ypos&0XFF); }else if(lcddev.id==0X1963){ if(lcddev.dir==0)//x坐标需要变换{Xpos=lcddev.width-1-Xpos;LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(0);LCD_WR_DATA(0); LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF); }else{LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF); LCD_WR_DATA((lcddev.width-1)>>8);LCD_WR_DATA((lcddev.width-1)&0XFF); }LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(Ypos>>8);LCD_WR_DATA(Ypos&0XFF); LCD_WR_DATA((lcddev.height-1)>>8);LCD_WR_DATA((lcddev.height-1)&0XFF); }else if(lcddev.id==0X5510){LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(Xpos>>8); LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(Xpos&0XFF); LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(Ypos>>8); LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(Ypos&0XFF);}else{if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏其实就是调转x,y坐标LCD_WriteReg(lcddev.setxcmd, Xpos);LCD_WriteReg(lcddev.setycmd, Ypos);} }
五、画点函数
//画点//x,y:坐标//POINT_COLOR:此点的颜色void LCD_DrawPoint(u16 x,u16 y){LCD_SetCursor(x,y);//设置光标位置 LCD_WriteRAM_Prepare();//开始写入GRAMLCD->LCD_RAM=POINT_COLOR; }//快速画点//x,y:坐标//color:颜色void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color){ if(lcddev.id==0X9341||lcddev.id==0X5310){LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF); }else if(lcddev.id==0X5510){LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(x>>8); LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(x&0XFF); LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(y>>8); LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(y&0XFF); }else if(lcddev.id==0X1963){if(lcddev.dir==0)x=lcddev.width-1-x;LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF); LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF); LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF); }else if(lcddev.id==0X6804){ if(lcddev.dir==1)x=lcddev.width-1-x;//横屏时处理LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF); }else{ if(lcddev.dir==1)x=lcddev.width-1-x;//横屏其实就是调转x,y坐标LCD_WriteReg(lcddev.setxcmd,x);LCD_WriteReg(lcddev.setycmd,y);} LCD->LCD_REG=lcddev.wramcmd; LCD->LCD_RAM=color; }
两个函数一个是调用函数,一个是直接快速设置。功能相同。
六、读点函数
//读取个某点的颜色值 //x,y:坐标//返回值:此点的颜色u16 LCD_ReadPoint(u16 x,u16 y){ u16 r=0,g=0,b=0;if(x>=lcddev.width||y>=lcddev.height)return 0;//超过了范围,直接返回 LCD_SetCursor(x,y); if(lcddev.id==0X9341||lcddev.id==0X6804||lcddev.id==0X5310||lcddev.id==0X1963)LCD_WR_REG(0X2E);//9341/6804/3510/1963 发送读GRAM指令else if(lcddev.id==0X5510)LCD_WR_REG(0X2E00);//5510 发送读GRAM指令else LCD_WR_REG(0X22); //其他IC发送读GRAM指令if(lcddev.id==0X9320)opt_delay(2);//FOR 9320,延时2us r=LCD_RD_DATA();//dummy Read if(lcddev.id==0X1963)return r;//1963直接读就可以 opt_delay(2); r=LCD_RD_DATA(); //实际坐标颜色 if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)//9341/NT35310/NT35510要分2次读出 {opt_delay(2); b=LCD_RD_DATA(); g=r&0XFF;//对于9341/5310/5510,第一次读取的是RG的值,R在前,G在后,各占8位g<<=8;} if(lcddev.id==0X9325||lcddev.id==0X4535||lcddev.id==0X4531||lcddev.id==0XB505||lcddev.id==0XC505)return r;//这几种IC直接返回颜色值else if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));//ILI9341/NT35310/NT35510需要公式转换一下else return LCD_BGR2RGB(r);//其他IC}
这是TFT-LCD显示基本的一些函数,这是有关TFT-LCD的初步认识,后边还会继续学习和认识有关其操作和应用。
- STM32F4——TFT-LCD原理及FSMC
- STM32F4——TFT-LCD原理及FSMC
- STM32 FSMC TFT LCD
- STM32-TFT-LCD触摸屏以及FSMC基础
- FSMC与LCD连接原理
- FSMC ON STM32F407 USE FOR TFT-LCD DRIVER ILI9325
- STM32F4 FSMC
- stm32f4 FSMC
- STM32F4学习(六)——LCD显示
- STM32 FSMC LCD 液晶的驱动—ILI9320
- STM32 FSMC LCD 液晶的驱动—ILI9320
- FSMC+LCD
- TFT LCD液晶显示器的驱动原理
- TFT LCD液晶显示器的驱动原理
- TFT-LCD液晶显示器的工作原理
- TFT LCD
- TFT LCD
- STM32F4 FSMC TFTLCD
- 8天玩转并行开发——第六天 异步编程模型
- 使用Java获取IP地址实例
- 拼音输入法(MPinyinIME)
- linux系统调用分析
- HDU1021 - Fibonacci Again (水题 找规律)
- STM32F4——TFT-LCD原理及FSMC
- Objective-C学习笔记十:继承二
- mongoDB 3.0安全权限访问控制
- MFC友好信息提示类
- spring jdbc的使用
- 激活硬盘被关闭的DMA模式
- 第三篇 (面向对象)①: 关于Java的面向对象特性
- Objective-C学习笔记11:多态和动态类型
- iOS 设置导航栏 Navigationbar相关信息