搜索
bottom↓
回复: 10
打印 上一主题 下一主题

【开源】LCD12864 ST7920带中文字库屏驱动程序

[复制链接]

出0入55汤圆

跳转到指定楼层
1
发表于 2020-4-20 11:51:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
刚调通了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);

以上。。

以下是头文件
  1. #ifndef __LCD12864_ZK_H
  2. #define __LCD12864_ZK_H

  3. #include "main.h"

  4. //数据显示长度
  5. #define  DISP_MASK           0x1F
  6. #define  DISP_ALL           0x00

  7. //进制格式
  8. #define  FORMAT_MASK           0x80
  9. #define  FORMAT_D           0x00 //十进制Decimal
  10. #define  FORMAT_H           0x80 //十六进制Hexadecimal

  11. //对齐方式
  12. #define  ALIGN_MASK           0x60
  13. #define  ALIGN_R                   0x00 //右对齐
  14. #define  ALIGN_L                   0x20 //左对齐
  15. #define  ALIGN_M                   0x40 //中间对齐

  16. void LCD_Init(void);
  17. void LCD_ShowString(unsigned char x,unsigned char y,const char *pStr,unsigned char bg);
  18. void LCD_ShowNumber(unsigned char x,unsigned char y,long num,unsigned char param,char fill,unsigned char bg);
  19. void LCD_SetWhite(unsigned char x,unsigned char y,unsigned char width);
  20. void LCD_SetBG(unsigned char x,unsigned char y,unsigned char w,unsigned char bg);
  21. void LCD_Process(void);
  22.        

  23. #endif

复制代码


