⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 5.txt

📁 LCD 的C语言驱动程序
💻 TXT
📖 第 1 页 / 共 3 页
字号:

show_asc(uchar ch);

//***********************

//初始化液晶

uchar lcdlight=32; 

void initlcd(void)

{   P2=0x00;     //P2作为总线时,其寄存器的值对总线没有影响。

                 //初始化为0,是为了更好的配合液晶的6800总线。motorola的液晶内部固定了6800总线方式。

                             //如果液晶是8080总线,则无需这样做。     

       wricmd(0x2f);//SET POWER CONTROL,开启一系列与电源有关的功能

       wricmd(0x20);//REGULATOR RESISTOR SELECT,内部反馈增益最小

       wricmd(0x81);

       wricmd(lcdlight);设置对比度值

       wricmd(0x40);//设置初始显示线,从哪里开始是玻璃上的布线决定的

       wricmd(0xa0);//ADC=0(SEG1~SEG132) 

       wricmd(0xc8);//SHL=0(COM1~COM64) 

       wricmd(0xa2);//设置LCD BIAS为1/9

       cls(9);//全部清除,包括icon

       wricmd(0xaf);//开启显示,也就是把GDRAM上的数值显示到屏上

       setcursor(0,0);//设置光标到左上角

}

*****************************************/



到这里,就正是进入我们的初始化了。什么?弄了半天你还没有讲初始化啊?各位看官不要着急,此初始化非彼初始化也。刚才我们讲的都是整个程序的初始化,而现在我们进入的是液晶屏的初始化。让我们看看这个过程吧。首先是uchar lcdlight=32,顾名思义,这个参数的作用就是调节lcd对比度的拉。motorola的液晶默认对比度为32。先让lcdlight=32,到时候利用wricmd函数,直接一个wricmd(lcdlight)语句,多方便~^_^。

闲话少说,接着往下看。下面是一个initlcd函数,这是可是如假包换的液晶初始化函数。液晶在每次上电使用都需要初始化,而大多数初始化程序我们都可以不去理会,因为那些都是按照说明书所说的,用于设置COM数和SEG数还有BIAS值的。

这里再解释一下P2=0x00;的作用。开始的时候我们就说过,这个液晶使用的是6800总线,这段,其实是为了兼容6800总线加上的,LCD的D/C脚在一开始的时候应该设为0,也就是写成:P22=0;就可以了,P22就是接到LCD的D/C脚上的。另外再提醒一点,一些必须的值,如COM,SEG,BIAS,显示模式等,在使用中这些设置用户是不应该改变的。

到这里,LCD初始化正式完成,已经可以供用户正常使用了。















/*****************************************

show_asc(uchar ch)

{

       uint addr;

       uchar hzdata[16];

       uchar xdot,i;

       addr=16*ch;  



       readeprom(addr,hzdata,16); //读出16个字节的点阵数据

       xdot=cursor.x*8;                  

       wricmd(0xb0+cursor.y);    //将y位置送入液晶

       wricmd(xdot & 0x0f);          //将x位置送入液晶

       wricmd( 0x10 | (xdot >> 4 ));   

       wricmd(0xe0);

       for(i=0;i<8;i++)

       {

              wridata(hzdata[i]);                //写上半个字符

       }

       wricmd(0xee);

       wricmd(0xb0+cursor.y+1); 

       wricmd(xdot & 0x0f);

       wricmd(0x10 | (xdot >> 4 ));   

       wricmd(0xe0);

       for(;i<16;i++)                      //写下半个字符

       {

              wridata(hzdata[i]);

       }

       wricmd(0xee);

}

*****************************************/

要理解这段程序,必须先知道点阵表示的含义。我们知道,字母和汉字是按字模位信息显示的,那如何得到汉字的字模信息呢?难道要我们自己去做?NO。DOS前辈们经过艰辛的努力,将制作好的字模放到了一个个标准的库中以免去后辈的麻烦,这就是点阵字库文件。一般我们使用16*16的点阵宋体字库,所谓16*16,是每一个汉字在纵、横各16点的区域内显示的,前一个16表示列,后一个十六表示行。不过后来又有了HZK12、HZK24,HZK32和HZK48字库及黑体、楷体和隶书字库。

这段程序是用来在当前光标位置显示一个6×12 点阵的ASC码字符的。其实标准的ASC码字符应该是8×16点阵区域表示,这也就是为什么我们常说“一个汉字占据两个字符位”的原因。Ch表示的是asc字符的值。首先说明一点,一个ASC字符分两部分显示,也就是说,把分为上下两个“半ASC码字符”。汉字同样应该如此显示。当然这只是我们目前介绍的这个lcd的特性。如果你使用的是别的种类,千万不要生搬硬套,一定要仔细阅读说明书。

