(42)STM32——LCD显示屏实验笔记

目录

学习目标

成果展示 

硬件知识

接口

并口时序

驱动时序

流程

RGB565

​编辑 指令

0XD3

0X36

0X2A

0X2B

0X2C

0X2E

FSMC

外设接口

读写时序

寄存器

FSMC_BCRx

FSMC_BTRx

FSMC_BWTRx

硬件连接

代码 

总结 


学习目标

        今天我们要讲解的是有关LCD显示屏的知识,其实这部分知识之前就学习过了,但是因为没有LCD显示屏,就没有做实验,所以我们今天就当是来复习一下之前的知识点了。主要的内容就是关于LCD的原理,与学会使用LCD。

成果展示 

(42)STM32——LCD显示屏实验笔记_第1张图片 

 

LCD显示屏

硬件知识

        TFT-LCD 即薄膜晶体管液晶显示器。其英文全称为:Thin Film Transistor-Liquid Crystal Display。TFT-LCD 与无源 TN-LCD、STN-LCD 的简单矩阵不同,它在液晶显示屏的每一个像素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD 也被叫做真彩液晶显示器。

(42)STM32——LCD显示屏实验笔记_第2张图片

(42)STM32——LCD显示屏实验笔记_第3张图片

接口

  • LCD_CS:LCD片选信号  
  • LCD_WR:LCD写信号  
  • LCD_RD:LCD读信号  
  • DB[17:1]:16位双向数据线  
  • LCD_RST:硬复位LCD信号  
  • LCD_RS:命令/数据标志(0:命令,1:数据)  
  • BL_CTR:背光控制信号    
  • T_MISO/T_MOSI/T_PEN/T_CS/T_CLK,触摸屏接口信号
     

注意:DB1~DB8,DB10~DB17,总是按顺序连接MCU的D0~D15

并口时序

        模块的 8080 并口读/写的过程为:

  • 先根据要写入/读取的数据类型,设置RS为高(数据)/低(命令),然后拉低片选,选中ILI9341,接着根据读数据/写数据置RD/WR为低。

        然后:

  1. 读数据:在RD的上升沿,读取数据线上的数据(D[15:0]);
  2. 写数据:在WR的上升沿,使数据写入到ILI9341里面;

(42)STM32——LCD显示屏实验笔记_第4张图片

驱动时序

(42)STM32——LCD显示屏实验笔记_第5张图片

(42)STM32——LCD显示屏实验笔记_第6张图片

以下几个重点的时序值得我们去注意一下,因为与我们的读写操作有关:

  • 读ID低电平脉宽(trdl)
  • 读ID高电平脉宽(trdh)
  • 读FM低电平脉宽(trdlfm)
  • 读FM高电平脉宽(trdhfm)
  • 写控制低电平脉宽(twrl)
  • 写控制高电平脉宽(trwh)

注意:ID指LCD的ID号,FM指帧缓存,即:GRAM。

流程

(42)STM32——LCD显示屏实验笔记_第7张图片

        硬复位的话,我们是连接在复位按键上的,所以就省去了一个IO口;然后是初始化序列,这个一般是厂家提供的,不需要我们自己去写,然后设置一下坐标,就可以写/读GRAM指令了,这就是一个基本的驱动流程。

RGB565

        RGB565其实就是将一个16位数据的高5位编码为红色,后6位编码为绿色,低5位编码为蓝色。 

        比如:0XF800为红色(D15~D11五个位都是1显示红色,其它位都是0没有颜色)

(42)STM32——LCD显示屏实验笔记_第8张图片 指令

        ILI9341所有指令都是8位的(高8位无效),且参数除了读写GRAM的时候是16位,其它操作参数都是8位。

        ILI9341的指令很多,我们重点讲解下面6条指令:0XD3   0X36   0X2B   0X2A   0X2C   0X2E。 

0XD3

        0XD3指令:读ID4指令,用于读取LCD控制器的ID。因此,同一个代码,可以根据ID的不同,执行不同的LCD驱动初始化,以兼容不同的LCD屏幕。

        第一个参数是无效的,然后第二个是0X,第三个返回93,第四个返回41,对于不同的型号,就会返回不同的值,来达到兼容的效果。

(42)STM32——LCD显示屏实验笔记_第9张图片

0X36

        0X36指令:存储访问控制指令,控制ILI9341存储器的读写方向,即在连续写GRAM的时候,可以控制GRAM指针的增长方向,从而控制显示方式(读GRAM同此)。 

(42)STM32——LCD显示屏实验笔记_第10张图片

(42)STM32——LCD显示屏实验笔记_第11张图片

0X2A

        列地址指令,在从左到右,从上到下(默认)的扫描方式下,该指令可用于设置横坐标(X坐标)

