熱門: 51單片機(jī) | 24小時(shí)必答區(qū) | 單片機(jī)教程 | 單片機(jī)DIY制作 | STM32 | Cortex M3 | 模數(shù)電子 | 電子DIY制作 | 音響/功放 | 拆機(jī)樂園 | Arduino | 嵌入式OS | 程序設(shè)計(jì)
![]() |
發(fā)布時(shí)間: 2018-4-15 14:24
正文摘要:程序?qū)懞煤笙螺d到單片機(jī)里,1602顯示的都是零,個(gè)位數(shù)字在閃爍。 部分程序: #include<reg52.h> #include<intrins.h> #define uchar unsigned char sbit DSIO=P3^4; ... |
zl2168 發(fā)表于 2018-4-15 16:57 我的程序用Proteus仿真也是可以的,能夠解釋下為何一直在閃爍? |
/*************************************************************************** *標(biāo)題: 可調(diào)的DS1302時(shí)鐘在LCD1602上顯示 * * ******************************************************************************* *接線:JP8接JP4、蜂鳴器短路帽的左端接到P3^2(用一根杜邦線) * *說明:本實(shí)驗(yàn)是在普中科技單片機(jī)開發(fā)板HC6800EM3上實(shí)現(xiàn)的 ******************************************************************************/ #include<reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit SCK=P3^6; //時(shí)鐘 sbit SDA=P3^4; //數(shù)據(jù) sbit RST=P3^5; // DS1302復(fù)位 sbit lcdrs=P2^6; sbit lcdrw=P2^5; sbit lcden=P2^7; sbit key1=P1^4; sbit key2=P1^5; sbit key3=P1^6; sbit key4=P1^7; sbit H=P1^1; //矩陣鍵盤第一行四個(gè)鍵 sbit beep=P3^2; bit ReadRTC_Flag; //定義讀DS1302標(biāo)志 uchar miao,fen,shi,ri,yue,week,nian,a,T,n=0; char l_tmpdate[7]={50,8,1,7,10,1,12};//設(shè)置初始時(shí)間,秒分時(shí)日月周年12-10-07 01:08:50 uchar code write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分時(shí)日月周年 最低位寫位 uchar code read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //秒分時(shí)日月周年 最低位讀位 uchar code table1[]="SUN"; //星期字表 uchar code table2[]="MON"; uchar code table3[]="TUE"; uchar code table4[]="WED"; uchar code table5[]="THU"; uchar code table6[]="FRI"; uchar code table7[]="SAT"; uchar code tab1[]="20 - -"; uchar code tab2[]=" : :"; /******************************************************************/ /* 函數(shù)聲明 */ /******************************************************************/ void Write_Ds1302_byte(uchar temp); void Write_Ds1302( uchar address,uchar dat ); uchar Read_Ds1302 ( uchar address ); void Read_RTC(void); void Set_RTC(void); void delay(uchar a); void ini_Timer(); void di(); void lcd_mang(); void write_lcd1602(uchar cmd,uchar i); void ini_lcd1602(); void write_week(uchar xq); void write_nyr(uchar add,uchar dat); void write_sfm(uchar add,uchar dat); void display(); void keyscan(); /******************************************************************/ /* 主函數(shù) */ /******************************************************************/ void main(void) { ini_Timer(); ini_lcd1602(); //Set_RTC(); //寫入時(shí)鐘值,如果使用備用電池時(shí)候,不需要沒每次上電寫入,此程序應(yīng)該屏蔽 while(1) { keyscan(); if(ReadRTC_Flag==0) { Read_RTC(); display(); } } } /******************************************************************/ /* BCD轉(zhuǎn)換成LCD1602能顯示的16進(jìn)制數(shù),秒、分、時(shí) */ /******************************************************************/ void write_sfm(uchar add,uchar dat) { uchar gw,sw; gw=dat%16; sw=dat/16; write_lcd1602(0x80+0x40+add,0); write_lcd1602(sw+0x30,1); write_lcd1602(gw+0x30,1); } /******************************************************************/ /* BCD轉(zhuǎn)換成LCD1602能顯示的16進(jìn)制數(shù),日、月、年 */ /******************************************************************/ void write_nyr(uchar add,uchar dat) { uchar gw,sw; gw=dat%16; sw=dat/16; write_lcd1602(0x80+add,0); write_lcd1602(sw+0x30,1); write_lcd1602(gw+0x30,1); } /******************************************************************/ /* 顯示星期 */ /******************************************************************/ void write_week(uchar xq) { uchar x; write_lcd1602(0x80+12,0); switch(xq) { case 1: for(x=0;x<3;x++) { write_lcd1602(table1[x],1); } break; case 2: for(x=0;x<3;x++) { write_lcd1602(table2[x],1); } break; case 3: for(x=0;x<3;x++) { write_lcd1602(table3[x],1); } break; case 4: for(x=0;x<3;x++) { write_lcd1602(table4[x],1); } break; case 5: for(x=0;x<3;x++) { write_lcd1602(table5[x],1); } break; case 6: for(x=0;x<3;x++) { write_lcd1602(table6[x],1); } break; case 7: for(x=0;x<3;x++) { write_lcd1602(table7[x],1); } break; } write_lcd1602(0x80+12,0); } /******************************************************************/ /* 顯示函數(shù) */ /******************************************************************/ void display() { write_sfm(10,miao); write_sfm(7,fen); write_sfm(4,shi); write_nyr(3,nian); write_nyr(6,yue); write_nyr(9,ri); write_week(week); } /******************************************************************/ /* 毫秒級(jí)延時(shí)函數(shù) */ /******************************************************************/ void delay(uchar a) { uchar i; while(a--) { for(i=0;i<250;i++) { _nop_(); _nop_(); _nop_(); _nop_(); } } } /******************************************************************/ /* 定時(shí)器0使蜂鳴器發(fā)聲函數(shù) */ /******************************************************************/ void ini_Timer() { a=0; TMOD=0X01; TH0=(65536-250)/256; TL0=(65536-250)%256; EA=1; ET0=1; TR0=1; } void timer0() interrupt 1 { TH0=(65536-250)/256; TL0=(65536-250)%256; a++; } void di() { while(key1==0||key2==0||key3==0) { if(a==2) { a=0; beep=~beep; } } } /******************************************************************/ /* LCD1602判忙函數(shù) */ /******************************************************************/ void lcd_mang() { lcdrs=0; lcdrw=1; lcden=1; _nop_(); _nop_(); _nop_(); _nop_(); while(P0&0x80); lcden=0; } /******************************************************************/ /* LCD1602寫指令(i=0)、數(shù)據(jù)(i=1)函數(shù) */ /******************************************************************/ void write_lcd1602(uchar cmd,uchar i) { lcd_mang(); lcdrs=i; lcdrw=0; lcden=0; _nop_(); _nop_(); lcden=1; _nop_(); _nop_(); P0=cmd; _nop_(); _nop_(); _nop_(); _nop_(); lcden=0; } /******************************************************************/ /* LCD1602初始化函數(shù) */ /******************************************************************/ void ini_lcd1602() { uchar i; write_lcd1602(0x38,0); delay(1); write_lcd1602(0x0c,0); delay(1); write_lcd1602(0x06,0); delay(1); write_lcd1602(0x01,0); delay(1); write_lcd1602(0x80+1,0); for(i=0;i<8;i++) { write_lcd1602(tab1[i],1); } write_lcd1602(0x80+0x40+4,0); for(i=0;i<6;i++) { write_lcd1602(tab2[i],1); } } /******************************************************************/ /* DS1302寫一個(gè)字節(jié) */ /******************************************************************/ void Write_Ds1302_Byte(uchar temp) { uchar i; for (i=0;i<8;i++) //循環(huán)8次 寫入數(shù)據(jù) { SCK=0; SDA=temp&0x01; //每次傳輸?shù)妥止?jié) temp>>=1; //右移一位 SCK=1; } } /******************************************************************/ /* 寫入DS1302 */ /******************************************************************/ void Write_Ds1302( uchar address,uchar dat ) { RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); //啟動(dòng) Write_Ds1302_Byte(address); //發(fā)送地址 Write_Ds1302_Byte(dat); //發(fā)送數(shù)據(jù) RST=0; //恢復(fù) } /******************************************************************/ /* 讀出DS1302數(shù)據(jù) */ /******************************************************************/ uchar Read_Ds1302 ( uchar address ) { uchar i,temp=0x00; RST=0; _nop_(); _nop_(); SCK=0; _nop_(); _nop_(); RST=1; _nop_(); _nop_(); Write_Ds1302_Byte(address); for (i=0;i<8;i++) //循環(huán)8次 讀取數(shù)據(jù) { if(SDA) temp|=0x80; //每次傳輸?shù)妥止?jié) SCK=0; temp>>=1; //右移一位 _nop_(); _nop_(); _nop_(); SCK=1; } RST=0; _nop_(); //以下為DS1302復(fù)位的穩(wěn)定時(shí)間 _nop_(); RST=0; SCK=0; _nop_(); _nop_(); _nop_(); _nop_(); SCK=1; _nop_(); _nop_(); SDA=0; _nop_(); _nop_(); SDA=1; _nop_(); _nop_(); return (temp); //返回 } /******************************************************************/ /* 讀時(shí)鐘數(shù)據(jù) */ /******************************************************************/ void Read_RTC(void) //讀取 日歷 { uchar i,*p; p=read_rtc_address; //地址傳遞 for(i=0;i<7;i++) //分7次讀取 秒分時(shí)日月周年 { l_tmpdate[i]=Read_Ds1302(*p); p++; miao=l_tmpdate[0]; fen =l_tmpdate[1]; shi =l_tmpdate[2]; ri =l_tmpdate[3]; yue =l_tmpdate[4]; week=l_tmpdate[5]; nian=l_tmpdate[6]; } } /******************************************************************/ /* 設(shè)定時(shí)鐘數(shù)據(jù) */ /******************************************************************/ void Set_RTC(void) //設(shè)定 日歷 { uchar i,*p,tmp; for(i=0;i<7;i++) { //BCD處理 tmp=l_tmpdate[i]/10; l_tmpdate[i]=l_tmpdate[i]%10; l_tmpdate[i]=l_tmpdate[i]+tmp*16; } Write_Ds1302(0x8E,0X00); //允許寫,禁止寫保護(hù) p=write_rtc_address; //傳地址 for(i=0;i<7;i++) //7次寫入 秒分時(shí)日月周年 { Write_Ds1302(*p,l_tmpdate[i]); p++; } Write_Ds1302(0x8E,0x80); //打開寫保護(hù) } /******************************************************************/ /* 鍵盤掃描函數(shù) */ /******************************************************************/ void keyscan() { H=0; //矩陣鍵盤第一排公共端拉低用于矩陣鍵盤的掃描檢測(cè) if(key1==0) //功能鍵 { delay(1); if(key1==0) { di(); while(!key1); //松手檢測(cè) ++n; ReadRTC_Flag=1; //停止走時(shí) switch(n) { case 1: write_lcd1602(0x80+0x40+11,0); //按一次功能鍵秒閃爍 write_lcd1602(0x0f,0); Write_Ds1302(0x8e,0x00); //允許寫,禁止寫保護(hù) Write_Ds1302(0x80,0x80|miao); //寫入DS1302秒位 Write_Ds1302(0x8e,0x80); //打開寫保護(hù) break; case 2: write_lcd1602(0x80+0x40+8,0); //按兩次功能鍵分閃爍 break; case 3: write_lcd1602(0x80+0x40+5,0); //按三次功能鍵時(shí)閃爍 break; case 4: write_lcd1602(0x80+10,0); //按四次功能鍵日閃爍 break; case 5: write_lcd1602(0x80+7,0); //按五次功能鍵月閃爍 break; case 6:write_lcd1602(0x80+4,0); //按六次功能鍵年閃爍 break; case 7: write_lcd1602(0x80+12,0); //按七次功能鍵周閃爍 break; case 8: n=0; //按八次功能鍵開始走時(shí),停止閃爍 ReadRTC_Flag=0; write_lcd1602(0x0c,0); Write_Ds1302(0x8e,0x00); Write_Ds1302(0x80,0x00|miao); Write_Ds1302(0x8e,0x80); break; } } } if(n!=0) //功能加鍵 { if(key2==0) { delay(1); if(key2==0) { di(); while(!key2); switch(n) { case 1: miao++; if(miao>=60) miao=0; write_lcd1602(0x80+0x40+10,0); //使LCD1602在秒位上顯示“加”設(shè)好的秒數(shù) write_lcd1602((miao)/10+'0',1); //十進(jìn)制轉(zhuǎn)換成LCD1602能顯示的字符,顯示出來 write_lcd1602((miao)%10+'0',1); T=(miao)/10*16+(miao)%10; //十進(jìn)制轉(zhuǎn)換成DS1302能寫的BCD碼 Write_Ds1302(0x8e,0x00); //允許寫,禁止寫保護(hù) Write_Ds1302(0x80,T); //寫入DS1302 Write_Ds1302(0x8e,0x80); //打開寫保護(hù) write_lcd1602(0x80+0x40+11,0); //寫完數(shù)據(jù)后光標(biāo)自動(dòng)右移,所以要?dú)w位 break; case 2: fen++; if(fen>=60) fen=0; write_lcd1602(0x80+0x40+7,0); write_lcd1602((fen)/10+'0',1); write_lcd1602((fen)%10+'0',1); T=(fen)/10*16+(fen)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x82,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+0x40+8,0); break; case 3: shi++; if(shi>=24) shi=0; write_lcd1602(0x80+0x40+4,0); write_lcd1602((shi)/10+'0',1); write_lcd1602((shi)%10+'0',1); T=(shi)/10*16+(shi)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x84,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+0x40+5,0); break; case 4: ri++; if(ri>31) ri=1; write_lcd1602(0x80+9,0); write_lcd1602((ri)/10+'0',1); write_lcd1602((ri)%10+'0',1); T=(ri)/10*16+(ri)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x86,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+10,0); break; case 5: yue++; if(yue>12) yue=1; write_lcd1602(0x80+6,0); write_lcd1602((yue)/10+'0',1); write_lcd1602((yue)%10+'0',1); T=(yue)/10*16+(yue)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x88,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+7,0); break; case 6: nian++; if(nian>=100) nian=0; write_lcd1602(0x80+3,0); write_lcd1602((nian)/10+'0',1); write_lcd1602((nian)%10+'0',1); T=(nian)/10*16+(nian)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x8c,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+4,0); break; case 7: week++; if(week>=8) week=1; write_week(week); T=(week)/10*16+(week)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x8a,T); Write_Ds1302(0x8e,0x80); break; } } } } if(key3==0) //功能減鍵 { delay(1); if(key3==0) { di(); while(!key3); switch(n) { case 1: miao--; if(miao<=0) miao=59; write_lcd1602(0x80+0x40+10,0); write_lcd1602((miao)/10+'0',1); write_lcd1602((miao)%10+'0',1); T=(miao)/10*16+(miao)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x80,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+0x40+11,0); break; case 2: fen--; if(fen<0) fen=59; write_lcd1602(0x80+0x40+7,0); write_lcd1602((fen)/10+'0',1); write_lcd1602((fen)%10+'0',1); T=(fen)/10*16+(fen)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x82,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+0x40+8,0); break; case 3: shi--; if(shi<0) shi=23; write_lcd1602(0x80+0x40+4,0); write_lcd1602((shi)/10+'0',1); write_lcd1602((shi)%10+'0',1); T=(shi)/10*16+(shi)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x84,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+0x40+5,0); break; case 4: ri--; if(ri<1) ri=31; write_lcd1602(0x80+9,0); write_lcd1602((ri)/10+'0',1); write_lcd1602((ri)%10+'0',1); T=(ri)/10*16+(ri)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x86,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+10,0); break; case 5: yue--; if(yue<0) yue=12; write_lcd1602(0x80+6,0); write_lcd1602((yue)/10+'0',1); write_lcd1602((yue)%10+'0',1); T=(yue)/10*16+(yue)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x88,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+7,0); break; case 6: nian--; if(nian<0) nian=99; write_lcd1602(0x80+3,0); write_lcd1602((nian)/10+'0',1); write_lcd1602((nian)%10+'0',1); T=(nian)/10*16+(nian)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x8c,T); Write_Ds1302(0x8e,0x80); write_lcd1602(0x80+4,0); break; case 7: week--; if(week<1) week=7; write_week(week); T=(week)/10*16+(week)%10; Write_Ds1302(0x8e,0x00); Write_Ds1302(0x8a,T); Write_Ds1302(0x8e,0x80); break; } } } } 自己看吧 |
首先檢查電路,電路沒有問題肯定就是程序問題了,看你這個(gè)就是沒有接收到時(shí)鐘信號(hào),硬件,程序好好查查吧 |
本帖最后由 zl2168 于 2018-4-15 16:59 編輯 實(shí)例91 具有校正功能的時(shí)鐘1302(LCD1602顯示) 先Proteus仿真,確認(rèn)有效。 ![]() ![]() 以上摘自張志良編著《80C51單片機(jī)仿真設(shè)計(jì)實(shí)例教程——基于Keil C和Proteus》清華大學(xué)出版社ISBN 978-7-302-41682-1,書中電路和程序設(shè)計(jì)有詳細(xì)說明,程序語句條條有注解。 |
Powered by 單片機(jī)教程網(wǎng)