stm32 2.8寸TFTLCD

一,硬件部分

 

 二,1680并口驱动简介

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

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

1.读数据:RD的上升沿, 读取数据线上的数据D[15:0];

2.写数据:WR的上升沿,使数据写入到ILI9341里面

 三,驱动流程

 实验版中RST与MCU相通,即按下复位即可。(硬复位)

初始化序列:厂家提供。

四,RGB565

模块对外接口采用16口,颜色深度为16位,格式为RGB565,关系如下图:

 例如0xf800,为R全1,其他全0,为纯红色。

五,ILI9341指令格式

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

0XD3指令(读34,)

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

例:得到9341

 0X36指令(逐行、列设置坐标)

该指令为存储访问控制指令,可以控制ILI9341存储器的读写方向,简单的说,就是在连续写GRAM的时候,可以控制GRAM指针的增长方向,从而控制显示方式(读GRAM也是一样)。

 

 0X2A指令

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

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

0X2B指令

该指令是页地址设置指令,在从左到右,从上到下的扫描方式(默认)下面,该指令用于设置纵坐标(y坐标)

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

0X2C指令

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

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

0X2E指令

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

ILI9341在收到该指令后,第一次输出的是dummy数据(无效),第二次开始,读取到的才是有效的GRAM数据(从坐标:SC,SP开始),输出规律为:每个颜色分量占8个位,一次输出2个颜色分量。比如:第一次输出是R1G1,随后的规律为:B1R2àG2B2àR3G3àB3R4àG4B4àR5G5... 以此类推 

六,FSMC寄存器

FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和16位PC存储器卡连接,STM32的FSMC接口支持包括SRAM、NAND FLASH、NOR FLASH和PSRAM等存储器。

 STM32的FSMC支持8/16/32位数据宽度,我们这里用到的LCD是16位宽度的,所以在设置的时候,选择16位宽就OK了。FSMC的外部设备地址映像,STM32的FSMC将外部存储器划分为固定大小为256M字节的四个存储块

 对于NOR FLASH/PSRAM控制器(存储块1),通过FSMC_BCRx、FSMC_BTRx和FSMC_BWTRx寄存器设置(其中x=1~4,对应4个区)。通过这3个寄存器,可以设置FSMC访问外部存储器的时序参数,拓宽了可选用的外部存储器的速度范围。  

