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

[复制链接]
 楼主| freeelectron 发表于 2021-12-30 09:57 | 显示全部楼层 |阅读模式
本帖最后由 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 为 132
65) ;
显示对比度,内部寄存器调节(软件调对比度);
占空比 1/64 偏压比 1/9;
工作温度 -20 到+70 度。


3、显存映射

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_20,color_FFFFFF,t_70,g_se,x_16.jpg
可以看出列定义为0-127,行地址范围以8个像素为-个单 位定义为(0-7)页,共64。


4、管脚说明

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_16,color_FFFFFF,t_70,g_se,x_16.jpg
可以看出,29脚的高低电平决定了使用并口还是串口方式。


5、串行方式驱动时序

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_20,color_FFFFFF,t_70,g_se,x_16.jpg
从图中可以看出:
在CSB拉低的时候,进行数据或命令传输;
RS为高的时候传输数据,RS为低的时候传输指令;
SCL为时钟;
SDA为数据。


6、串行写流程

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_20,color_FFFFFF,t_70,g_se,x_16.jpg
首先拉低CSB;
通过设置RS的电平,选择写数据或指令;
SCL拉低,bit7传输,SCL拉高,依次类推,从bit7到bit0完成一个字节的传输;
最后拉高CSB。


7、写入数据流程

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_18,color_FFFFFF,t_70,g_se,x_16.jpg
可以看出,写数据之前,要先设置写入的地址,这里有列地址(0-127列),页地址(0-7页),同时要注意,列地址会自加。


8、指令说明

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_20,color_FFFFFF,t_70,g_se,x_16.jpg


9、原理设计

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_18,color_FFFFFF,t_70,g_se,x_16.jpg


10、程序驱动

本文使用GD32驱动LCD。


10.1、io口定义以及初始化
  1. #define LCD_SCL_PORT         GPIOB
  2. #define LCD_SCL_PIN          GPIO_PIN_6

  3. #define LCD_SDA_PORT         GPIOB
  4. #define LCD_SDA_PIN          GPIO_PIN_7

  5. #define LCD_CSB_PORT         GPIOB
  6. #define LCD_CSB_PIN          GPIO_PIN_11

  7. #define LCD_RST_PORT         GPIOC
  8. #define LCD_RST_PIN          GPIO_PIN_11

  9. #define LCD_A0_PORT          GPIOC
  10. #define LCD_A0_PIN           GPIO_PIN_13

  11. #define LCD_BKLED_PORT       GPIOA
  12. #define LCD_BKLED_PIN        GPIO_PIN_6

  13. #define LCD_CMD                       1
  14. #define LCD_DATA             0
  15.                                                
  16. #define PORT(port)                LCD_##port##_PORT
  17. #define PIN(pin)                  LCD_##pin##_PIN
  18.                                                
  19. #define LCD_PIN_OUT(pin,level) { if(level)                               \
  20.                                                              { gpio_bit_set(PORT(pin),PIN(pin));}    \
  21.                                                              else                                    \
  22.                                                              { gpio_bit_reset(PORT(pin),PIN(pin));}  \
  23.                                }

10.2、LCD写
  1. /*
  2. ismcd:高为数据,低为指令
  3. */
  4. static void LcdWrite(uint8_t iscmd ,uint8_t data)
  5. {
  6.         uint8_t  i;
  7.        
  8.         LCD_PIN_OUT(CSB,0);
  9.         if(iscmd)
  10.         {
  11.                 LCD_PIN_OUT(A0,0);
  12.         }
  13.         else
  14.         {
  15.                 LCD_PIN_OUT(A0,1);
  16.         }
  17.         for(i=0;i<8;i++)
  18.         {
  19.                 LCD_PIN_OUT(SCL,0);
  20.                  DelayUs(10);
  21.                 if(data&0x80)
  22.                 {
  23.                         LCD_PIN_OUT(SDA,1);
  24.                 }
  25.                 else
  26.                 {
  27.                         LCD_PIN_OUT(SDA,0);
  28.                 }
  29.                 LCD_PIN_OUT(SCL,1);
  30.                 DelayUs(10);
  31.                 data=data<<1;
  32.         }
  33.        
  34.         LCD_PIN_OUT(CSB,1);
  35. }

10.3、LCD设置地址
  1. void LcdAddress(uint8_t  page,uint8_t column)
  2. {
  3.         LcdWrite(LCD_CMD,0xb0+page);
  4.         LcdWrite(LCD_CMD,((column>>4)&0x0f)+0x10); //设置列地址的高4 位
  5.         LcdWrite(LCD_CMD,((column>>0)&0x0f)+0x00); //设置列地址的低4 位
  6. }

10.4、LCD清屏
  1. /*全屏清屏*/
  2. void LcdClearScreen(void)
  3. {
  4.         uint8_t  i,j;
  5.        
  6.         for(i=0;i<8;i++)
  7.         {
  8.                 LcdAddress(i,0);
  9.                 for(j=0;j<128;j++)
  10.                 {
  11.                         LcdWrite(LCD_DATA,0x00);
  12.                 }
  13.         }
  14. }

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


10.5、LCD显示边框
  1. void LcdDispBK(void)
  2. {
  3.         uint8_t  i;
  4.        
  5.         //上框
  6.         LcdAddress(0,0);
  7.         for (i=0;i<128;i++)
  8.         {
  9.                 LcdWrite(LCD_DATA,0x01);
  10.         }
  11.         //下框
  12.         LcdAddress(7,0);
  13.         for (i=0;i<128;i++)
  14.         {
  15.                 LcdWrite(LCD_DATA,0x80);
  16.         }
  17.        
  18.         //左框
  19.         for(i=0;i<8;i++)
  20.         {
  21.                 LcdAddress(i,0);
  22.                 LcdWrite(LCD_DATA,0xff);
  23.         }
  24.         //右框
  25.         for(i=0;i<8;i++)
  26.         {
  27.                 LcdAddress(i,127);
  28.                 LcdWrite(LCD_DATA,0xff);
  29.         }
  30. }