再回头看程序。首先就是一堆定义,无符号整形数addr表示的是点阵在flash中的物理位置,表示ASC码字符‘1’的字符点阵占据的物理位置是0-15。为什么?你看,16*8点阵区域,一个点用1bit表示,‘0’就是灭,‘1’就是亮,那么总共128bit,是不是就是16byte?同理,字符‘2’是16-30,以此类推。所以addr=16*ch。比如我传递进来的ch是4,则addr为64。而hzdata这个数组是用来存储读出的数据的。Xdot表示的是横向点位置,在下面我们可以知道它的计算公式是cursor.x*8,就是光标横坐标值乘以8。由于之前我们将光标设置在左上角,所以cursor.x为0,因此此时横向点位置也为0。如果我们已经显示了一个ASC字符,此时的cursor.x就应该为1,那么xdot就应该为8:这应该很好理解,从点阵区域的大小我们可以知道一个ASC码字符从横坐标上看占用的是8个点(0-7),下一个ASC码字符当然应该从8开始拉。

接下来是readeprom(addr,hzdata,16)这个函数。什么意思呢?由于它是属于另外一个.c文件,这里只是给出原型:

Readeprom函数原型如下:

readeprom(ulong ad,uchar *pst,uint n)

{

       union {ulong addr_l;struct {uint a32;uint a10;}addr_i;struct {uchar a3;uint a21;uchar a0;}addr;} address;

      uint i;

       uchar xdata *flash;             

       P1=0xff;                      //P1口如被占用暂停读取

       while(P1!=0xff);

       address.addr_l=ad;

       P1=(P1&0xc0) | (address.addr.a21/0x20);   //设置bank线,每块8K字节

       flash=0x8000+address.addr_i.a10%0x2000; //flash窗口地址范围0x8000-0x9ffff

       for(i=0;i  读N个字节//

       {

              *(pst++)=*(flash++);

              if(flash==0xa000) //如果地址跨页则翻到下一个bank

              {

                     P1++;

                     flash=0x8000;

              }

       }

}

在这里我们就不单独解释了,只是说说他的大概作用,即读N个flash中的字节,每次最多65535字节。入口参数的含义分别是:ulong ad为字符在flash中的物理地址,uchar *pst表示读出来放在内存中的指针首位置,uint n表示读出多少个字节。

也就是说,readeprom(addr,hzdata,16)后,我们已经把表示ch需要用的16个字节传到了hzdata数组中,到时候就可以直接拿来用了。

在接下来是送x,y的位置,为什么y位置是0xb0+cursor.y呢?0xb0是一个命令指令,表示设置page。刚才说了,一个page是8行组成,也就是说高8个点,也就是说一个字符或者汉字都应该由两个page来提供数据。刚才还说了,显示是分上下两半部分组成的,所以先page设置成0xb0+cursor.y,然后再设置成0xb0+cursor.y+1,这样是不是先后选中两个page?嘿嘿,很顺理成章吧?由于我们这个系列lcd默认是132点宽,所以横向点的数目(也就是列地址)至少需要8位表示才够了(7位只有128),但是x位置送的列地址是xdot & 0x0f,高8位的4个0是命令标志,只有低4位,明显不能表示完。怎么办呢?我们就分两步送,先送低4位,再说高四位。忘了这个设置列地址的指令?回头去看看cls函数中的内容吧^_^。高4位怎么送?wricmd( 0x10 | (xdot >> 4 ));这是设置高4位列地址的指令。低四位表示列的高地址。

    继续。wricmd(0xe0)的作用是设置成读-改-写模式。这个前面已经介绍过了。在接下来就是送我们要送显的数据到GDDRAM中的过程了,这个过程很简单,大体就是一列一列的送,送了一个字节后列GDDRAM中的列地址自动加一,数组下标也加一,然后再继续送,其实我们从cls函数的过程中就能领悟到。送完上半部分,高低列地址重新送,page+1,再重复这个过程。具体指令就不介绍了,聪明的你一定能够理解~呵呵。 

/*****************************************

show_hz(uchar ch1, uchar ch2)

{

       ulong addr;

       uchar hzdata[32];

       uchar xdot,i;

       if (ch1>=0xb0)                    //寻址汉字在flash中的物理位置

       {

              addr=(ch1-0xb0)*94+ ch2-0xa1;

              addr=addr*32+0x5a40;

       }

       else

       {

              addr=(ch1-0xa1)*94+ ch2-0xa1;

              addr=addr*32+0x800;

       }



       readeprom(addr,hzdata,32); //读出32个汉字点阵数据



       xdot=cursor.x*8;                  //计算X位置

       wricmd(0xb0+cursor.y); 

       wricmd(xdot & 0x0f);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -