• LCD驱动


    简介

    1、为什么可以把 TFTLCD 当成 SRAM 设备用

    • 首先我们了解下外部 SRAM的连接,外部 SRAM 的控制一般有:地址线(如 A0~ A18)、数据线(如 D0~D15)、写信号(WE)、读信号(OE)、片选信号(CS),如果 SRAM 支持字节控制,那么还有 UB/LB 信号
    • 而 TFTLCD的信号包括:RS(选择发送命令或者数据)、D0~ D15、WR(写)、RD(读)、CS(片选)、RST(复位) 和 BL 等
    • 其中真正在操作 LCD 的时候需要用到的就只有:RS、D0~D15、WR、RD 和 CS。
    • 其操作时序和 SRAM的控制完全类似,唯一不同就是 TFTLCD 有 RS 信号,但是没有地址信号。

    2、具体数据线的改变,导致能够使用

    • TFTLCD 通过 RS 信号来决定传送的数据是数据还是命令,本质上可以理解为一个地址信号,比如我们把 RS 接在 A0 上面,那么当 FSMC 控制器写地址 0 的时候,会使得 A0 变为 0, 对 TFTLCD 来说,就是写命令。而FSMC 写地址 1 的时候,A0 将会变为 1,对 TFTLCD 来说,就是写数据了。这样,就把数据和命令区分开了,他们其实就是对应 SRAM 操作的两个连续地址。
    • 当然 RS 也可以接在其他地址线上,探索者 STM32F4 开发板是把 RS 连接在 A6 上面的

    使用

    1、任何 LCD,使用流程都可以简单的用以上流程图表示。其中硬复位和初始化序列,只需要执行一次即可。而画点流程就是:设置坐标→写 GRAM 指令→写入颜色数据,然后在 LCD 上面,我们就可以看到对应的点显示我们写入的颜色了。读点流程为:设置坐标→读 GRAM 指令→读取颜色数据,这样就可以获取到对应点的颜色数据了。
    在这里插入图片描述
    2、实际操作

    • 首先在HAL库进行配置:选择片选信号为NE4,选择控制类型为LCD控制,此时就可以选将数据和命令控制线 映射到A6,然后设置DATA为16bit(因为使用了RGB565),最后设置好时序,和背光IO为PB15就可以了
    • 如何在使用过程中发送命令或者数据呢:直接在使A6变为1或者0的内存地址上写就可以了
    • 发送初始化命令啥的

    各种屏幕介绍

    视频
    1、显示器介绍

    • 常见的显示器有CRT显示器
    • LCD(Liquid Crystal Display):液晶显示器,所有像素点共用一个背光灯
    • LED点阵显示器
    • OLED(Organic Light Emitting Diode):有机发光二极管显示器

    2、LCD屏幕介绍

    • 液晶分子不能完全遮住光,因此不能显示纯黑
    • 液晶在温度低的时候相应会变慢,这也就是LCD的手机在冬天温度低的时候滑动手机会有拖影的现象
    • LCD更厚一点,OLED是有机物容易老化所以使用寿命是小于LCD的,容易烧屏
    • DC调光,直接控制电压控制那个大的灯的亮度,电压高灯就亮,没有频闪伤眼。
    • 由于背光的波长相当大一部分属于蓝光,蓝光伤眼
      在这里插入图片描述

    3、OLED

    • 对比度更好
    • OLED是有机物容易老化,使用寿命小于LCD的,容易烧屏
    • 由于没有背光层啥的,屏幕可以更薄
    • PWM调节控制亮度,频率低了容易造成频闪
      在这里插入图片描述

    显示器控制

    视频

    1、显示器基本参数

    • 像素:成像最小的点,一个显示单元;三个构成一个像素,如下图所示
    • 分辨率:1920×1080(前面是行,后面是列)
    • 色彩深度:一个像素用多少位表示;常见的有色深16bit(RGB565,红色通道用5位表示这样,一共可以显示2的16次方种颜色)和24bit(RGB888);还有RGB8888,其中有一位代表了透明度,即2的32次方
    • 显示器尺寸:用对角线的尺寸表示,用英寸(1英寸就是2.54cm)表示
    • 点距:两个相邻像素点之间的距离
      在这里插入图片描述

    2、显示器的接口技术

    • 使用信号转接板可以使用这四种,但是一般不这样,不划算。DP,HDMI;DVI,VGA这两个比较老,现在的笔记本基本都没了
    • 单片机常用的接口模式:MCU模式,RGB模式,SPI,串口

    在这里插入图片描述

    产品

    简介

    1、用的是正点原子提供的3.5寸TFTLCD驱动芯片用的是NT35310,电阻触摸屏。分辨率480×320,集成的触摸屏接口是SPI的;采用 RGB565 格式存储颜色数据,即16位颜色深度(我感觉16位数据并口,意思就是16位颜色)

    2、16位8080并口(通过FSMC模拟实现),数据线:

    • CS:TFTLCD 片选信号,;对应就是FSMC_NE4 做片选
    • WR:向 TFTLCD 写入数据
    • RD:从 TFTLCD 读取数据
    • D[15:0]:16 位双向数据线
    • RST:硬复位 TFTLCD(RST 信号线是直接接到 STM32F4 的复位脚上,并不由软件控制,这样可以省下来一个
      IO 口。)
    • RS:命令/数据标志(0,读写命令;1,读写数据)
    • 还需要一个IO口作为背光控制线

    使用简介

    • 使用基本就是先发送初始化信息进行初始化
    • 然后发送要写坐标的命令 之后发送坐标信息 (设置坐标)
    • 然后发送写值命令 然后写值也就是这个点的颜色

    配置

    HAL库配置

    STM32F4 的 FSMC 支持 8/16/32 位数据宽度,我们这里用到的 LCD 是 16 位宽度的,所以在设置的时候,选择 16 位宽就 OK 了
    在这里插入图片描述
    在这里插入图片描述
    配置背光PB15 上电默认输出高电平
    在这里插入图片描述

    基本参数与寄存器

    //LCD重要参数集
    typedef struct  
    {
       		 	 
    	uint16_t width;			//LCD 宽度
    	uint16_t height;			//LCD 高度d
    	uint16_t id;				//LCD ID
    	uint8_t  dir;			//横屏还是竖屏控制:0,竖屏;1,横屏。	
    	uint16_t	wramcmd;		//开始写gram指令
    	uint16_t setxcmd;		//设置x坐标指令
    	uint16_t setycmd;		//设置y坐标指令 
    }LcdDevArg; 	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    /************************ 基本参数与寄存器 *************************************/
    
    //管理LCD重要参数
    //默认为竖屏  就宽度和高度设置的不同
    LcdDevArg lcddev={
       
    	//参数
    	.dir=0,		//竖屏/横屏 
    	.width=320,
    	.height=480,
    	//命令
    	.wramcmd=0X2C,//开始写gram指令
    	.setxcmd=0X2A,//设置x坐标指令
    	.setycmd=0X2B,//y坐标命令  
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    关键函数(读写函数)

    //读写函数
     void LCD_WR_REG(volatile uint16_t regval);//写命令
     uint16_t LCD_RD_DATA(void);							 //读数据
     void LCD_WR_DATA(volatile uint16_t data); //写数据
    void LCD_WriteReg(uint16_t LCD_Reg,uint16_t LCD_RegValue);//先写寄存器再写值
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数据命令操作原理

    • 1、 用的是第4块,地址范围为0x6800 0000——6BFF FFFF
    • 2、我们把FSMC的A6地址线与 数据/命令 相连接 当A6为高电平时,数据线[15:0]被理解为数据
      反正当A6为低电平时 被理解为命令
    • 3、因此当我们需要写数据时,则使第6位地址为1;写命令时为0
    • 4、7E:0111 1110 此时第六位为1数据,但是由于STM32内部会右移一位对齐,则右移后第六位为0
    • 5、因此原地址为0 加1后就为数据了
    //LCD地址结构体
    typedef struct
    {
       
    	volatile uint16_t LCD_REG;//0 命令
    	volatile uint16_t LCD_RAM;//1 数据
    } LCD_TypeDef;
    
    
    /*  
    1、 用的是第4块,地址范围为0x6800 0000——6BFF FFFF
    2、我们把FSMC的A6地址线与 数据/命令 相连接  当A6为高电平时,数据线[15:0]被理解为数据
       反正当A6为低电平时 被理解为命令
    3、因此当我们需要写数据时,则使第6位地址为1;写命令时为0
    4、7E:0111 1110   此时第六位为1数据,但是由于STM32内部会右移一位对齐,则右移后第六位为0
    5、因此原地址为0 加1后就为数据了
    */
    #define LCD_BASE        ((uint32_t)(0x6C000000 | 0x0000007E))
    #define LCD             ((LCD_TypeDef *) LCD_BASE)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    实际操作:

    • 当我们在LCD->LCD_REG地址写入数据的时候,STM32会自动在数据线[15:0],输出相应数据。但此时LCD会将这段数据识别成命令
    • 当我们在LCD->LCD_RAM地址写入数据时,STM32会自动在数据线[15:0],输出相应数据。但此时LCD会将这段数据识别成数据
    • 同理读数据也是相同的,当我们在ram=LCD->LCD_RAM这段内存读数据时,STM32就会将从数据线[15:0]读到的数据读出。此时就是可以看成是LCD发送过来的数据
    //写寄存器 
    //regval:寄存器值
     void LCD_WR_REG(volatile uint16_t regval)
    {
          
    	regval=regval;		//使用-O2优化的时候,必须插入的延时
    	LCD->LCD_REG=regval;//写入要写的寄存器序号	 
    }
    //读LCD数据
    //返回值:读到的值 通常用在发送完寄存器 后读取返回的值,他返回的值是需要我们读的
     uint16_t LCD_RD_DATA(void)
    {
       
    	volatile uint16_t ram;			//防止被优化
    	ram=LCD->LCD_RAM;	//这里相当于 读一个内存地址(可以看成读一个变量 自动会生成读时序)
    	return ram;	 
    }	
    //写LCD数据
    //data:要写入的值
     void LCD_WR_DATA(volatile uint16_t data)
    {
       	  
    	data=data;			//使用-O2优化的时候,必须插入的延时
    	LCD->LCD_RAM=data;		 
    }
    
    //写寄存器 针对某个寄存器写值,先写寄存器序号,然后写入数据
    //LCD_Reg:寄存器地址
    //LCD_RegValue:要写入的数据
    void LCD_WriteReg(uint16_t LCD_Reg,uint16_t LCD_RegValue)
    {
       	
    	LCD->LCD_REG = LCD_Reg;		//写入要写的寄存器序号	 
    	LCD->LCD_RAM = LCD_RegValue;//写入数据	    		 
    }	  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    读写点函数

    void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos);//设置光标位置  用于读点
    void opt_delay(uint8_t i);
    
    //实际操作函数
    void LCD_Fast_DrawPoint(uint16_t x,uint16_t y,uint32_t color);//快速画点
    uint32_t LCD_ReadPoint(uint16_t x,uint16_t y);//读点
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    /************************ 读点与画点函数 *************************************/
    //快速画点
    //x,y:坐标
    //color:颜色
     void LCD_Fast_DrawPoint(uint16_t x,uint16_t y,uint32_t color)
    {
       	   
    		//设置坐标
    		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); 		 	 
    
    	//写点颜色
    	LCD->LCD_REG=lcddev.wramcmd; 
    	LCD->LCD_RAM=color; 
    }	 
    
    
    
    
    
    //当mdk -O1时间优化时需要设置
    //延时i
    void opt_delay(uint8_t i)
    {
       
    	while(i--);
    }
    //设置光标位置(对RGB屏无效)
    //Xpos:横坐标
    //Ypos:纵坐标
    void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
    {
       	 	    
    		LCD_WR_REG(lcddev.setxcmd); //发送设置x坐标命令
    		LCD_WR_DATA(Xpos>>8);LCD_WR_DATA(Xpos&0XFF); //先发送高8位 后发送低8位			 
    		LCD_WR_REG(lcddev.setycmd); 
    		LCD_WR_DATA(Ypos>>8);LCD_WR_DATA(Ypos&0XFF); 			
    } 	
    
    
    
    //读取个某点的颜色值	 
    //x,y:坐标
    //返回值:此点的颜色
    uint32_t LCD_ReadPoint(uint16_t x,uint16_t y)
    {
       
     	uint16_t r=0,g=0,b=0
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    一文详解DevExpress的HTML & CSS模板如何实现集合渲染
    2023江西财经大学计算机考研信息汇总
    12-js事件补充
    机器学习模型—决策树
    【名城优企游学】国轩高科,用数字化带来强劲发展动力
    【真题笔记】14年系统架构设计师要点总结
    中介子方程二十二
    [知识管理] Obsidian + Remotely Save插件 + 第三方存储/OSS(七牛云)的同步方案
    执法记录仪如何防抖
    pdf.js引入方式及初始化配置
  • 原文地址:https://blog.csdn.net/chengcao123/article/details/127318178