SRAM/NOR闪存片选控制寄存器(FSMC_BCRx

EXTMOD:扩展模式使能位,控制是否允许读写不同的时序,需设置为1

WREN:写使能位。我们需要向TFTLCD写数据,故该位必须设置为1

MWID[1:0]:存储器数据总线宽度。00,表示8位数据模式;01表示16位数据模式;10和11保留。我们的TFTLCD是16位数据线,所以设置WMID[1:0]=01。

MTYP[1:0]:存储器类型。00表示SRAM、ROM;01表示PSRAM;10表示NOR FLASH;11保留。我们把LCD当成SRAM用,所以需要设置MTYP[1:0]=00。

MBKEN:存储块使能位。需设置为1

 SRAM/NOR闪存片选时序寄存器(FSMC_BTRx

ACCMOD[1:0]:访问模式。00:模式A;01:模式B;10:模式C;11:模式D。

DATAST[7:0]:数据保持时间,等于: DATAST(+1)个HCLK时钟周期,DATAST最大为255。对ILI9341来说,其实就是RD低电平持续时间,最大为355ns。对STM32F1,一个HCLK=13.8ns (1/72M),设置为15;对STM32F4,一个HCLK=6ns(1/168M) ,设置为60。

ADDSET[3:0]:地址建立时间。表示:ADDSET (+1)个HCLK周期,ADDSET最大为15。对ILI9341来说,这里相当于RD高电平持续时间,为90ns。STM32F1的FSMC性能存在问题,即便设置为0,RD也有190ns的高电平,我们这里设置为1。而对STM32F4,则设置为15。

 如果未设置EXTMOD位,则读写共用这个时序寄存器!

SRAM/NOR闪存写时序寄存器(FSMC_BWTRx

 

ACCMOD[1:0]:访问模式。00:模式A;01:模式B;10:模式C;11:模式D。

DATAST[7:0]:数据保持时间,等于: DATAST(+1)个HCLK时钟周期,DATAST最大为255。对ILI9341来说,其实就是WR低电平持续时间,为15ns,不过ILI9320等则需要50ns。考虑兼容性,对STM32F1,一个HCLK=13.8ns (1/72M),设置为3;对STM32F4,一个HCLK=6ns(1/168M) ,设置为9。

ADDSET[3:0]:地址建立时间。表示:ADDSET+1个HCLK周期,ADDSET最大为15。对ILI9341来说,这里相当于WR高电平持续时间,为15ns。同样考虑兼容ILI9320,对STM32F1,这里即便设置为1,WR也有100ns的高电平,我们这里设置为1。而对STM32F4,则设置为8。

寄存器组合

在ST官方库提供的的寄存器定义里面,并没有定义FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx等这个单独的寄存器,而是将他们进行了一些组合。规律如下:

 

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

BTCR[0]对应FSMC_BCR1,BTCR[1]对应FSMC_BTR1

BTCR[2]对应FSMC_BCR2,BTCR[3]对应FSMC_BTR2

BTCR[4]对应FSMC_BCR3,BTCR[5]对应FSMC_BTR3

BTCR[6]对应FSMC_BCR4,BTCR[7]对应FSMC_BTR4

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

BWTR[0]对应FSMC_BWTR1,BWTR[2]对应FSMC_BWTR2,

BWTR[4]对应FSMC_BWTR3,BWTR[6]对应FSMC_BWTR4,

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

七,软件部分

结构体

typedef struct  
{		    
        u16 width;		//LCD 宽度
        u16 height;		//LCD 高度
        u16 id;		//LCD ID
        u8  dir;		//横屏还是竖屏控制:0,竖屏;1,横屏。	
        u16	wramcmd;	//开始写gram指令
        u16  setxcmd;		//设置x坐标指令
        u16  setycmd;		//设置y坐标指令 
}_lcd_dev; 	
//LCD参数
extern _lcd_dev lcddev;	//管理LCD重要参数

lcddev结构体参数的赋值,基本上都是在LCD_Display_Dir函数完成

7个底层接口函数

1,写寄存器值函数 :void LCD_WR_REG(u16 regval)

2,写数据函数:void LCD_WR_DATA(u16 data)

3,读数据函数:u16 LCD_RD_DATA(void)

4,写寄存器内容函数: void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue)

5,读寄存器内容函数: u16 LCD_ReadReg(u16 LCD_Reg)

6,开始写GRAM函数: void LCD_WriteRAM_Prepare(void)

7,写GRAM函数: void LCD_WriteRAM(u16 RGB_Code)

lcd伪代码 

LCD初始化函数伪代码:

//LCD初始化
void LCD_Init(void)
{
    初始化GPIO;
    初始化FSMC;		             	//Mini板不需要
    读取LCD ID;	
    printf(“LCD ID:%x\r\n”,lcddev.id);//打印LCD ID,用到了串口1
                                        //所以必须初始化串口1,否则黑屏	
    根据不同的ID执行LCD初始化代码;
    LCD_Display_Dir(0);		 	//默认为竖屏
    LCD_LED=1;			 	//点亮背光
    LCD_Clear(WHITE);			//清屏
}

坐标设置函数

//设置光标位置
//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==XXXX)	//根据不同的LCD型号,执行不同的代码
     { 
	 ……//省略部分代码
     }
}
		 

画点函数

//画点
//x,y:坐标
//POINT_COLOR:此点的颜色
void LCD_DrawPoint(u16 x,u16 y)
{
    LCD_SetCursor(x,y);		//设置光标位置 
    LCD_WriteRAM_Prepare();	//开始写入GRAM
    LCD_WR_DATA(POINT_COLOR); 

}

读点函数

LCD读点函数:u16 LCD_ReadPoint(u16 x,u16 y)

1,非Mini板的读点函数代码(FSMC方式,适合战舰、精英、探索者F4)

2Mini板的读点函数代码(GPIO方式,适合Mini)

lcd字符显示函数

//在指定位置显示一个字符
//x,y:起始坐标
//num:要显示的字符:" "--->"~"
//size:字体大小 12/16/24
//mode:叠加方式(1)还是非叠加方式(0)
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
{  							  
       u8 temp,t1,t;
       u16 y0=y;
       u8 csize=(size/8+((size%8)?1:0))*(size/2);	//得到字体一个字符对应点阵集所占的字节数	
       num=num-' ';	//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
       for(t=0;t<csize;t++)
       {  
if(size==12)temp=asc2_1206[num][t]; 		//调用1206字体
             else if(size==16)temp=asc2_1608[num][t];	//调用1608字体
             else if(size==24)temp=asc2_2412[num][t];	//调用2412字体
             else return;			//没有的字库
             for(t1=0;t1<8;t1++)
             {			    
      if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);
      else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);
                    temp<<=1;
                    y++;
                    if(y>=lcddev.height)return;		//超区域了
                    if((y-y0)==size)
                    {
	y=y0;
	x++;
	if(x>=lcddev.width)return;		//超区域了
	break;
                     }
              }  	 
        }  	    	   	 	  
} 

 字符码表