(42)STM32——LCD显示屏实验笔记_第12张图片

        在默认扫描方式时,该指令用于设置X坐标,该指令带有4个参数,实际上是2个坐标值:SC和EC,即列地址的起始值和结束值,SC必须小于等于EC,且0<=SC/EC<=239(4.3寸屏幕不一样)。一般在设置X坐标的时候,我们只需带两个参数即可,也就是设置SC即可,因为如果EC没有变化,我们只需设置一次即可,从而提高速度。

0X2B

        0X2B指令:页地址设置指令,在从左到右,从上到下(默认)扫描方式下,该指令可用于设置纵坐标(Y坐标)

(42)STM32——LCD显示屏实验笔记_第13张图片

        在默认扫描方式时,该指令用于设置 y 坐标,该指令带有 4 个参数,实际上是 2 个坐标值:SP 和 EP,即页地址的起始值和结束值,SP 必须小于等于 EP,且 0≤SP/EP≤319。一般在设置 y 坐标的时候,我们只需要带 2 个参数即可,也就是设置 SP 即可,因为如果 EP 没有变化,我们只需要设置一次即可,从而提高速度。

0X2C

        0X2C,该指令是写 GRAM 指令,在发送该指令之后,我们便可以往 LCD 的 GRAM 里面写入颜色数据了,该指令支持连续写(地址自动递增)。

(42)STM32——LCD显示屏实验笔记_第14张图片

        从上表可知,在收到指令 0X2C 之后,数据有效位宽变为 16 位,我们可以连续写入 LCD GRAM 值,而 GRAM 的地址将根据 MY/MX/MV 设置的扫描方向进行自增。例如:假设设置的是从左到右,从上到下的扫描方式,那么设置好起始坐标(通过 SC,SP 设置)后,每写入一个颜色值,GRAM 地址将会自动自增 1(SC++),如果碰到 EC,则回到 SC,同时 SP++,一直到坐标:EC,EP 结束,其间无需再次设置的坐标,从而大大提高写入速度。

0X2E

        读GRAM指令,用于读取ILI9341的显存(GRAM),同时0X2C指令支持连续读(地址自动递增)。

(42)STM32——LCD显示屏实验笔记_第15张图片

        该指令用于读取 GRAMILI9341 在收到该指令后,第一次输出的是 dummy 数据,也就是无效的数据,第二次开始,读取到的才是有效的 GRAM 数据(从坐标:SC,SP 开始),输出规律为:每个颜色分量占 8 个位,一次输出 2 个颜色分量。比如:第一次输出是 R1G1,随后的规律为:B1R2->G2B2->R3G3->B3R4->G4B4->R5G5... 以此类推。如果我们只需要读取一个点的颜色值,那么只需要接收到参数 3 即可,如果要连续读取(利用 GRAM地址自增,方法同上),那么就按照上述规律去接收颜色数据。

FSMC

        FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和16位PC存储器卡连接,STM32的FSMC接口支持包括SRAM、NAND FLASH、NOR FLASHSH和PSRAM等存储器(不支持SD RAM,只有429、439支持,407、103不支持)。FSMC的框图如下图所示:

(42)STM32——LCD显示屏实验笔记_第16张图片

        FSMC驱动外部SRAM时,外部SRAM的控制一般有:地址线(如A0~A25)、数据线(如D0~D15)、写信号(WE,即WR)、读信号(OE,即RD)、片选信号(CS),如果SRAM支持字节控制,还有UB/LB信号。

        TFTLCD的信号包括:RS、D0~D15、WR、RD、CS、RST和BL等,其中真正在操作LCD的时候需要用到的只有:RS、D0~D15、WR、RD和CS。其操作时序和SRAM的控制完全类似,唯一不同的就是TFTLCD有RS信号,但是没有地址信号。

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

        因此可以把TFTLCD当成一个SRAM来用(将TFTLCD的RS连接到地址线的时候可以当作SRAM),只不过这个SRAM有2个地址,这就是FSMC可以驱动LCD的原理。

外设接口

        STM32的FSMC支持8/16/32位数据宽度。FSMC的外部设备地址映像,STM32的FSMC将外部存储器划分为固定大小为256M字节的四个存储块。

(42)STM32——LCD显示屏实验笔记_第17张图片

这个我们来简单理解一下,8位相当于一个字节,而每次加8刚好能读出地址,但是16位就相当于两个字节,每次加2,所以需要除2才能读出正确读数。

(42)STM32——LCD显示屏实验笔记_第18张图片 

读写时序

(42)STM32——LCD显示屏实验笔记_第19张图片

(42)STM32——LCD显示屏实验笔记_第20张图片 

寄存器

FSMC_BCRx

(42)STM32——LCD显示屏实验笔记_第21张图片

FSMC_BTRx

