STM32芯片通过驱动ILI9325芯片来控制液晶显示屏显示,触摸屏通过TSC2046芯片来控制
CSX:TFTLCD片选信号
WRX:写入数据
RDX:读取数据
DB[17:0]:16位双向数据线(无DB0和DB9)
RESX:硬复位TFTLCD
D/CX:命令/数据标志(0:读写命令 1:读写数据)
对应STM32的引脚
LCD复位:RESET
DB[17:0]:各PB引脚
LCD控制引脚:PC6-PC9
GRAM相当于彩屏数据缓冲buffer,把要显示的内容以显示矩阵的形式写到buffer里,让彩屏LCD来读取buffer里的数据再由彩屏驱动芯片显示到显示屏上。
液晶彩屏像素点的数据格式
DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB
17 16 15 14 13 17 12 11 10 8 7 6 5 4 3 2 1 5
红色 绿色 蓝色
DC->高(数据)/低(命令)
CS->拉低片选
读取:设置RD为低,在RD的上升沿读取数据或命令
写:设置WR为低,在WR的上升沿写入到ILI9325里面
(0,0)位置位于屏幕左上角,对于ILI9325(0,0)位置也是显存地址0000H对应的地方
GRAM低8位用于表示X轴,范围:0~EFH(0~239)
高12位表示Y轴,范围:0~13FH(0~319)
右下角终点地址为:13FEFH = 81903 超过了 240*320=76800,因为屏幕像素点的坐标地址并不是连续的,但是问题不大。默认情况下,每次向gram中写像素数据,iLI9325的gram地址自动先从左到右,再从上到下增加,ILI9325用R20H和R21H两个寄存器来确定GRAM地址,在某个点写数据的过程是:
1.向寄存器R20H,R21H写像素地址
2.写一次R22H命令,通知ILI9325准备接受RGB数据
3.写RGB数据
如果要在某个矩形区域连续写同种颜色的数据,则可通过划定区域,指定窗口区域中连续输入数据,要用到的寄存器有R03H,R50 R51 R52 R53共5个寄存器,因为GRAM地址可以按照R03H中的ORG AM ID确定方向的自动增减。
其中 TRI DFM均默认0,不解释,BGR置为1,BGR为1表示写入GRAM的数据格式是按B G R的顺序存放的,设置错误图像会按照逆序的RGB颜色显示,若发现显示颜色有误,改BGR为0就好了。
AM:水平/垂直扫描方向选择,0为水平,1为垂直;
ID:内存地址计数器(AC)增/减方向;
#include "lcd.h"
#include "stdlib.h"
#include "font.h"
#include "usart1.h"
u16 POINT_COLOR,BACK_COLOR=WHITE;
void LCD_WR_DATA(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
void LCD_WR_REG(u8 data)
{
LCD_RS_CLR;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
u16 LCD_RD_DATA(void)
{
u16 t;
LCD_GPIOB_Configuration(0);
LCD_RS_SET;
LCD_CS_CLR;
LCD_RD_CLR;
LCD_RD_SET;
t=DATAIN;
LCD_CS_SET;
LCD_GPIOB_Configuration(1);
return t;
}
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
void LCD_WriteRAM_Prepare(void)
{
LCD_WR_REG(0x22);
}
void LCD_Display(u8 off_on)
{
if(off_on==1)
LCD_WriteReg(0x07,0x0173);
else
LCD_WriteReg(0x07, 0x0);
}
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
if(Horizontal_or_Vertical)
{
LCD_WriteReg(0x20,Ypos);
LCD_WriteReg(0x21,319-Xpos);
}
else
{
LCD_WriteReg(0x20, Xpos);
LCD_WriteReg(0x21, Ypos);
}
}
void LCD_Scan(void)
{
u16 regval=0;
regval|=L2R_U2D;
regval|=1<<12;
LCD_WriteReg(0X03,regval);
}
void LCD_DrawPoint(u16 x,u16 y,u16 Color)
{
LCD_SetCursor(x,y);
LCD_WriteRAM_Prepare();
LCD_WR_DATA(Color);
}
void LCD_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; //GPIO_Pin_10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_All);
}
void LCD_GPIOB_Configuration(u8 sel)
{
GPIO_InitTypeDef GPIO_InitStructure;
if(sel==1)
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
}
else
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
}
}
void LCD_Configuration(void)
{
LCD_GPIO_Configuration();
LCD_WriteReg(0x0000,0x0001);
LCD_WriteReg(0x00E5,0x78F0);
LCD_WriteReg(0x0001,0x0100);
LCD_WriteReg(0x0002,0x0700);
LCD_WriteReg(0x0003,0x1030);
LCD_WriteReg(0x0004,0x0000);
LCD_WriteReg(0x0008,0x0202);
LCD_WriteReg(0x0009,0x0000);
LCD_WriteReg(0x000A,0x0000);
LCD_WriteReg(0x000C,0x0000);
LCD_WriteReg(0x000D,0x0000);
LCD_WriteReg(0x000F,0x0000);
//power on sequence VGHVGL
LCD_WriteReg(0x0010,0x0000);
LCD_WriteReg(0x0011,0x0007);
LCD_WriteReg(0x0012,0x0000);
LCD_WriteReg(0x0013,0x0000);
LCD_WriteReg(0x0007,0x0000);
//vgh
LCD_WriteReg(0x0010,0x1690);
LCD_WriteReg(0x0011,0x0227);
//delayms(100);
//vregiout
LCD_WriteReg(0x0012,0x009D); //0x001b
//delayms(100);
//vom amplitude
LCD_WriteReg(0x0013,0x1900);
//delayms(100);
//vom H
LCD_WriteReg(0x0029,0x0025);
LCD_WriteReg(0x002B,0x000D);
//gamma
LCD_WriteReg(0x0030,0x0007);
LCD_WriteReg(0x0031,0x0303);
LCD_WriteReg(0x0032,0x0003);// 0006
LCD_WriteReg(0x0035,0x0206);
LCD_WriteReg(0x0036,0x0008);
LCD_WriteReg(0x0037,0x0406);
LCD_WriteReg(0x0038,0x0304);//0200
LCD_WriteReg(0x0039,0x0007);
LCD_WriteReg(0x003C,0x0602);// 0504
LCD_WriteReg(0x003D,0x0008);
//ram
LCD_WriteReg(0x0050,0x0000);
LCD_WriteReg(0x0051,0x00EF);
LCD_WriteReg(0x0052,0x0000);
LCD_WriteReg(0x0053,0x013F);
LCD_WriteReg(0x0060,0xA700);
LCD_WriteReg(0x0061,0x0001);
LCD_WriteReg(0x006A,0x0000);
//
LCD_WriteReg(0x0080,0x0000);
LCD_WriteReg(0x0081,0x0000);
LCD_WriteReg(0x0082,0x0000);
LCD_WriteReg(0x0083,0x0000);
LCD_WriteReg(0x0084,0x0000);
LCD_WriteReg(0x0085,0x0000);
//
LCD_WriteReg(0x0090,0x0010);
LCD_WriteReg(0x0092,0x0600);
LCD_WriteReg(0x0007,0x0133);
LCD_WriteReg(0x00,0x0022);//
}
void LCD_Init(void)
{
LCD_Configuration();
LCD_Scan();
LCD_LED;
}
void LCD_Clear(u16 Color)
{
u32 index=0;
LCD_SetCursor(0x00,0x0000);
LCD_WriteRAM_Prepare();
for(index=0;index<76800;index++)
{
LCD_WR_DATA(Color);
}
}
CSX:TFTLCD片选信号
WRX:写入数据
RDX:读取数据
DB[17:0]:16位双向数据线(无DB0和DB9)
RESX:硬复位TFTLCD
D/CX:命令/数据标志(0:读写命令 1:读写数据)
对应STM32的引脚
LCD复位:RESET
DB[17:0]:各PB引脚
LCD控制引脚:PC6-PC9
GRAM相当于彩屏数据缓冲buffer,把要显示的内容以显示矩阵的形式写到buffer里,让彩屏LCD来读取buffer里的数据再由彩屏驱动芯片显示到显示屏上。
液晶彩屏像素点的数据格式
DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB DB
17 16 15 14 13 17 12 11 10 8 7 6 5 4 3 2 1 5
红色 绿色 蓝色
DC->高(数据)/低(命令)
CS->拉低片选
读取:设置RD为低,在RD的上升沿读取数据或命令
写:设置WR为低,在WR的上升沿写入到ILI9325里面
(0,0)位置位于屏幕左上角,对于ILI9325(0,0)位置也是显存地址0000H对应的地方
GRAM低8位用于表示X轴,范围:0~EFH(0~239)
高12位表示Y轴,范围:0~13FH(0~319)
右下角终点地址为:13FEFH = 81903 超过了 240*320=76800,因为屏幕像素点的坐标地址并不是连续的,但是问题不大。默认情况下,每次向gram中写像素数据,iLI9325的gram地址自动先从左到右,再从上到下增加,ILI9325用R20H和R21H两个寄存器来确定GRAM地址,在某个点写数据的过程是:
1.向寄存器R20H,R21H写像素地址
2.写一次R22H命令,通知ILI9325准备接受RGB数据
3.写RGB数据
如果要在某个矩形区域连续写同种颜色的数据,则可通过划定区域,指定窗口区域中连续输入数据,要用到的寄存器有R03H,R50 R51 R52 R53共5个寄存器,因为GRAM地址可以按照R03H中的ORG AM ID确定方向的自动增减。
其中 TRI DFM均默认0,不解释,BGR置为1,BGR为1表示写入GRAM的数据格式是按B G R的顺序存放的,设置错误图像会按照逆序的RGB颜色显示,若发现显示颜色有误,改BGR为0就好了。
AM:水平/垂直扫描方向选择,0为水平,1为垂直;
ID:内存地址计数器(AC)增/减方向;
实际上AM和ID只对开辟窗口写数据方式有用,需要结合R50~R53,一般初始化时会给R50~R53设置为239,319。
#include "lcd.h"
#include "stdlib.h"
#include "font.h"
#include "usart1.h"
u16 POINT_COLOR,BACK_COLOR=WHITE;
void LCD_WR_DATA(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
void LCD_WR_REG(u8 data)
{
LCD_RS_CLR;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
u16 LCD_RD_DATA(void)
{
u16 t;
LCD_GPIOB_Configuration(0);
LCD_RS_SET;
LCD_CS_CLR;
LCD_RD_CLR;
LCD_RD_SET;
t=DATAIN;
LCD_CS_SET;
LCD_GPIOB_Configuration(1);
return t;
}
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
void LCD_WriteRAM_Prepare(void)
{
LCD_WR_REG(0x22);
}
void LCD_Display(u8 off_on)
{
if(off_on==1)
LCD_WriteReg(0x07,0x0173);
else
LCD_WriteReg(0x07, 0x0);
}
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
if(Horizontal_or_Vertical)
{
LCD_WriteReg(0x20,Ypos);
LCD_WriteReg(0x21,319-Xpos);
}
else
{
LCD_WriteReg(0x20, Xpos);
LCD_WriteReg(0x21, Ypos);
}
}
void LCD_Scan(void)
{
u16 regval=0;
regval|=L2R_U2D;
regval|=1<<12;
LCD_WriteReg(0X03,regval);
}
void LCD_DrawPoint(u16 x,u16 y,u16 Color)
{
LCD_SetCursor(x,y);
LCD_WriteRAM_Prepare();
LCD_WR_DATA(Color);
}
void LCD_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; //GPIO_Pin_10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_All);
}
void LCD_GPIOB_Configuration(u8 sel)
{
GPIO_InitTypeDef GPIO_InitStructure;
if(sel==1)
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
}
else
{
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
}
}
void LCD_Configuration(void)
{
LCD_GPIO_Configuration();
LCD_WriteReg(0x0000,0x0001);
LCD_WriteReg(0x00E5,0x78F0);
LCD_WriteReg(0x0001,0x0100);
LCD_WriteReg(0x0002,0x0700);
LCD_WriteReg(0x0003,0x1030);
LCD_WriteReg(0x0004,0x0000);
LCD_WriteReg(0x0008,0x0202);
LCD_WriteReg(0x0009,0x0000);
LCD_WriteReg(0x000A,0x0000);
LCD_WriteReg(0x000C,0x0000);
LCD_WriteReg(0x000D,0x0000);
LCD_WriteReg(0x000F,0x0000);
//power on sequence VGHVGL
LCD_WriteReg(0x0010,0x0000);
LCD_WriteReg(0x0011,0x0007);
LCD_WriteReg(0x0012,0x0000);
LCD_WriteReg(0x0013,0x0000);
LCD_WriteReg(0x0007,0x0000);
//vgh
LCD_WriteReg(0x0010,0x1690);
LCD_WriteReg(0x0011,0x0227);
//delayms(100);
//vregiout
LCD_WriteReg(0x0012,0x009D); //0x001b
//delayms(100);
//vom amplitude
LCD_WriteReg(0x0013,0x1900);
//delayms(100);
//vom H
LCD_WriteReg(0x0029,0x0025);
LCD_WriteReg(0x002B,0x000D);
//gamma
LCD_WriteReg(0x0030,0x0007);
LCD_WriteReg(0x0031,0x0303);
LCD_WriteReg(0x0032,0x0003);// 0006
LCD_WriteReg(0x0035,0x0206);
LCD_WriteReg(0x0036,0x0008);
LCD_WriteReg(0x0037,0x0406);
LCD_WriteReg(0x0038,0x0304);//0200
LCD_WriteReg(0x0039,0x0007);
LCD_WriteReg(0x003C,0x0602);// 0504
LCD_WriteReg(0x003D,0x0008);
//ram
LCD_WriteReg(0x0050,0x0000);
LCD_WriteReg(0x0051,0x00EF);
LCD_WriteReg(0x0052,0x0000);
LCD_WriteReg(0x0053,0x013F);
LCD_WriteReg(0x0060,0xA700);
LCD_WriteReg(0x0061,0x0001);
LCD_WriteReg(0x006A,0x0000);
//
LCD_WriteReg(0x0080,0x0000);
LCD_WriteReg(0x0081,0x0000);
LCD_WriteReg(0x0082,0x0000);
LCD_WriteReg(0x0083,0x0000);
LCD_WriteReg(0x0084,0x0000);
LCD_WriteReg(0x0085,0x0000);
//
LCD_WriteReg(0x0090,0x0010);
LCD_WriteReg(0x0092,0x0600);
LCD_WriteReg(0x0007,0x0133);
LCD_WriteReg(0x00,0x0022);//
}
void LCD_Init(void)
{
LCD_Configuration();
LCD_Scan();
LCD_LED;
}
void LCD_Clear(u16 Color)
{
u32 index=0;
LCD_SetCursor(0x00,0x0000);
LCD_WriteRAM_Prepare();
for(index=0;index<76800;index++)
{
LCD_WR_DATA(Color);
}
}