const unsigned char oled_asc2_1206[95][12]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x3F,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
……
{0x40,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x40,0x00},/*"~",94*/
};
const unsigned char oled_asc2_1608[95][16]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xCC,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
……
{0x00,0x00,0x60,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00},/*"~",94*/
}
const unsigned char oled_asc2_2412[95][36]={ 
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0x0F,0xFE,0x38,0x0F,0x80,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
……
{0x00,0x00,0x00,0x18,0x00,0x00,0x60,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x0C,0x00,0x00,0x10,0x00,0x00},/*"~",94*/
}

### STM322.8TFTLCD触摸屏XPT2046的相关资源 #### 关于STM322.8TFTLCD触摸屏XPT2046的驱动程序、教程或示例代码的信息如下: 对于STM32平台上的开发,针对2.8TFT LCD(通常分辨率为32240),以及带有XPT2046控制器的电阻式触摸屏的支持已经非常成熟。这类显示屏广泛应用于嵌入式项目中。 #### 驱动程序支持 为了使STM32能够控制这种类型的显示器及其触控功能,开发者可以选择使用官方提供的HAL库或是第三方图形界面库如uGFX、TouchGFX等来简化编程工作量。特别是ST公司推出的STM32CubeMX工具集成了丰富的外设初始化设置选项,其中包括对ILI9341/ST7789V等常见液晶面板芯片的支持[^1]。 #### 示例代码展示 下面是一个简单的C语言函数用于初始化连接到SPI总线上的XPT2046触摸屏控制器,并获取坐标数据的例子: ```c #include "stm32f1xx_hal.h" // 定义 SPI 接口参数... #define TS_SPI_PORT hspi1 #define CS_PIN GPIO_PIN_4 #define CS_GPIO_PORT GPIOA void XPT2046_Init(void){ // 初始化 SPI 和其他必要的硬件资源... } uint16_t Read_XPT2046(uint8_t channel){ uint8_t cmd; uint16_t data; HAL_GPIO_WritePin(CS_GPIO_PORT,CS_PIN ,GPIO_PIN_RESET); switch(channel){ case 0://读取Y+ cmd=0b11010000; break; case 1://读取X- cmd=0b11100000;break; default:return 0xFFFF; } HAL_SPI_Transmit(&TS_SPI_PORT,&cmd,1,100); HAL_SPI_Receive(&TS_SPI_PORT,(uint8_t*)&data,2,100); HAL_GPIO_WritePin(CS_GPIO_PORT,CS_PIN ,GPIO_PIN_SET); return ((data&0xFF)<<8)|(data>>8)&0x0FFF; } ``` 此段代码展示了如何通过SPI通信协议操作XPT2046触摸屏控制器以获得触摸位置的数据。需要注意的是,在实际应用中还需要考虑噪声过滤等问题以提高触摸精度[^2]。 #### 图形用户界面集成 如果计划构建更加复杂的UI应用程序,则可以考虑采用专门设计给微控制器使用的轻量化GUI引擎——LVGL (Light and Versatile Graphics Library),它不仅兼容多种MCU架构而且提供了良好的文档和支持社区。结合上述提到的基础驱动层实现,就可以轻松地为STM32添加精美的图形化交互界面了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值