(42)STM32——LCD显示屏实验笔记_第22张图片

FSMC_BWTRx

(42)STM32——LCD显示屏实验笔记_第23张图片

FSMC_BCRx 和 FSMC_BTRx,组合成 BTCR[8]寄存器组,他们的对应关系如下:

  1. BTCR[0]对应 FSMC_BCR1,BTCR[1]对应 FSMC_BTR1
  2. BTCR[2]对应 FSMC_BCR2,BTCR[3]对应 FSMC_BTR2
  3. BTCR[4]对应 FSMC_BCR3,BTCR[5]对应 FSMC_BTR3
  4. BTCR[6]对应 FSMC_BCR4,BTCR[7]对应 FSMC_BTR4

FSMC_BWTRx 则组合成 BWTR[7],他们的对应关系如下:

  1. BWTR[0]对应 FSMC_BWTR1,BWTR[2]对应 FSMC_BWTR2,
  2. BWTR[4]对应 FSMC_BWTR3,BWTR[6]对应 FSMC_BWTR4,

BWTR[1]、BWTR[3]和 BWTR[5]保留,没有用到。

硬件连接

(42)STM32——LCD显示屏实验笔记_第24张图片

  • LCD_BL(背光控制)对应 PB0;
  • LCD_CS 对应 PG12 即 FSMC_NE4;
  • LCD _RS 对应 PF12 即 FSMC_A6;
  • LCD _WR 对应 PD5 即 FSMC_NWE;
  • LCD _RD 对应 PD4 即 FSMC_NOE;
  • LCD _D[15:0]则直接连接在 FSMC_D15~FSMC_D0;

代码 

        代码太多了,就简单介绍一下FSMC的配置。

vu32 i=0;
	
  GPIO_InitTypeDef  GPIO_InitStructure;
	FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  readWriteTiming; 
	FSMC_NORSRAMTimingInitTypeDef  writeTiming;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);//使能PD,PE,PF,PG时钟  
  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能FSMC时钟  
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PB15 推挽输出,控制背光
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 //PB15 推挽输出,控制背光
	
  GPIO_InitStructure.GPIO_Pin = (3<<0)|(3<<4)|(7<<8)|(3<<14);//PD0,1,4,5,8,9,10,14,15 AF OUT
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化  
	
  GPIO_InitStructure.GPIO_Pin = (0X1FF<<7);//PE7~15,AF OUT
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化  

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化  

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化 

  GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);//PD1,AF12
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC); 
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC); 
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);//PD15,AF12
 
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC);//PE7,AF12
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC);
  GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);//PE15,AF12
 
  GPIO_PinAFConfig(GPIOF,GPIO_PinSource12,GPIO_AF_FSMC);//PF12,AF12
  GPIO_PinAFConfig(GPIOG,GPIO_PinSource12,GPIO_AF_FSMC);


  readWriteTiming.FSMC_AddressSetupTime = 0XF;	 //地址建立时间(ADDSET)为16个HCLK 1/168M=6ns*16=96ns	
  readWriteTiming.FSMC_AddressHoldTime = 0x00;	 //地址保持时间(ADDHLD)模式A未用到	
  readWriteTiming.FSMC_DataSetupTime = 60;			//数据保存时间为60个HCLK	=6*60=360ns
  readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
  readWriteTiming.FSMC_CLKDivision = 0x00;
  readWriteTiming.FSMC_DataLatency = 0x00;
  readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;	 //模式A 
    

	writeTiming.FSMC_AddressSetupTime =3;	      //地址建立时间(ADDSET)为3个HCLK =18ns ,9
  writeTiming.FSMC_AddressHoldTime = 0x00;	 //地址保持时间(A		
  writeTiming.FSMC_DataSetupTime = 2;		 //数据保存时间为6ns*3个HCLK=18ns,8
  writeTiming.FSMC_BusTurnAroundDuration = 0x00;
  writeTiming.FSMC_CLKDivision = 0x00;
  writeTiming.FSMC_DataLatency = 0x00;
  writeTiming.FSMC_AccessMode = FSMC_AccessMode_A;	 //模式A 

 
  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//  这里我们使用NE4 ,也就对应BTCR[6],[7]。
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 不复用数据地址
  FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM;  //SRAM   
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit   
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable,突发访问模式禁止; 
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; // 下面这些是成组模式和同步模式才用的
	FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable; 
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;   
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;  
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;	//  存储器写使能
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;   
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; // 读写使用不同的时序
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; 
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //读写时序
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming;  //写时序

  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  //初始化FSMC配置

  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);  // 使能BANK1 

总结 

         这个东西,个人认为会用就行,原理部分稍稍了解一下,能熟练运用就行。

你可能感兴趣的:(STM32笔记,stm32,单片机,arm)