本帖最后由 freeelectron 于 2021-12-30 10:04 编辑
#申请原创#@21小跑堂
1、基本原理
驱动LCD其实就是往LCD的显存写数据,写1的地方显示,写0的地方不显示,反显刚好相反;由于显存以128列、64行分布,所以也称12864液晶。
2、基本特性
工作电压 3.3V,背光电压 3.0V\45MA 通讯方式;
8 位并行(6800 和 8080 时序),4 线串行通讯 12864;
点阵显示器内存(DDRAM 为 13265) ;
显示对比度,内部寄存器调节(软件调对比度);
占空比 1/64 偏压比 1/9;
工作温度 -20 到+70 度。
3、显存映射
可以看出列定义为0-127,行地址范围以8个像素为-个单 位定义为(0-7)页,共64。
4、管脚说明
可以看出,29脚的高低电平决定了使用并口还是串口方式。
5、串行方式驱动时序
从图中可以看出:
在CSB拉低的时候,进行数据或命令传输;
RS为高的时候传输数据,RS为低的时候传输指令;
SCL为时钟;
SDA为数据。
6、串行写流程
首先拉低CSB;
通过设置RS的电平,选择写数据或指令;
SCL拉低,bit7传输,SCL拉高,依次类推,从bit7到bit0完成一个字节的传输;
最后拉高CSB。
7、写入数据流程
可以看出,写数据之前,要先设置写入的地址,这里有列地址(0-127列),页地址(0-7页),同时要注意,列地址会自加。
8、指令说明
9、原理设计
10、程序驱动
本文使用GD32驱动LCD。
10.1、io口定义以及初始化#define LCD_SCL_PORT GPIOB
#define LCD_SCL_PIN GPIO_PIN_6
#define LCD_SDA_PORT GPIOB
#define LCD_SDA_PIN GPIO_PIN_7
#define LCD_CSB_PORT GPIOB
#define LCD_CSB_PIN GPIO_PIN_11
#define LCD_RST_PORT GPIOC
#define LCD_RST_PIN GPIO_PIN_11
#define LCD_A0_PORT GPIOC
#define LCD_A0_PIN GPIO_PIN_13
#define LCD_BKLED_PORT GPIOA
#define LCD_BKLED_PIN GPIO_PIN_6
#define LCD_CMD 1
#define LCD_DATA 0
#define PORT(port) LCD_##port##_PORT
#define PIN(pin) LCD_##pin##_PIN
#define LCD_PIN_OUT(pin,level) { if(level) \
{ gpio_bit_set(PORT(pin),PIN(pin));} \
else \
{ gpio_bit_reset(PORT(pin),PIN(pin));} \
}
10.2、LCD写
/*
ismcd:高为数据,低为指令
*/
static void LcdWrite(uint8_t iscmd ,uint8_t data)
{
uint8_t i;
LCD_PIN_OUT(CSB,0);
if(iscmd)
{
LCD_PIN_OUT(A0,0);
}
else
{
LCD_PIN_OUT(A0,1);
}
for(i=0;i<8;i++)
{
LCD_PIN_OUT(SCL,0);
DelayUs(10);
if(data&0x80)
{
LCD_PIN_OUT(SDA,1);
}
else
{
LCD_PIN_OUT(SDA,0);
}
LCD_PIN_OUT(SCL,1);
DelayUs(10);
data=data<<1;
}
LCD_PIN_OUT(CSB,1);
}
10.3、LCD设置地址
void LcdAddress(uint8_t page,uint8_t column)
{
LcdWrite(LCD_CMD,0xb0+page);
LcdWrite(LCD_CMD,((column>>4)&0x0f)+0x10); //设置列地址的高4 位
LcdWrite(LCD_CMD,((column>>0)&0x0f)+0x00); //设置列地址的低4 位
}
10.4、LCD清屏
/*全屏清屏*/
void LcdClearScreen(void)
{
uint8_t i,j;
for(i=0;i<8;i++)
{
LcdAddress(i,0);
for(j=0;j<128;j++)
{
LcdWrite(LCD_DATA,0x00);
}
}
}
清屏,就是向显存写入0,即不显示。
10.5、LCD显示边框
void LcdDispBK(void)
{
uint8_t i;
//上框
LcdAddress(0,0);
for (i=0;i<128;i++)
{
LcdWrite(LCD_DATA,0x01);
}
//下框
LcdAddress(7,0);
for (i=0;i<128;i++)
{
LcdWrite(LCD_DATA,0x80);
}
//左框
for(i=0;i<8;i++)
{
LcdAddress(i,0);
LcdWrite(LCD_DATA,0xff);
}
//右框
for(i=0;i<8;i++)
{
LcdAddress(i,127);
LcdWrite(LCD_DATA,0xff);
}
}
10.6、LCD显示8*16字符串
void LcdDispStr8x16(uint8_t reverse,uint8_t page,uint8_t column,uint8_t *str)
{
uint16_t i=0,j;
uint8_t zk[16];
while(str[i]>0x00)
{
if((str[i]>=0x20)&&(str[i]<=0x7e))
{
extern uint8_t GT20L16S1YGetAsciiData( uint8_t ASCIICode, uint32_t BaseAdd, uint8_t* S1YDZ_Data );
GT20L16S1YGetAsciiData( str[i], 0x3b7c0, zk);
LcdAddress(page,column); //上半部分
for(j=0;j<8;j++)
{
if (reverse==1)
{
LcdWrite(LCD_DATA,zk[j]);
}
else
{
LcdWrite(LCD_DATA,~(zk[j]));
}
}
LcdAddress(page+1,column);//下半部分
for(j=0;j<8;j++)
{
if (reverse==1)
{
LcdWrite(LCD_DATA,zk[j+8]);
}
else
{
LcdWrite(LCD_DATA,~(zk[j+8]));
}
}
i++;
column+=8;
}
}
}
10.7、LCD显示16*16汉字
void LcdDispStr16x16(uint8_t reverse,uint8_t page,uint8_t column,uint8_t *str)
{
uint16_t i=0,j;
uint8_t zk[32];
while(str[i]>0x00)
{
extern void GT20L16S1YGetGb2312Data( uint8_t MSB, uint8_t LSB, uint8_t* S1YDZ_Data );
GT20L16S1YGetGb2312Data( str[i], str[i+1], zk );
LcdAddress(page,column); //上半部分
for(j=0;j<16;j++)
{
if (reverse==1)
{
LcdWrite(LCD_DATA,zk[j]);
}
else
{
LcdWrite(LCD_DATA,~(zk[j]));
}
}
LcdAddress(page+1,column);//下半部分
for(j=0;j<16;j++)
{
if (reverse==1)
{
LcdWrite(LCD_DATA,zk[j+16]);
}
else
{
LcdWrite(LCD_DATA,~(zk[j+16]));
}
}
i++,i++;
column+=16;
}
}
10.8、LCD初始化
void LcdInit(void)
{
LcdIoInit();
LCD_PIN_OUT(RST,0);
DelayUs(20);
LCD_PIN_OUT(RST,1); /*复位完毕*/
DelayUs(20);
LcdWrite(LCD_CMD,0xe2); /*软复位*/
DelayUs(50);
LcdWrite(LCD_CMD,0x2c); /*升压步聚1*/
DelayUs(50);
LcdWrite(LCD_CMD,0x2e); /*升压步聚2*/
DelayUs(50);
LcdWrite(LCD_CMD,0x2f); /*升压步聚3*/
DelayUs(50);
LcdWrite(LCD_CMD,0x24); /*粗调对比度,可设置范围0x20~0x27*/
LcdWrite(LCD_CMD,0x81); /*微调对比度*/
LcdWrite(LCD_CMD,0x1b); /*0x1a,微调对比度的值,可设置范围0x00~0x3f 1f*/
LcdWrite(LCD_CMD,0xa3); /*偏压比(bias),0xa2:1/9 0xa3:1=1/7 */
LcdWrite(LCD_CMD,0xc8); /*行扫描顺序:从上到下*/
LcdWrite(LCD_CMD,0xa0); /*列扫描顺序:从左到右*/
LcdWrite(LCD_CMD,0x40); /*起始行:第一行开始*/
LcdWrite(LCD_CMD,0xaf); /*开显示*/
LcdClearScreen();
LcdDispBK();
LcdDispStr8x16(0,2,20,(uint8_t*)"display,test") ;
LcdDispStr16x16(1,5,50,(uint8_t*)"你好");
}
注:如果显示不清晰,可以通过偏压比,对比度来调节。
11、显示测试
图中显示了中文、英文、边框,还实现了反显。
|
|