一文学会LCD12864显示中文、英文、反显

1、基本原理

驱动LCD其实就是往LCD的显存写数据,写1的地方显示,写0的地方不显示,反显刚好相反;由于显存以128列、64行分布,所以也称12864液晶。

2、基本特性

工作电压 3.3V,背光电压 3.0V\45MA 通讯方式;
8 位并行(6800 和 8080 时序),4 线串行通讯 12864;
点阵显示器内存(DDRAM 为 132
65) ;
显示对比度,内部寄存器调节(软件调对比度);
占空比 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));}  \
                               }
void LcdIoInit(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_GPIOC);
	
	gpio_init(LCD_SCL_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,  LCD_SCL_PIN);
	gpio_init(LCD_SDA_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,  LCD_SDA_PIN);
	
	gpio_init(LCD_CSB_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,  LCD_CSB_PIN);
	gpio_init(LCD_RST_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,  LCD_RST_PIN);
	gpio_init(LCD_A0_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,  LCD_A0_PIN);
	
	gpio_init(LCD_BKLED_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,  LCD_BKLED_PIN);
	
	LCD_PIN_OUT(BKLED,1);
}
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清屏

清屏,就是向显存写入0,即不显示。

/*全屏清屏*/ 
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); 
		}
	}
}
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;
		}
	}
}

本文使用的GT20L16S1Y字库,所以点阵数据直接从字库读取。

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;
	}
}

本文使用的GT20L16S1Y字库,所以点阵数据直接从字库读取。

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、显示测试

在这里插入图片描述
图中显示了中文、英文、边框,还实现了反显。

控制器7920,代码没啥好说,我尽量多写了注释,播放动画也很流畅的。 亮点就是支持中英文混合输出,其他没啥。 lcd12864.h源码如下: #ifndef _LCD12864_H #define _LCD12864_H #include "my51.h" #define LCD_dataBus P0 //总线 sbit LCD_EN = P3^4; //使能控制 sbit LCD_RS = P3^5; //数据_命令选择端 sbit LCD_RW = P3^6; //读写控制 sbit LCD_PSB= P3^7; //串并选择,H并行,L串行 extern bool bShowPicFlag; //绘图时图像显示控制(仅控制GDRAM) /*************************基本功能函数*********************************************/ extern void LCD12864_init(); //初始化,必须置顶调用 extern void LCD12864_setPos(u8 row, u8 cols); //设置光标位置 extern void LCD12864_writeByte(u8 dat); //写一个字节 extern void LCD12864_writeCmd(u8 cmd); //写指令 extern u8 LCD12864_readByte(); //读一个字节ram extern u8 LCD12864_readIR(); //读暂存器 extern bool LCD12864_isBusy(); //判忙 /*************************调用基本字库显示文字**************************************/ //独创支持全角半角字符及中英混合的字符串,或字符串的子串,起始行号row(0-3)和列坐标cols(0-15),写满屏幕为止 //行号4-7行是滚动区 extern void LCD12864_writeData(u8 row, u8 cols,u8* pBuf,u8 dataSize);//写一堆数据 extern void LCD12864_earseSomeDDRam(u8 row,u8 cols,u8 dataSize); //擦除N字节DDRam /*************************用户自定义图标字体****************************************/ extern void LCD12864_writeCGRAM(u8 userRamNum,u8* pCGRAM_userCode); //写自定义图标字体 extern void LCD12864_showCGRAM(u8 row,u8 cols,u8 num) ; //显示自定义图标字体,row(0-3),cols(0-15) extern void LCD12864_clearCGRAM(u8 CGRAM_groupNum) ; //CGRAM清零(初始化也可清0) /*************************图像显示功能函数**********************************************/ extern void LCD12864_showGDRAM(bool bShowImage); //GDRAM绘图显示开关 extern void LCD12864_clearGDRAM(); //液晶整个可视区的GDRAM快速清0 //前4参数:起始点x(0-7)位址,y(0-63)坐标,要显示的宽度(1-128)和高度(1-64)[可显示从图像左上角开始的部分区域] //后4参数:图像代码地址,图像本身的宽度(1-128)和高度(1-64), 反白(true反白,false不反白) //画图填充GDRAM ,注:显示的区域或者图像本身宽度必须是8的倍数 extern u8 LCD12864_drawGDRAM(u8 x,u8 y,u8 width,u8 height,u8 *pImageCode,u8 imageWidth,u8 imageHight,bool bReverse); extern void LCD12864_drawDot(u8
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

freemote

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值