用 74HC595 把 LCD1602 改成串行數(shù)據(jù)接口
LCD1602的接口形式是并行的,它有8條數(shù)據(jù)線、3條控制線。這樣就需要11條線來控制它的正常工作。雖然它還可以工作在4位數(shù)據(jù)線的形式,最精簡(jiǎn)的形式是6條線。
有位網(wǎng)友想要使用74HC595進(jìn)行串-并轉(zhuǎn)換,想要用4條線來控制LCD1602。
可見鏈接:http://zhidao.baidu.com/question/458604195.html。
多用了一塊芯片,省下了單片機(jī)的引腳,這也算是一種方法吧,在系統(tǒng)規(guī)模較大、資源緊張的條件下,還是值得應(yīng)用的。
74HC595是“串入并出”的移位寄存器芯片,它需要用3條線控制數(shù)據(jù)的輸入,才能正常的輸出8位數(shù)據(jù)。
有了8位數(shù)據(jù),這時(shí),LCD1602還需要至少兩條控制線。
經(jīng)過做而論道的精心設(shè)計(jì),分時(shí)使用這些控制線,最終,僅僅使用了3條線,就完成了對(duì)74HC595和LCD1602的有效控制!
這要比前面的網(wǎng)友提出的4條線的方案,還要更加精簡(jiǎn),節(jié)省率提高了25%。
精簡(jiǎn)后的電路圖如下:
圖中是一個(gè)數(shù)字鐘,是為另一個(gè)網(wǎng)友編寫的,可以參考下面的鏈接:
http://hi.baidu.com/do_sermon/item/c8d1161d40768f10e3f98682
http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/blog/item/a0c99e2343b541844423e865.html
(百度空間在2012年8月,無聊的改版了,結(jié)果,把它自己的網(wǎng)站鏈接,都弄斷了。因此,下面的鏈接,已經(jīng)失效了。不刪了,留作紀(jì)念吧。)
由于LCD1602的驅(qū)動(dòng)電路發(fā)生了改變,所以數(shù)字鐘的程序,也要相應(yīng)的修改。
那么,針對(duì)本電路的程序如下:
//===================================================
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineKEY_IOP3
sbitLCD_RS=P2^0;
sbitLCD_EN=P2^2;
sbitSCK=P2^0;
sbitSDI=P2^1;
sbitRCK=P2^2;
sbitSPK=P1^2;
sbitLED=P2^4;
bitnew_s,modify=0;
chart0,sec=50,min=59,hour=23;
charcodeLCD_line1[]="DesignedbyZELD";
charcodeLCD_line2[]="Timer:00:00:00";
charTimer_buf[]="23:59:50";
//---------------------------------------------------
voiddelay(uintz)
{
uintx,y;
for(x=z;x>0;x--)for(y=100;y>0;y--);
}
//---------------------------------------------------
voidwrite_595(uchardate)//寫入595
{
uchari;
for(i=0;i<8;i++){
SCK=0;SDI=date&0x80;
SCK=1;date<<=1;
}
}
//---------------------------------------------------
voidW_LCD_Com(ucharcom)//寫指令
{
write_595(com);LCD_RS=0;//寫入指令
RCK=1;RCK=0;//令595輸出,并用EN輸出一個(gè)高脈沖
}
//---------------------------------------------------
voidW_LCD_Dat(uchardat)//寫數(shù)據(jù)
{
write_595(dat);LCD_RS=1;//寫入數(shù)據(jù)
RCK=1;RCK=0;//令595輸出,并用EN輸出一個(gè)高脈沖
}
//---------------------------------------------------
voidW_LCD_STR(uchar*s)//寫字符串
{
while(*s)W_LCD_Dat(*s++);
}
//---------------------------------------------------
voidW_BUFF(void)//填寫顯示緩沖區(qū)
{
Timer_buf[7]=sec%10+48;Timer_buf[6]=sec/10+48;
Timer_buf[4]=min%10+48;Timer_buf[3]=min/10+48;
Timer_buf[1]=hour%10+48;Timer_buf[0]=hour/10+48;
W_LCD_Com(0xc0+7);W_LCD_STR(Timer_buf);
}
//---------------------------------------------------
ucharread_key(void)
{
ucharx1,x2;
KEY_IO=255;
x1=KEY_IO;
if(x1!=255){
delay(100);
x2=KEY_IO;
if(x1!=x2)return255;
while(x2!=255)x2=KEY_IO;
if(x1==0x7f)return0;
elseif(x1==0xbf)return1;
elseif(x1==0xdf)return2;
elseif(x1==0xef)return3;
elseif(x1==0xf7)return4;
}
return255;
}
//---------------------------------------------------
voidInit()
{
W_LCD_Com(0x38);delay(50);
W_LCD_Com(0x38);delay(50);
W_LCD_Com(0x0c);
W_LCD_Com(0x06);
W_LCD_Com(0x01);delay(50);
W_LCD_Com(0x80);W_LCD_STR(LCD_line1);
W_LCD_Com(0xC0);W_LCD_STR(LCD_line2);
TMOD=0x01;//T0定時(shí)方式1
TH0=0x4c;
TR0=1;//啟動(dòng)T0
PT0=1;//高優(yōu)先級(jí),以保證定時(shí)精度
ET0=1;
EA=1;
}
//---------------------------------------------------
voidmain()
{
uinti,j;
ucharKey;
Init();
while(1){
//-------------------------------
if(new_s){//如果出現(xiàn)了新的一秒,修改時(shí)間
new_s=0;sec++;sec%=60;
if(!sec){min++;min%=60;
if(!min){hour++;hour%=24;}
}
W_BUFF();//寫顯示
//-------------------------------
if(!sec&&!min){//整點(diǎn)報(bào)時(shí)
for(i=0;i<200;i++){
SPK=0;for(j=0;j<100;j++);
SPK=1;for(j=0;j<100;j++);
}}
}
//-------------------------------
Key=read_key();//讀出按鍵
switch(Key){//分別處理四個(gè)按鍵
case0:modify=1;break;
case1:if(modify){min++;min%=60;W_BUFF();break;}
case2:if(modify){hour++;hour%=24;W_BUFF();break;}
case3:modify=0;break;
}}
}
//---------------------------------------------------
voidtimer0(void)interrupt1//T0中斷函數(shù),50ms執(zhí)行一次
{
TH0=0x4c;
t0++;t0%=20;//20,一秒鐘
if(t0==0){new_s=1;LED=~LED;}
if(modify)LED=0;
}
//===================================================