写在开始:(借此灌下水^_^ ) 之前,发了一个帖子,大意是看见杀手和水剑写的帖子,心里也痒痒了,想写一写以前学习单片机过程中的一些经历,希望能给大家一点参考。无奈最近时间很是紧张,因此,一直都没能着手整理。本打算星期六写的,但是接到一个朋友的电话,说想买CPLD的开发板。于是,计划被迫打乱,只好先陪他去电子市场买板子。回来之后,虽然头很晕(坐车的原因),但是不能再拖了,否则留给大家一个只说不做的印象就不好了。虽然头晕,但是下面的写出来的东西可不晕。OK,LET’S GO !
1602字符液晶在实际的产品中运用的也比较多了,前几天留意了一下,发现宿舍门前的自动售水机就是采用的1602液晶进行显示的。而且对于单片机的学习而言,掌握1602的用法是每一个学习者必然要经历的过程。在此,我将使用1602过程中遇到的问题以及感受记录下来,希望能够给初学者带来一点指导,少走一点弯路。
所谓1602是指显示的内容为16*2,即可以显示两行,每行16个字符。目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
下面我们来驱动1602吧在1602的上排显示“LCD1602 check ok”下排显示“study up”程序中没有用到忙检测,而是用的是延时函数来替代忙检测
- #include<reg52.h> //包含头文件,这个嘛,就不用多说了~~
- #define uint unsigned int //预定义一下
- #define uchar unsigned char
- sbit rs=P3^5; //1602的数据/指令选择控制线
- sbit rw=P3^6; //1602的读写控制线
- sbit en=P3^7; //1602的使能控制线
- /*P2口接1602的D0~D7,注意不要接错了顺序,我以前可在这上面吃过亏~*/
- uchar code table[]="LCD1602 check ok"; //要显示的内容1放入数组tablel
- uchar code table1[]="study up"; //要显示的内容2放入数组table1
- void delay(uint n) //延时函数
- {
- uint x,y;
- for(x=n;x>0;x--)
- for(y=110;y>0;y--);
- }
- void lcd_wcom(uchar com) //1602写命令函数
- {
- rs=0; //选择指令寄存器
- rw=0; //选择写
- P2=com; //把命令字送入P2
- delay(5); //延时一小会儿,让1602准备接收数据
- en=1; //使能线电平变化,命令送入1602的8位数据口
- en=0;
- }
- void lcd_wdat(uchar dat) //1602写数据函数
- {
- rs=1; //选择数据寄存器
- rw=0; //选择写
- P2=dat; //把要显示的数据送入P2
- delay(5); //延时一小会儿,让1602准备接收数据
- en=1; //使能线电平变化,数据送入1602的8位数据口
- en=0;
- }
- void lcd_init() //1602初始化函数
- {
- lcd_wcom(0x38); //8位数据,双列,5*7字形
- lcd_wcom(0x0c); //开启显示屏,关光标,光标不闪烁
- lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
- lcd_wcom(0x01); //清屏
- }
- void main() //主函数
- {
- uchar n,m=0;
- lcd_init(); //液晶初始化
- lcd_wcom(0x80); //显示地址设为80H(即00H,)上排第一位
- for(m=0;m<16;m++) //将table[]中的数据依次写入1602显示
- {
- lcd_wdat(table[m]);
- delay(200);
- }
- lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位
- for(n=0;n<8;n++) //将table1[]中的数据依次写入1602显示
- {
- lcd_wdat(table1[n]);
- delay(200);
- }
- while(1); //动态停机
- }
复制代码
程序写好后烧写进单片机,现在让我们看看效果吧
这就是显示的效果,你做成功了吗?
下面让我们来看看如何显示一个自定义的字符吧
我们从CGROM表上可以看到,在表的最左边是一列可以允许用户自定义的CGRAM,从上往下看着是16个,实际只有8个字节可用。它的字符码是00000000-00000111这8个地址,表的下面还有8个字节,但因为这个CGRAM的字符码规定0-2位为地址,3位无效,4-7全为零。因此CGRAM的字符码只有最后三位能用也就是8个字节了。等效为0000X111,X为无效位,最后三位为000-111共8个。
如果我们要想显示这8个用户自定义的字符,操作方法和显示CGROM的一样,先设置DDRAM位置,再向DDRAM写入字符码,例如“A”就是41H。现在我们要显示CGRAM的第一个自定义字符,就向DDRAM写入00000000B(00H),如果要显示第8个就写入00000111(08H),简单吧!
好!现在我们来看怎么向这八个自定义字符写入字模。有个设置CGRAM地址的指令大家还记得吗?赶快再找出来看看。
从这个指令可以看出指令数据的高2位已固定是01,只有后面的6位是地址数据,而这6位中的高3位就表示这八个自定义字符,最后的3位就是字模数据的八个地址了。例如第一个自定义字符的字模地址为01000000-01000111八个地址。我们向这8个字节写入字模数据,让它能显示出“℃”
地址:01000000 数据:00010000 图示:○○○■○○○○
01000001 00000110 ○○○○○■■○
01000010 00001001 ○○○○■○○■
01000011 00001000 ○○○○■○○○
01000100 00001000 ○○○○■○○○
01000101 00001001 ○○○○■○○■
01000110 00000110 ○○○○○■■○
01000111 00000000 ○○○○○○○○
下面我们写一段程序让这8个自定义字符显示出一个心的图案: (由于上面那个显示程序已经有很详细的注释了,因此这个程序只对与上个程序不同的地方写注释)
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit rs=P3^5;
- sbit rw=P3^6;
- sbit en=P3^7;
- uchar code table[]={0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,
- 0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
- 0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
- 0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,
- 0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,
- 0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,
- 0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,
- 0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00};//心图案
- /*uchar code table1[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};//字符℃ */
- void delay(uint n)
- {
- uint x,y;
- for(x=n;x>0;x--)
- for(y=110;y>0;y--);
- }
- void lcd_wcom(uchar com)
- {
- rs=0;
- rw=0;
- P2=com;
- delay(5);
- en=1;
- en=0;
- }
- void lcd_wdat(uchar dat)
- {
- rs=1;
- rw=0;
- P2=dat;
- delay(5);
- en=1;
- en=0;
- }
- void lcd_init()
- {
- lcd_wcom(0x38);
- lcd_wcom(0x0c);
- lcd_wcom(0x06);
- lcd_wcom(0x01);
- }
- void main()
- {
- char m=0;
- lcd_init();
- lcd_wcom(0x40); //设定CGRAM地址
- for(m=0;m<64;m++) //将心型代码写入CGRAM中
- {
- lcd_wdat(table[m]);
- }
- lcd_wcom(0x85); //设定上排的显示位置
- for(m=0;m<4;m++) //显示心型图案的上半部分
- {
- lcd_wdat(m);
- }
- lcd_wcom(0xc5); //将显示坐标转移到下排和上排相对应的地方
- for(m=4;m<8;m++) //显示心型图案的下半部分
- {
- lcd_wdat(m);
- }
- while(1);
- }
复制代码 让我们一起来看看显示的效果吧~~
在绿底黑字液晶模块和蓝底白字液晶模块上分别显示的效果。
下面再为大家展示几种可能出现的问题
1:通电之后,程序也烧写进去了,但是1602就是不显示,只显示一排黑块(一般都是在上排8个小黑块,记得刚开始用1602液晶的时候,被这个整怕了~~),怎么样,你郁闷了吧,其实出现这种问题的原因无非以下几种:硬件连线上的错误,这种错误一般用万用表仔细检查后很容易找出来。第二种情况就是硬件连接上是正确的,那么此时出问题最大的就是程序上了,如果你用的是忙检测,看一下忙检测函数写对了没,如果用的是延时函数,那么看看延时的时间是否够长。再就是看看时序图,这点很重要的哦。如果硬件和软件都没有错,那么就要考虑1602是否坏了,但是出现这种情况的几率很小,如果遇到这种情况,你可以考虑去买彩票了~~
下面这种情况你遇到过吗?我遇到过了的,搞得我很是郁闷~~
我做的实验是要液晶显示ABC这三个字母,并且开光标,光标闪烁。大家可以在第一排的最后几位看到ABC和光标都已经显示出来了。但是为什么其它位会显示这么多8呢?嘿嘿~~郁闷吧。出现这种情况的原因就是在初始化液晶的时候,要把清屏指令放在最后面,否则就会出现上图这种情况。怎么样,第一次听说吧~不过,我不知道其它的液晶是否也有这个问题出现,至少我用的这块就有这种情况,但是我的另一个液晶则没有这种情况出现,不管是在一开始就清屏还是最后清屏。大家注意下就可以了,万一出现了这种情况,就会处理了~~
上面这张图是用1602作为显示的温度电子钟~~上面的年月日三个字就是用自定义字符的方法显示的。呵呵,怎么样~~到此1602的驱动基本上结束了,剩下的就靠大家自己去发挥了。
完整的Word格式文档51黑下载地址(共68页):
51单片机好学1602全过程C语言编程显示很全的哦.doc
(1.64 MB, 下载次数: 219)
|