857
社区成员
![](https://csdnimg.cn/release/cmsfe/public/img/topic.427195d5.png)
![](https://csdnimg.cn/release/cmsfe/public/img/me.40a70ab0.png)
![](https://csdnimg.cn/release/cmsfe/public/img/task.87b52881.png)
![](https://csdnimg.cn/release/cmsfe/public/img/share-circle.3e0b7822.png)
这是我参加朝闻道知识分享大赛的第十九篇文章
最后一次分享关于STM32的相关知识,讲解一下LCD液晶显示的相关内容吧。
TFTLCD即薄膜晶体管液晶显示器。它与无源TN-LCD、STN-LCD的简单矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。
TFTLCD具有:亮度好、对比度高、层次感强、颜色鲜艳等特点。是目前最主流的LCD显示器。广泛应用于电视、手机、电脑、平板等各种电子产品。
TFTLCD模块原理图:
TFTLCD接口说明 :
lLCD_CS:LCD片选信号
lLCD_WR:LCD写信号
lLCD_RD:LCD读信号
lDB[17:1]:16位双向数据线。
lLCD_RST:硬复位LCD信号
lLCD_RS:命令/数据标志
lBL_CTR:背光控制信号
lT_MISO/T_MOSI/T_PEN/T_CS/T_CLK,触摸屏接口信号
驱动流程:
FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和16位PC存储器卡连接,STM32的FSMC接口支持包括SRAM、NAND FLASH、NOR FLASH和PSRAM等存储器。FSMC的框图如下图所示:
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也可以接在其他地址线上,战舰V3和精英板开发板都是把RS连接在A10上面,而探索者STM32F4把RS接在A6上面。 因此,可以把TFTLCD当成一个SRAM来用,只不过这个SRAM有2个地址,这就是FSMC可以驱动LCD的原理。
寄存器组合说明:
在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]保留,没有用到。
LCD地址结构体
typedef struct
{
vu16 LCD_REG;
vu16 LCD_RAM;
} LCD_TypeDef;
#define LCD_BASE
#define LCD
LCD重要参数集
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重要参数
LCD初始化
void LCD_Init(void)
{
printf(“LCD ID:%x\r\n”,lcddev.id);
LCD_Display_Dir(0); //默认为竖屏
LCD_LED=1; //点亮背光
LCD_Clear(WHITE); //清屏
}
设置光标位置
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型号,执行不同的代码
{
……//省略部分代码
}
}
在指定位置显示一个字符
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;
}
}
}
}
至此,有关LCD液晶显示的相关知识就分享完毕了。同时,stm32的相关知识也介绍完了。
祝好~~~