以下是C文件
  1. #include "main.h"

  2. #define LCD_RST_1                P20 = 1
  3. #define LCD_RST_0                P20 = 0

  4. #define LCD_CS_1                P26 = 1
  5. #define LCD_CS_0                P26 = 0

  6. #define LCD_CLK_1                P24 = 1
  7. #define LCD_CLK_0                P24 = 0

  8. #define LCD_SID_1                P25 = 1
  9. #define LCD_SID_0                P25 = 0



  10. static void write(char cmd, unsigned char dat) //写指令或数据  数据cmd=1:0xfa 命令cmd=0:0xf8
  11. {        unsigned char i,j,Temp;
  12.        
  13.         LCD_CS_1;
  14.         LCD_CLK_0;
  15.        
  16.         for(j=0;j<3;j++){             
  17.                          if (j==0){ Temp =( cmd? 0xfa:0xf8);}
  18.                 else if (j==1){ Temp =((dat<<0) & 0xf0);}
  19.                 else if (j==2){ Temp =((dat<<4) & 0xf0);}
  20.                 for(i=0;i<8;i++){  
  21.                         (Temp&0x80)?(LCD_SID_1):(LCD_SID_0);  Temp<<=1; delay_us(1); //左移
  22.                         LCD_CLK_1; //delay_us(1);   //_nop_();_nop_();//移入  
  23.                         LCD_CLK_0; //delay_us(1);   //_nop_();_nop_();_nop_(); //读出
  24.                 }
  25.         }
  26.         LCD_CS_0;
  27. }       

  28. unsigned char SetWdat[64];//反白显示缓存
  29. unsigned char SetWdat_bak[64];//反白显示缓存

  30. //设置反白区域
  31. void LCD_SetBG(unsigned char x,unsigned char y,unsigned char w,unsigned char bg)
  32. {
  33.         unsigned char i;
  34.         if(x>15||y>3||w==0) return; //超出范围
  35.         if(w+x>16) w = 16-x;
  36.         for(i=0;i<w;i++){
  37.                 SetWdat[(y<<4)+x+i] = bg;
  38.         }
  39. }

  40. //反白显示2字节
  41. void LCD_ShowBG2Byte(unsigned char n)
  42. {
  43.         unsigned char Ax[] = {0x80,0x80,0x88,0x88};
  44.         unsigned char Ay[] = {0x80,0x90,0x80,0x90};
  45.         unsigned char j;
  46.         unsigned char x = ((n&0x0f)>>1);
  47.         unsigned char y = (n>>4);
  48.        
  49.         write(0,0x34); write(0,0x36); //打开GGRAM
  50.         for(j=0;j<16;j++){
  51.                 write(0,Ay[y]+j); //y
  52.                 write(0,Ax[y]+x); //x
  53.                 write(1,SetWdat[n]);
  54.                 write(1,SetWdat[n+1]);
  55.         }
  56.         write(0,0x30); //关闭GGRAM
  57. }

  58. void LCD_BGProcess(void) //反白显示
  59. {
  60.         unsigned char i;
  61.         for(i=0;i<64;i+=2){
  62.                 if((SetWdat_bak[i]!=SetWdat[i])||(SetWdat_bak[i+1]!=SetWdat[i+1])){ SetWdat_bak[i] = SetWdat[i]; SetWdat_bak[i+1] = SetWdat[i+1];
  63.                         LCD_ShowBG2Byte(i);
  64.                 }
  65.         }
  66. }


  67. unsigned char LCDdat[64];//显示缓存
  68. unsigned char LCDdat_bak[64];//显示缓存备份

  69. void LCD_Process(void) //模拟刷屏12864
  70. {       
  71.         unsigned char Addr[] = {0x80,0x90,0x88,0x98};
  72.         unsigned char i;
  73.        
  74.         for(i=0;i<64;i+=2){
  75.                 if((LCDdat_bak[i]!=LCDdat[i])||(LCDdat_bak[i+1]!=LCDdat[i+1])){LCDdat_bak[i] = LCDdat[i];LCDdat_bak[i+1] = LCDdat[i+1];
  76.                         write(0,Addr[i>>4]+((i&0x0f)>>1)); //写地址 控制光标
  77.                         write(1,LCDdat[i]);   //数据一次要连写两个
  78.                         write(1,LCDdat[i+1]); //数据一次要连写两个
  79.                 }
  80.         }
  81.         LCD_BGProcess();
  82. }

  83. //void LCD_RefreshALL(void) //模拟刷屏12864
  84. //{       
  85. //        unsigned char Addr[] = {0x80,0x90,0x88,0x98};
  86. //        unsigned char i,j;
  87. //       
  88. //        for(i=0;i<4;i++){ //送四行汉字 //一次送一个汉字 (两个字节)
  89. //                write(0,Addr[i]); //先送地址后送16个字符
  90. //                for(j=0;j<16;j++){write(1,LCDdat[(i*16)+j]);}
  91. //        }
  92. //}




  93. void LCD_ClearGM(void)
  94. {
  95.         unsigned char i,j;
  96.         write(0,0x34);
  97.         write(0,0x36);
  98.         for(j=0;j<32;j++)
  99.         {
  100.                 write(0,0x80+j);
  101.                 write(0,0x80);
  102.                 for(i=0;i<16;i++)
  103.                 {
  104.                         write(1,0x00);
  105.                 }
  106.         }
  107.         for(j=0;j<32;j++)
  108.         {
  109.                 write(0,0x80+j);
  110.                 write(0,0x88);
  111.                 for(i=0;i<16;i++)
  112.                 {
  113.                         write(1,0x00);
  114.                 }
  115.         }
  116.         write(0,0x30);
  117. }

  118. //******************** 显示字符串 ***********************//
  119. //**  x:横坐标(0~15)  y:纵坐标(0~3)  显示中文时注意从x坐标偶数写,否则乱码
  120. void LCD_ShowString(unsigned char x,unsigned char y,const char *pStr,unsigned char bg)
  121. {
  122.         unsigned char i;
  123.         unsigned int strLen = strlen(pStr);        //字符串长度用 strlen(); 类型长度 sizeof();
  124.         if(strLen<=0||x>15||y>3) return; //超出范围
  125.        
  126.         if(strLen+x>16) strLen = 16-x;
  127.         for(i=0;i<strLen;i++){ //只在一行显示,超出部分丢弃
  128.                 LCDdat[16*y+x+i] = pStr[i];
  129.         }
  130.         LCD_SetBG(x,y,strLen,bg);
  131. }


  132. //******************** 显示数字 ***********************//
  133. //**  x:横坐标(0~15)  y:纵坐标(0~3)  
  134. //**  param:
  135. //**  (bit(7) 0:十进制显示 1:十六进制显示)
  136. //**  (bit(6~5) 00:右对齐 01:左对齐 10:中间对齐)
  137. //**  (bit(4~0)显示的长度0~31 0:显示全部)
  138. //**  fill: 空白处填充的字符,注意转义字符
  139. void LCD_ShowNumber(unsigned char x,unsigned char y,long num,unsigned char param,char fill,unsigned char bg)
  140. {
  141.         unsigned char i;
  142.         char strBuff[32];        //一行字符缓存
  143.         char disBuff[32];        //一行字符缓存用于显示
  144.         int strLen = 0;
  145.         unsigned char disLen = (param&DISP_MASK);
  146.        
  147.         if((x>15)||(y>3)) return; //超出范围
  148.        
  149.         if(param&FORMAT_MASK){ //十六进制显示
  150.                 strLen = sprintf(strBuff,"%lX",num);
  151.         }
  152.         else{ //十进制显示
  153.                 strLen = sprintf(strBuff,"%ld",num);
  154.         }
  155.        
  156.         if(strLen<=0) return; //错误
  157.        
  158.         if(disLen==DISP_ALL) disLen = strLen; //数据长度为0则全部显示
  159.        
  160.         if((param&ALIGN_MASK)==ALIGN_R){//右对齐
  161.                 for(i=0;i<disLen;i++){
  162.                         if(i<strLen) disBuff[disLen-1-i] = strBuff[strLen-1-i];
  163.                         else disBuff[disLen-1-i] = fill;
  164.                 }
  165.         }
  166.         else if((param&ALIGN_MASK)==ALIGN_L){//左对齐
  167.                 for(i=0;i<disLen;i++){
  168.                         if(i<strLen) disBuff[i] = strBuff[i];
  169.                         else disBuff[i] = fill;
  170.                 }
  171.         }
  172.         else if((param&ALIGN_MASK)==ALIGN_M){//中间对齐
  173.                 uint8_t disM = (disLen>>1); //显示窗口的中间位置
  174.                 uint8_t strM = (strLen>>1); //数据的中间位置
  175.                 for(i=0;i<disM;i++){ //前半部分  右对齐
  176.                         if(i<strM) disBuff[disM-1-i] = strBuff[strM-1-i];
  177.                         else disBuff[disM-1-i] = fill;
  178.                 }
  179.                 for(i=disM;i<disLen;i++){ //后半部分 左对齐
  180.                         if(strM+i-disM<strLen) disBuff[i] = strBuff[strM+i-disM];
  181.                         else disBuff[i] = fill;
  182.                 }
  183.         }
  184.         disBuff[disLen] = '\0'; //末尾加结束符
  185.         LCD_ShowString(x,y,disBuff,bg);
  186. }

  187. /**********************************
  188.           LCD初始化
  189. **********************************/

  190. void LCD_Init(void)
  191. {
  192.         memset(LCDdat,' ',sizeof(LCDdat));
  193.         memset(LCDdat_bak,0x00,sizeof(LCDdat_bak));
  194.         memset(SetWdat,0x00,sizeof(SetWdat));       
  195.         memset(SetWdat_bak,0x00,sizeof(SetWdat_bak));
  196.        
  197.         LCD_RST_0;         delay_ms(100);
  198.         LCD_RST_1;         //delay_ms(100);//复位
  199.         write(0,0x30);  //8 位介面,基本指令集
  200.         write(0,0x0c);  //显示打开,光标关,反白关
  201.         write(0,0x01);  //清屏,将DDRAM的地址计数器归零
  202. //        delay_ms(100);
  203.         LCD_ClearGM();
  204.        
  205. //        LCD_SetBG(3,1,5,1);
  206. }


