【开源】LCD12864 ST7920带中文字库屏驱动程序
刚调通了LCD12864 芯片为ST7920带中文字库的屏的驱动,串行驱动,贴出来让大家挑挑刺,顺便开源备份一下功能:说白了,其实就3个
1、显示字符串
2、显示数字
3、反白显示
说明:
1、先说字符串,因为屏幕自带了字库16*16的,支持中文,只能显示4行,每行16字节,特别是中英文混合显示,处理不好会乱码,所以这部分也没特别好的办法,直接由用户控制了。支持反白显示
2、数字显示支持十进制和十六进制,左对齐、右对齐和中间对齐,支持全部显示或者只显示一部分空白部分支持自定义字符(当然是字库要有才行),支持反白显示。
3、反白显示可以单独控制,用0x00和0xff就可以适应大部分应用,也就是透明和不透明之分。当然,改一下也可以支持图形,这个目前没做。。
效果: LCD_ShowNumber(2,0,0x567890,FORMAT_H|DISP_ALL,' ',0xff);
LCD_ShowNumber(2,1,-12345,FORMAT_D|ALIGN_R|10,'*',0x00);
LCD_ShowNumber(2,2,12345,FORMAT_D|ALIGN_M|7,' ',0xff);
LCD_ShowNumber(5,3,tick,FORMAT_D|ALIGN_M|DISP_ALL,' ',0xff);
以上。。
以下是头文件
#ifndef __LCD12864_ZK_H
#define __LCD12864_ZK_H
#include "main.h"
//数据显示长度
#defineDISP_MASK 0x1F
#defineDISP_ALL 0x00
//进制格式
#defineFORMAT_MASK 0x80
#defineFORMAT_D 0x00 //十进制Decimal
#defineFORMAT_H 0x80 //十六进制Hexadecimal
//对齐方式
#defineALIGN_MASK 0x60
#defineALIGN_R 0x00 //右对齐
#defineALIGN_L 0x20 //左对齐
#defineALIGN_M 0x40 //中间对齐
void LCD_Init(void);
void LCD_ShowString(unsigned char x,unsigned char y,const char *pStr,unsigned char bg);
void LCD_ShowNumber(unsigned char x,unsigned char y,long num,unsigned char param,char fill,unsigned char bg);
void LCD_SetWhite(unsigned char x,unsigned char y,unsigned char width);
void LCD_SetBG(unsigned char x,unsigned char y,unsigned char w,unsigned char bg);
void LCD_Process(void);
#endif
以下是C文件
#include "main.h"
#define LCD_RST_1 P20 = 1
#define LCD_RST_0 P20 = 0
#define LCD_CS_1 P26 = 1
#define LCD_CS_0 P26 = 0
#define LCD_CLK_1 P24 = 1
#define LCD_CLK_0 P24 = 0
#define LCD_SID_1 P25 = 1
#define LCD_SID_0 P25 = 0
static void write(char cmd, unsigned char dat) //写指令或数据数据cmd=1:0xfa 命令cmd=0:0xf8
{ unsigned char i,j,Temp;
LCD_CS_1;
LCD_CLK_0;
for(j=0;j<3;j++){
if (j==0){ Temp =( cmd? 0xfa:0xf8);}
else if (j==1){ Temp =((dat<<0) & 0xf0);}
else if (j==2){ Temp =((dat<<4) & 0xf0);}
for(i=0;i<8;i++){
(Temp&0x80)?(LCD_SID_1):(LCD_SID_0);Temp<<=1; delay_us(1); //左移
LCD_CLK_1; //delay_us(1); //_nop_();_nop_();//移入
LCD_CLK_0; //delay_us(1); //_nop_();_nop_();_nop_(); //读出
}
}
LCD_CS_0;
}
unsigned char SetWdat;//反白显示缓存
unsigned char SetWdat_bak;//反白显示缓存
//设置反白区域
void LCD_SetBG(unsigned char x,unsigned char y,unsigned char w,unsigned char bg)
{
unsigned char i;
if(x>15||y>3||w==0) return; //超出范围
if(w+x>16) w = 16-x;
for(i=0;i<w;i++){
SetWdat[(y<<4)+x+i] = bg;
}
}
//反白显示2字节
void LCD_ShowBG2Byte(unsigned char n)
{
unsigned char Ax[] = {0x80,0x80,0x88,0x88};
unsigned char Ay[] = {0x80,0x90,0x80,0x90};
unsigned char j;
unsigned char x = ((n&0x0f)>>1);
unsigned char y = (n>>4);
write(0,0x34); write(0,0x36); //打开GGRAM
for(j=0;j<16;j++){
write(0,Ay+j); //y
write(0,Ax+x); //x
write(1,SetWdat);
write(1,SetWdat);
}
write(0,0x30); //关闭GGRAM
}
void LCD_BGProcess(void) //反白显示
{
unsigned char i;
for(i=0;i<64;i+=2){
if((SetWdat_bak!=SetWdat)||(SetWdat_bak!=SetWdat)){ SetWdat_bak = SetWdat; SetWdat_bak = SetWdat;
LCD_ShowBG2Byte(i);
}
}
}
unsigned char LCDdat;//显示缓存
unsigned char LCDdat_bak;//显示缓存备份
void LCD_Process(void) //模拟刷屏12864
{
unsigned char Addr[] = {0x80,0x90,0x88,0x98};
unsigned char i;
for(i=0;i<64;i+=2){
if((LCDdat_bak!=LCDdat)||(LCDdat_bak!=LCDdat)){LCDdat_bak = LCDdat;LCDdat_bak = LCDdat;
write(0,Addr+((i&0x0f)>>1)); //写地址 控制光标
write(1,LCDdat); //数据一次要连写两个
write(1,LCDdat); //数据一次要连写两个
}
}
LCD_BGProcess();
}
//void LCD_RefreshALL(void) //模拟刷屏12864
//{
// unsigned char Addr[] = {0x80,0x90,0x88,0x98};
// unsigned char i,j;
//
// for(i=0;i<4;i++){ //送四行汉字 //一次送一个汉字 (两个字节)
// write(0,Addr); //先送地址后送16个字符
// for(j=0;j<16;j++){write(1,LCDdat[(i*16)+j]);}
// }
//}
void LCD_ClearGM(void)
{
unsigned char i,j;
write(0,0x34);
write(0,0x36);
for(j=0;j<32;j++)
{
write(0,0x80+j);
write(0,0x80);
for(i=0;i<16;i++)
{
write(1,0x00);
}
}
for(j=0;j<32;j++)
{
write(0,0x80+j);
write(0,0x88);
for(i=0;i<16;i++)
{
write(1,0x00);
}
}
write(0,0x30);
}
//******************** 显示字符串 ***********************//
//**x:横坐标(0~15)y:纵坐标(0~3)显示中文时注意从x坐标偶数写,否则乱码
void LCD_ShowString(unsigned char x,unsigned char y,const char *pStr,unsigned char bg)
{
unsigned char i;
unsigned int strLen = strlen(pStr); //字符串长度用 strlen(); 类型长度 sizeof();
if(strLen<=0||x>15||y>3) return; //超出范围
if(strLen+x>16) strLen = 16-x;
for(i=0;i<strLen;i++){ //只在一行显示,超出部分丢弃
LCDdat = pStr;
}
LCD_SetBG(x,y,strLen,bg);
}
//******************** 显示数字 ***********************//
//**x:横坐标(0~15)y:纵坐标(0~3)
//**param:
//**(bit(7) 0:十进制显示 1:十六进制显示)
//**(bit(6~5) 00:右对齐 01:左对齐 10:中间对齐)
//**(bit(4~0)显示的长度0~31 0:显示全部)
//**fill: 空白处填充的字符,注意转义字符
void LCD_ShowNumber(unsigned char x,unsigned char y,long num,unsigned char param,char fill,unsigned char bg)
{
unsigned char i;
char strBuff; //一行字符缓存
char disBuff; //一行字符缓存用于显示
int strLen = 0;
unsigned char disLen = (param&DISP_MASK);
if((x>15)||(y>3)) return; //超出范围
if(param&FORMAT_MASK){ //十六进制显示
strLen = sprintf(strBuff,"%lX",num);
}
else{ //十进制显示
strLen = sprintf(strBuff,"%ld",num);
}
if(strLen<=0) return; //错误
if(disLen==DISP_ALL) disLen = strLen; //数据长度为0则全部显示
if((param&ALIGN_MASK)==ALIGN_R){//右对齐
for(i=0;i<disLen;i++){
if(i<strLen) disBuff = strBuff;
else disBuff = fill;
}
}
else if((param&ALIGN_MASK)==ALIGN_L){//左对齐
for(i=0;i<disLen;i++){
if(i<strLen) disBuff = strBuff;
else disBuff = fill;
}
}
else if((param&ALIGN_MASK)==ALIGN_M){//中间对齐
uint8_t disM = (disLen>>1); //显示窗口的中间位置
uint8_t strM = (strLen>>1); //数据的中间位置
for(i=0;i<disM;i++){ //前半部分右对齐
if(i<strM) disBuff = strBuff;
else disBuff = fill;
}
for(i=disM;i<disLen;i++){ //后半部分 左对齐
if(strM+i-disM<strLen) disBuff = strBuff;
else disBuff = fill;
}
}
disBuff = '\0'; //末尾加结束符
LCD_ShowString(x,y,disBuff,bg);
}
/**********************************
LCD初始化
**********************************/
void LCD_Init(void)
{
memset(LCDdat,' ',sizeof(LCDdat));
memset(LCDdat_bak,0x00,sizeof(LCDdat_bak));
memset(SetWdat,0x00,sizeof(SetWdat));
memset(SetWdat_bak,0x00,sizeof(SetWdat_bak));
LCD_RST_0; delay_ms(100);
LCD_RST_1; //delay_ms(100);//复位
write(0,0x30);//8 位介面,基本指令集
write(0,0x0c);//显示打开,光标关,反白关
write(0,0x01);//清屏,将DDRAM的地址计数器归零
// delay_ms(100);
LCD_ClearGM();
// LCD_SetBG(3,1,5,1);
}
兄台,能丢到github或者gitee上吗? 谢谢分享,LCD12864不好用,绘图模式刷屏速度太慢了 angler12 发表于 2020-4-20 12:47
兄台,能丢到github或者gitee上吗?
没有github或者gitee。。。真不好意思。不是专业的{:lol:} flash3g 发表于 2020-4-20 15:58
谢谢分享,LCD12864不好用,绘图模式刷屏速度太慢了
全屏刷是比较慢。但上面的程序不是全屏刷,而且速度已经飞快了。 谢谢提供 现在这种屏用的人少了吧?手里还有几十个全新的。 mark一下,看看有没有机会用上。 flash3g 发表于 2020-4-20 15:58
谢谢分享,LCD12864不好用,绘图模式刷屏速度太慢了
我都是开缓冲100ms刷一次。 以前也写过一个串口驱动的LCD12864 (记得用的是北京青云的LCD显示屏)
问一下,arduino的库可以直接放mdk下面用么?
页:
[1]