基於51微控制器的LCD1602顯示
阿新 • • 發佈:2019-02-10
最近工作簽了,沒啥事,畢業設計題目也沒出來,打算重新學一下51微控制器,補補功課。今天看著 LCD1602 的
datasheet試著自己編寫,proteus模擬軟體沒有LCD1602,使用LM016來代替,先了解一下LCD1602的各引腳
功能。如下圖:
圖1 LCD1602 引腳圖
51微控制器程式設計要使用RS、E和D0-D7引腳,由於R/W為對1602讀寫的引腳,不需要對其進行讀,所以接低電平。
然後根據下圖的LCD1602時序圖寫指令和資料。
圖2 LCD1602時序圖
先寫兩個函式,寫指令和資料(第一次,我註釋了“EN=1”後面的延時):
write_com(uchar com) //寫指令
{
EN=0;
RS=0;
P0=com;
delayms(1);
EN=1;
delayms(1);
EN=0;
}
write_data(uchar dat) //寫資料
{
EN=0;
RS=1;
P0=dat;
delayms(1);
EN=1;
delayms(1);
EN=0;
}
程式如下:
#include <reg51.h> #include <stdio.h> #include <string.h> #define uchar unsigned char #define uint unsigned int sbit RS=P3^0; //液晶資料指令選擇端 sbit EN=P3^1; //液晶使能端 sbit led=P2^2; uchar code table[]="Dear Chenli ,"; uchar code table1[]="I LOVE YOU !"; void delayms(uint a) //延時毫秒 { uint x,y; for(x=a;x>0;x--) for(y=110;y>0;y--); } write_com(uchar com)//寫指令 { EN=0; RS=0; P0=com; delayms(1); EN=1; //delayms(1); EN=0; } write_data(uchar dat)//寫資料 { EN=0; RS=1; P0=dat; delayms(1); EN=1; //delayms(1); EN=0; } void init() { write_com(0x38);//設定16x2顯示,5X7點陣,8位資料介面, write_com(0x0c);//設定開顯示,不顯示游標 write_com(0x06);//寫一個字元後,地址指標加1 write_com(0x01);//顯示清0,資料指標清0 } void main(void) { uchar i; init(); write_com(0x80);//+0x10 for(i=0;i<strlen(table);i++) { write_data(table[i]); delayms(5); } write_com(0x80+0x40); for(i=0;i<strlen(table1);i++) { write_data(table1[i]); delayms(1); } /* for(i=0;i<16;i++) //移屏操作,16次,把螢幕右邊的內容移到顯示區域內 { write_com(0x18);//移屏指令 delayms(100); } */ while (1) { led=0; delayms(500); led=1; delayms(500); } }
得到的顯示結果如下:
說明模擬結果是正確的。
對上面的程式稍加修改,LCD1602第一行起始地址為0x80+0x10第二行起始地址為0x80+0x40+0x10,由於,仍不
加延時,但是當我想實現以下LCD1602的移屏效果,卻得不到想要的結果,如下:
上圖的程式碼如下:
#include <reg51.h> #include <stdio.h> #include <string.h> #define uchar unsigned char #define uint unsigned int sbit RS=P3^0; //液晶資料指令選擇端 sbit EN=P3^1; //液晶使能端 sbit led=P2^2; uchar code table[]="Dear Chenli ,"; uchar code table1[]="I LOVE YOU !"; void delayms(uint a) //延時毫秒 { uint x,y; for(x=a;x>0;x--) for(y=110;y>0;y--); } write_com(uchar com)//寫指令 { EN=0; RS=0; P0=com; delayms(1); EN=1; //delayms(1); EN=0; } write_data(uchar dat)//寫資料 { EN=0; RS=1; P0=dat; delayms(1); EN=1; //delayms(1); EN=0; } void init() { write_com(0x38);//設定16x2顯示,5X7點陣,8位資料介面, write_com(0x0c);//設定開顯示,不顯示游標 write_com(0x06);//寫一個字元後,地址指標加1 write_com(0x01);//顯示清0,資料指標清0 } void main(void) { uchar i; init(); write_com(0x80+0x10);//+0x10 第一次修改處,地址由0x80變為0x80+0x10 for(i=0;i<strlen(table);i++) { write_data(table[i]); delayms(5); } write_com(0x80+0x40+0x10); //第一次修改處,地址由0x80+0x40變為0x80+0x40+0x10 for(i=0;i<strlen(table1);i++)//第一次修改,取消移屏的註釋 { write_data(table1[i]); delayms(1); } for(i=0;i<16;i++) //移屏操作,16次,把螢幕右邊的內容移到顯示區域內 { write_com(0x18); //移屏指令 delayms(100); } while (1) { led=0; delayms(500); led=1; delayms(500); } }
仔細觀察,發現第一行的內容不見了,模擬時發現第一行的顯示在0x80~(0x80+0x0F)區域,但是程式是寫在
(0x80+0x10)~(0x80+0x1F),我檢查了幾遍,還是不對,百思不得其解。
最後我修改了一下對1602寫資料、指令的延時後(取消程式中延時函式的註釋),效果一下就出來了。如下:
由於是圖片,所以效果不是很好,模擬時可以看到整個移屏的效果,還不錯。
這是為什麼呢?為什麼添加了延時,顯示就正確了?
可能是資料還沒有完全寫完,所以。。。。。
OVER ^_^ 。