复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出110入8汤圆

2
发表于 2020-4-20 12:47:48 | 只看该作者
兄台,能丢到github或者gitee上吗?

出0入0汤圆

3
发表于 2020-4-20 15:58:12 | 只看该作者
谢谢分享,LCD12864不好用,绘图模式刷屏速度太慢了

出0入55汤圆

4
 楼主| 发表于 2020-4-21 02:11:12 | 只看该作者
angler12 发表于 2020-4-20 12:47
兄台,能丢到github或者gitee上吗?

没有github或者gitee。。。真不好意思。不是专业的

出0入55汤圆

5
 楼主| 发表于 2020-4-21 02:13:05 | 只看该作者
flash3g 发表于 2020-4-20 15:58
谢谢分享,LCD12864不好用,绘图模式刷屏速度太慢了

全屏刷是比较慢。但上面的程序不是全屏刷,而且速度已经飞快了。

出0入0汤圆

6
发表于 2020-4-21 10:00:40 | 只看该作者
谢谢提供

出0入137汤圆

7
发表于 2020-4-21 10:03:29 | 只看该作者
现在这种屏用的人少了吧?手里还有几十个全新的。

出0入0汤圆

8
发表于 2020-4-21 12:15:27 | 只看该作者
mark一下,看看有没有机会用上。

出0入0汤圆

9
发表于 2020-4-21 12:37:19 | 只看该作者
flash3g 发表于 2020-4-20 15:58
谢谢分享,LCD12864不好用,绘图模式刷屏速度太慢了

我都是开缓冲100ms刷一次。

出0入76汤圆

10
发表于 2020-4-21 14:57:00 | 只看该作者
以前也写过一个串口驱动的LCD12864 (记得用的是北京青云的LCD显示屏)

出0入4汤圆

11
发表于 2020-4-21 21:01:00 来自手机 | 只看该作者
问一下,arduino的库可以直接放mdk下面用么?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 09:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表