使用Proteus模拟操作HDG12864F-1液晶屏

六眼飞鱼酱① 提交于 2020-03-05 12:02:45

  在Proteus中模拟了89C52操作HDG12864F-1液晶屏,原理图如下:

  一、HDG12864F-1官网信息

  该液晶屏是Hantronix的产品,官网上搜索出这个型号是系列型号中的一种,各种型号间的区别主要是尺寸不同、有无背光、背光颜色等等。

 

   下面是官网中几个手册的链接:

二、基本操作函数

  根据几个手册提供的信息,“写命令”和“写数据”函数如下:

 1 sbit cs = P1^7;//-cs,片选,低电平有效
 2 sbit rst = P1^6;//-rst,复位,低电平有效
 3 sbit a0 = P1^5;//写命令、写数据控制位。1=Display data; 0=Control data;
 4 sbit wr = P1^4;//-Write serial data,写串口数据,低电平有效
 5 sbit rd = P1^3;//-Read serial data,读串口数据,低电平有效
 6 sbit scl = P1^2;//Shift clock input,时钟输入
 7 sbit si = P1^1;//Serial data input,串口数据输入
 8 //手册中说了,各种操作都是ns级,不用各种等待命令,下面操作也没有写入等待功能
 9 //写命令
10 void wrt_cmd(unsigned char command)
11 {
12     unsigned char i = 8;
13     cs = 0;
14     a0 = 0;//0=Control data,命令置0
15     wr = 0;
16     rd = 1;
17     while(i--){
18     scl = 0;
19     si = (bit) (command & 0x80);//先写高位
20     scl = 1;
21     command <<= 1;
22     }
23     scl = 0;
24 }
25 //写数据
26 void wrt_dt(unsigned char data_)
27 {
28     unsigned char i = 8;
29     cs = 0;
30     wr = 0;
31     a0 = 1;//1=Display data,写数据置1
32     rd = 1;
33     while(i--){
34     scl = 0;
35     si = (bit) (data_ & 0x80);
36     scl = 1;
37     data_ <<= 1;
38     }
39     scl = 0;
40 }