10.6、LCD显示8*16字符串
  1. void LcdDispStr8x16(uint8_t reverse,uint8_t page,uint8_t column,uint8_t *str)
  2. {
  3.         uint16_t i=0,j;                       
  4.         uint8_t zk[16];

  5.         while(str[i]>0x00)
  6.         {
  7.                 if((str[i]>=0x20)&&(str[i]<=0x7e))
  8.                 {
  9.                         extern uint8_t  GT20L16S1YGetAsciiData( uint8_t ASCIICode, uint32_t BaseAdd, uint8_t* S1YDZ_Data );

  10.                         GT20L16S1YGetAsciiData( str[i], 0x3b7c0, zk);
  11.                        
  12.                         LcdAddress(page,column); //上半部分
  13.                         for(j=0;j<8;j++)
  14.                         {
  15.                                 if (reverse==1)
  16.                                 {
  17.                                         LcdWrite(LCD_DATA,zk[j]);
  18.                                 }
  19.                                 else
  20.                                 {
  21.                                         LcdWrite(LCD_DATA,~(zk[j]));
  22.                                 }
  23.                         }
  24.                         LcdAddress(page+1,column);//下半部分
  25.                        
  26.                         for(j=0;j<8;j++)
  27.                         {
  28.                                 if (reverse==1)
  29.                                 {
  30.                                         LcdWrite(LCD_DATA,zk[j+8]);
  31.                                 }
  32.                                 else
  33.                                 {
  34.                                         LcdWrite(LCD_DATA,~(zk[j+8]));
  35.                                 }
  36.                         }
  37.                         i++;
  38.                         column+=8;
  39.                 }
  40.         }
  41. }

10.7、LCD显示16*16汉字
  1. void LcdDispStr16x16(uint8_t reverse,uint8_t page,uint8_t column,uint8_t *str)
  2. {
  3.         uint16_t i=0,j;
  4.         uint8_t zk[32];

  5.         while(str[i]>0x00)
  6.         {
  7.                 extern  void GT20L16S1YGetGb2312Data( uint8_t MSB, uint8_t LSB, uint8_t* S1YDZ_Data );

  8.                 GT20L16S1YGetGb2312Data( str[i], str[i+1], zk );
  9.                
  10.                 LcdAddress(page,column); //上半部分
  11.                 for(j=0;j<16;j++)
  12.                 {
  13.                         if (reverse==1)
  14.                         {
  15.                                 LcdWrite(LCD_DATA,zk[j]);
  16.                         }
  17.                         else
  18.                         {
  19.                                 LcdWrite(LCD_DATA,~(zk[j]));
  20.                         }
  21.                 }
  22.                 LcdAddress(page+1,column);//下半部分
  23.                
  24.                 for(j=0;j<16;j++)
  25.                 {
  26.                         if (reverse==1)
  27.                         {
  28.                                 LcdWrite(LCD_DATA,zk[j+16]);
  29.                         }
  30.                         else
  31.                         {
  32.                                 LcdWrite(LCD_DATA,~(zk[j+16]));
  33.                         }
  34.                 }
  35.                 i++,i++;
  36.                 column+=16;
  37.         }
  38. }

10.8、LCD初始化
  1. void LcdInit(void)
  2. {
  3.         LcdIoInit();
  4.        
  5.         LCD_PIN_OUT(RST,0);
  6.         DelayUs(20);
  7.         LCD_PIN_OUT(RST,1);     /*复位完毕*/
  8.         DelayUs(20);
  9.         LcdWrite(LCD_CMD,0xe2); /*软复位*/
  10.         DelayUs(50);
  11.         LcdWrite(LCD_CMD,0x2c); /*升压步聚1*/
  12.         DelayUs(50);
  13.         LcdWrite(LCD_CMD,0x2e); /*升压步聚2*/
  14.         DelayUs(50);
  15.         LcdWrite(LCD_CMD,0x2f); /*升压步聚3*/
  16.         DelayUs(50);
  17.        
  18.         LcdWrite(LCD_CMD,0x24); /*粗调对比度,可设置范围0x20~0x27*/
  19.         LcdWrite(LCD_CMD,0x81); /*微调对比度*/
  20.        
  21.         LcdWrite(LCD_CMD,0x1b); /*0x1a,微调对比度的值,可设置范围0x00~0x3f 1f*/
  22.         LcdWrite(LCD_CMD,0xa3); /*偏压比(bias),0xa2:1/9   0xa3:1=1/7    */
  23.        
  24.         LcdWrite(LCD_CMD,0xc8); /*行扫描顺序:从上到下*/
  25.         LcdWrite(LCD_CMD,0xa0); /*列扫描顺序:从左到右*/
  26.         LcdWrite(LCD_CMD,0x40); /*起始行:第一行开始*/
  27.        
  28.         LcdWrite(LCD_CMD,0xaf); /*开显示*/
  29.         LcdClearScreen();
  30.         LcdDispBK();

  31.         LcdDispStr8x16(0,2,20,(uint8_t*)"display,test") ;
  32.         LcdDispStr16x16(1,5,50,(uint8_t*)"你好");
  33. }


注:如果显示不清晰,可以通过偏压比,对比度来调节。


11、显示测试

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAZnJlZW1vdGU=,size_12,color_FFFFFF,t_70,g_se,x_16.jpg
图中显示了中文、英文、边框,还实现了反显。




您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:stm32/LoRa物联网:304350312

65

主题

785

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:stm32/LoRa物联网:304350312

65

主题

785

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部