三、显存和屏幕的对应关系

  手册中有描述,不太好理解,网上也查了不少,还是用自己的方法好理解一些。

  在详细说明对应关系前,必须提到该芯片有正、反两种写入方向,ADC Select (Segment Driver Direction Select),见完整版手册第50页。厂家居然把“从屏幕右边开始写”称为“正”,看着别扭。不过我先看的是“正”的,下面就先“正”着说。手册中对正反的描述如下:

 

  1. 屏幕从左到右分成128列,分别是column0~column127,后面简称c0~c127,每一列对应着屏幕上横向的一个点;同时,从上到下分成8行,手册中将每一行称之为1个Page,每个Page对应着一个字节,恰好8个bit,每个bit对应着屏幕上纵向的一个点,8个Page一共8*8=64个点。这样,就将屏幕分成了128*64个点。“使用注意事项”中给出了图示:

 

  2. 大格局说清楚了,再来说说写RAM的顺序,我在这里绕了好长时间,利用下面的图形反复校对终于搞清楚了。图中:1-代表亮点,空白(0)-代表暗点。

  下图一共有8*8的点阵4个,形成了一个16*16的大点阵,一个16*16的大点阵可以显示一个汉字。

 

   如果从屏幕右上角开始显示汉字,则有:

  • 右上角的点阵代表汉字的右上角,其中每一列8个点构成一个Byte,下面的点是高位,上面的点是低位,例如:代表C0列的Byte为1010 1011B=abH。
  • 因为写数据的时候是从右边开始,所以字模数组的顺序也是从右边开始的。例如右上角8*8点阵形成的数组为:N[0],N[1],N[2],N[3],N[4],N[5],N[6],N[7]。
  • 写完一个Byte后,控制器将列坐标自动加1,因此按0~7的顺序写完这个数组后,在屏幕的右上角就完成了一个汉字右上四分之一的显示。
  • 接着连续写汉字左上四分之一,就是写N[8]~N[15]共8个字节。到这里一个汉字的上半部分就写完了。
  • 接下来就是更改Page了(相当于更改纵向位置)。刚才写汉字的上半部分时,纵坐标是在Page=0的位置,现在需要将纵坐标设置成Page=1;同时,也要将列重新设置为0。这样再连续写N[16]~N[31]共16个Byte后,一个完整的汉字就在屏幕上写好了。

  这段功能的主程序和实际效果如下:

 1 #include "HDG12864F1.h"
 2 void main(void)
 3  {  unsigned char i;
 4     unsigned char chinachar[32] = {
 5       0xab,0xab,0xab,0xab,    0xab,0xab,0xab,0xab,
 6       0x55,0x55,0x55,0x55,    0x55,0x55,0x55,0x55,
 7       0xaa,0xaa,0xaa,0xaa,    0xaa,0xaa,0xaa,0xaa,
 8       0xd5,0xd5,0xd5,0xd5,    0xd5,0xd5,0xd5,0xff
 9     };
10     //HDG12864F1_Direction(DISPLAY_LEFT_TO_RIGHT);
11     HDG12864F1_SetColumnAddress(0);//设开始写的横向坐标为C0
12     HDG12864F1_SetPageAddress(0);//设开始写的纵向坐标为Page0
13     for(i=0; i<16; i++){
14       HDG12864F1_WriteData(chinachar[i]);//连续写汉字的上半部分
15     }
16     HDG12864F1_SetColumnAddress(0);//再将横向坐标设为C0
17     HDG12864F1_SetPageAddress(1);//将纵向坐标设为Page1
18     for(i=16; i<32; i++){
19       HDG12864F1_WriteData(chinachar[i]);//连续写汉字的下半部分
20     }
21 }    

 

   其中,用到的几个函数如下。设置纵向位置、列位置两个函数,分别根据手册要求编写,见下图中(3)Page address set和(4)Column address set。

 1 //设置列位置,其中参数address:0~127
 2 void HDG12864F1_SetColumnAddress(unsigned char address)
 3 {  //写列要分成两步走,先写高四位,再写低四位
 4     wrt_cmd(0x10 + (address >> 4 & 0x0f));//C中右移是算术右移,必须&0x0f去掉高4位才能得到正确的结果
 5     wrt_cmd(address & 0x0f);
 6 }
 7 //设置纵向位置,其中参数pageAddress:0~8
 8 void HDG12864F1_SetPageAddress(unsigned char pageAddress)
 9 {
10     wrt_cmd(0xb0 + pageAddress);
11 }
12 //写数据
13 void HDG12864F1_WriteData(unsigned char data_)
14 {
15     wrt_dt(data_);
16 }

  3. 上面说的内容都是以“从右侧开始写入”为条件的,也就是厂家所说的“正”着来,这不太符合我们日常的习惯,厂家也考虑到了这一点,并且提供了一个功能,让用户决定从左还是从右开始写起,就是上图中(9)Display normal/reverse。为了更加清楚,定义了两个宏,使用的时候直接把参数direction换成需要的宏即可。

1 #define DISPLAY_LEFT_TO_RIGHT    0
2 #define DISPLAY_RIGHT_TO_LEFT    1
3 void HDG12864F1_Direction(unsigned char direction)
4 {
5     wrt_cmd(0xa0+direction);
6 }

  将main()函数第10行注释的“//”去掉,再次运行程序得到字形呈镜面对称。

 

  4. 另外,还验证了上2图中功能(2)Display start line set,该功能的作用是对写好的屏幕内容向上滚屏,滚出上边的部分会从屏幕下边冒出来,我设置了一个循环,对该函数的参数从0~63逐次加1,刚刚开始运行后截屏得到的图形如下。

1 //参数line取值范围0~63
2 void HDG12864F1_SetStartLine(unsigned char line)
3 {
4     wrt_cmd(0x40 + line);
5 }

 

   5. 其他功能还有很多,没有逐个试验,下面贴出功能表的下半部分,需要时可参考。

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!