標題: 求幫忙把如下程序改成可以在普中開發(fā)板上使用 [打印本頁]
作者: mastu 時間: 2017-11-29 15:12
標題: 求幫忙把如下程序改成可以在普中開發(fā)板上使用
#include <reg51.h>
#include <intrins.h>
unsigned char code dis_week[]={"SUN,MON,TUE,WED,THU,FRI,SAT"};
unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; //星期月參變數(shù)
unsigned char data dis_buf1[16]; //lcd上排顯示緩沖區(qū)
unsigned char data dis_buf2[16]; //lcd下排顯示緩沖區(qū)
unsigned char data year,month,date,week;//年、月、日、星期
unsigned char data armhour,armmin,armsec;//鬧鐘時、分、秒
unsigned char data hour,min,sec,sec100; //時、分、秒、百分之一秒
unsigned char data flag,vkey,skey;//設(shè)置狀態(tài)計數(shù)標志、按鍵先前值、按鍵當前值
bit alarm; //標識是否啟用鬧鐘,1--啟用,0--關(guān)閉
sbit rs = P2^0; //LCD數(shù)據(jù)/命令選擇端(H/L)
sbit rw = P2^1; //LCD讀/寫選擇端(H/L)
sbit ep = P2^2; //LCD使能控制
sbit PRE = P3^3; //調(diào)整鍵(AN3)
sbit SET = P3^4; //調(diào)整鍵(AN4)
sbit SPK = P3^6;
void delayms(unsigned char ms); //延時程序
bit lcd_busy(); //測試LCD忙碌狀態(tài)程序
void lcd_wcmd(char cmd); //寫入指令到LCD程序
void lcd_wdat(char dat); //寫入數(shù)據(jù)到LCD程序
void lcd_pos(char pos); //LCD數(shù)據(jù)指針位置程序
void lcd_init(); //LCD初始化設(shè)定程序
void pro_timedate(); //時間日期處理程序
void pro_display(); //顯示處理程序
void pro_key(); //按鍵處理程序
void time_alarm(); //定時報警功能(鬧鐘)
unsigned char scan_key(); //按鍵掃描程序
unsigned char week_proc(); //星期自動計算與顯示函數(shù)
bit leap_year(); //判斷是否為閏年
void lcd_sef_chr(); //LCD自定義字符程序
void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s);
//更新顯示緩沖區(qū)函數(shù)
// 延時程序
void delay(unsigned char ms)
{ while(ms--)
{ unsigned char i;
for(i = 0; i< 250; i++)
{
_nop_(); //執(zhí)行一條_nop_()指令為一個機器周期
_nop_();
_nop_();
_nop_();
}
}
}
//測試LCD忙碌狀態(tài)
bit lcd_busy()
{
bit result;
rs = 0;
rw = 1;
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result =(bit)(P0&0x80); //LCD的D0--D7中,D7=1為忙碌,D7=0為空閑
ep = 0;
return result;
}
//寫入指令到LCD
void lcd_wcmd(char cmd)
{
while(lcd_busy()); //當lcd_busy為1時,再次檢測LCD忙碌狀態(tài),lcd-busy為0時,開始寫指令
rs = 0;
rw = 0;
ep = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//寫入數(shù)據(jù)到LCD
void lcd_wdat(char dat)
{
while(lcd_busy()); //當lcd_busy為1時,再次檢測LCD忙碌狀態(tài),lcd-busy為0時,開始寫數(shù)據(jù)
rs = 1;
rw = 0;
ep = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//LCD數(shù)據(jù)指針位置程序
void lcd_pos(char pos)
{
lcd_wcmd(pos|0x80); //數(shù)據(jù)指針=80+地址碼(00H~27H,40H~67H)
}
//設(shè)定二個自定義字符,(注意:LCD1602中自定義字符的地址為0x00--0x07,即可定義8個字符)
//這里我們設(shè)定把一個自定義字符放在0x00位置(000),另一個放在0x01位子(001)
void lcd_sef_chr()
{ //第一個自定義字符
lcd_wcmd(0x40); //"01 000 000" 第1行地址 (D7D6為地址設(shè)定命令形式D5D4D3為字符存放位置(0--7),D2D1D0為字符行地址(0--7))
lcd_wdat(0x1f); //"XXX 11111" 第1行數(shù)據(jù)(D7D6D5為XXX,表示為任意數(shù)(一般用000),D4D3D2D1D0為字符行數(shù)據(jù)(1-點亮,0-熄滅)
lcd_wcmd(0x41); //"01 000 001" 第2行地址
lcd_wdat(0x11); //"XXX 10001" 第2行數(shù)據(jù)
lcd_wcmd(0x42); //"01 000 010" 第3行地址
lcd_wdat(0x15); //"XXX 10101" 第3行數(shù)據(jù)
lcd_wcmd(0x43); //"01 000 011" 第4行地址
lcd_wdat(0x11); //"XXX 10001" 第4行數(shù)據(jù)
lcd_wcmd(0x44); //"01 000 100" 第5行地址
lcd_wdat(0x1f); //"XXX 11111" 第5行數(shù)據(jù)
lcd_wcmd(0x45); //"01 000 101" 第6行地址
lcd_wdat(0x0a); //"XXX 01010" 第6行數(shù)據(jù)
lcd_wcmd(0x46); //"01 000 110" 第7行地址
lcd_wdat(0x1f); //"XXX 11111" 第7行數(shù)據(jù)
lcd_wcmd(0x47); //"01 000 111" 第8行地址
lcd_wdat(0x00); //"XXX 00000" 第8行數(shù)據(jù)
//第二個自定義字符
lcd_wcmd(0x48); //"01 001 000" 第1行地址
lcd_wdat(0x01); //"XXX 00001" 第1行數(shù)據(jù)
lcd_wcmd(0x49); //"01 001 001" 第2行地址
lcd_wdat(0x1b); //"XXX 11011" 第2行數(shù)據(jù)
lcd_wcmd(0x4a); //"01 001 010" 第3行地址
lcd_wdat(0x1d); //"XXX 11101" 第3行數(shù)據(jù)
lcd_wcmd(0x4b); //"01 001 011" 第4行地址
lcd_wdat(0x19); //"XXX 11001" 第4行數(shù)據(jù)
lcd_wcmd(0x4c); //"01 001 100" 第5行地址
lcd_wdat(0x1d); //"XXX 11101" 第5行數(shù)據(jù)
lcd_wcmd(0x4d); //"01 001 101" 第6行地址
lcd_wdat(0x1b); //"XXX 11011" 第6行數(shù)據(jù)
lcd_wcmd(0x4e); //"01 001 110" 第7行地址
lcd_wdat(0x01); //"XXX 00001" 第7行數(shù)據(jù)
lcd_wcmd(0x4f); //"01 001 111" 第8行地址
lcd_wdat(0x00); //"XXX 00000" 第8行數(shù)據(jù)
}
//LCD初始化設(shè)定
void lcd_init()
{
lcd_wcmd(0x38); //設(shè)置LCD為16X2顯示,5X7點陣,八位數(shù)據(jù)借口
delay(1);
lcd_wcmd(0x0c); //LCD開顯示及光標設(shè)置(光標不閃爍,不顯示"-")
delay(1);
lcd_wcmd(0x06); //LCD顯示光標移動設(shè)置(光標地址指針加1,整屏顯示不移動)
delay(1);
lcd_wcmd(0x01); //清除LCD的顯示內(nèi)容
delay(1);
}
//閏年的計算
bit leap_year()
{
bit leap;
if((year%4==0&&year%100!=0)||year%400==0)//閏年的條件
leap=1;
else
leap=0;
return leap;
}
//星期的自動運算和處理
unsigned char week_proc()
{ unsigned char num_leap;
unsigned char c;
num_leap=year/4-year/100+year/400;//自00年起到y(tǒng)ear所經(jīng)歷的閏年數(shù)
if( leap_year()&& month<=2 ) //既是閏年且是1月和2月
c=5;
else
c=6;
week=(year+para_month[month]+date+num_leap+c)%7;//計算對應(yīng)的星期
return week;
}
//更新顯示緩沖區(qū)
void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s)
{ dis_buf1[0]=t1; //
dis_buf1[1]=0x20; //空格
dis_buf1[2]=50; //'2'
dis_buf1[3]=48; //'0'
dis_buf1[4]=year/10+48;
dis_buf1[5]=year%10+48;
dis_buf1[6]=0x2d;
dis_buf1[7]=month/10+48;
dis_buf1[8]=month%10+48;
dis_buf1[9]=0x2d; //'-'
dis_buf1[10]=date/10+48;
dis_buf1[11]=date%10+48;
dis_buf1[12]=0x20;
dis_buf1[13]=dis_week[4*week];
dis_buf1[14]=dis_week[4*week+1];
dis_buf1[15]=dis_week[4*week+2];
dis_buf2[0]=t2[0];
dis_buf2[1]=t2[1];
dis_buf2[2]=t2[2];
dis_buf2[3]=t2[3];
dis_buf2[4]=t2[4];
dis_buf2[5]=t2[5];
dis_buf2[6]=t2[6]; //空格
if (alarm)
dis_buf2[7]=0x01; //alarm=1,顯示鬧鐘啟用標致(第二個自定義字符)
else
dis_buf2[7]=0x20; //alarm=0,不顯示鬧鐘啟用標致
dis_buf2[8]=dis_h/10+48;
dis_buf2[9]=dis_h%10+48;
dis_buf2[10]=0x3a; //':'
dis_buf2[11]=dis_m/10+48;
dis_buf2[12]=dis_m%10+48;
dis_buf2[13]=0x3a;
dis_buf2[14]=dis_s/10+48;
dis_buf2[15]=dis_s%10+48;
}
//時間和日期處理程序
void pro_timedate()
{
sec++;
if(sec > 59)
{sec = 0;
min++;
if(min>59)
{min=0;
hour++;
if(hour>23)
{hour=0;
date++;
if (month==1||month==3||month==5||month==7||month==8||month==10||month==12)
if (date>31) {date=1;month++;} //大月31天
if (month==4||month==6||month==9||month==11)
if (date>30) {date=1;month++;} //小月30天
if (month==2)
{if( leap_year()) //閏年的條件
{if (date>29) {date=1;month++;}} //閏年2月為29天
else
{if (date>28) {date=1;month++;}} //平年2月為28天
}
if (month>12) {month=1;year++;}
if (year>99) year=0;
}
}
}
week_proc();
if (sec==armsec && min==armmin && hour==armhour)
{if (alarm)
TR1=1; //鬧鐘啟用時,報警時間到,啟動Timer1
}
}
//顯示處理程序
void pro_display()
{ unsigned char i;
lcd_pos(0x00);
for (i=0;i<=15;i++)
{lcd_wdat(dis_buf1);}
lcd_pos(0x40);
for (i=0;i<=15;i++)
{lcd_wdat(dis_buf2);}
}
//Timer0中斷處理程序,秒的產(chǎn)生
void timer0() interrupt 1
{
TH0=0xD8;
TL0=0xF0;
sec100++;
if(sec100 >= 100) //1秒時間 (100*10ms=1000ms=1s)
{sec100 = 0;
pro_timedate();//調(diào)用時間和日期處理程序
}
if (sec&0x01) //"__run__"閃一秒,停一秒
update_disbuf(0x00," ",hour,min,sec); //0x00表示顯示00位置的自定義字符
else
update_disbuf(0x00,"__run__",hour,min,sec);
pro_display(); //調(diào)用顯示處理函數(shù)
}
//按鍵掃描程序
unsigned char scan_key()
{
skey=0x00; //給變量vkey置初值
skey|=PRE; //讀取PRE鍵的狀態(tài)
skey=skey<<1; //將PRE鍵的狀態(tài)存于skey的B1位
skey|=SET; //讀取SET鍵的狀態(tài),并存于skey的B0位
return skey; //返回skey的鍵值(即PRE,SET的狀態(tài))
}
//外部中斷INT0中斷處理程序
void int0() interrupt 0
{
TR0=0; //禁止Timer0
IE=0; //禁止中斷
lcd_wcmd(0x0e); //顯示光標"_",整個光標不閃爍
alarm=1;
update_disbuf(0x50,"alarm_",armhour,armmin,armsec); //更新顯示數(shù)據(jù),0x50表示要顯示"P"
pro_display(); //調(diào)用顯示處理程序
lcd_pos(0x47); //使光標位于第一個調(diào)整項下
flag=0;
vkey=0x03;
while(flag^0x0a)
{skey = scan_key(); //掃描按鍵狀態(tài)
if (skey^vkey) //若skey與vkey相同,跳出循環(huán),相異執(zhí)行循環(huán)體
{ delay(10); //去按鍵抖動
skey = scan_key(); //轉(zhuǎn)回掃描按鍵狀態(tài)
if (skey^vkey) //若skey與vkey相同,跳出循環(huán),相異執(zhí)行循環(huán)體
{ vkey=skey; //將skey的值付給vkey
if (skey==0x01) //PRE鍵按下
{ flag++; //調(diào)整標志位加1
switch (flag) //將光標置于相應(yīng)調(diào)整位置
{
case 1: lcd_pos(0x49);break; //光標置小時報警設(shè)置位置
case 2: lcd_pos(0x4c);break; //光標置分鐘報警設(shè)置位置
case 3: lcd_pos(0x4f);break; //光標置秒時報警設(shè)置位置
case 4: update_disbuf(0x50,"time_ ",hour,min,sec);
pro_display();
lcd_pos(0x05);break; //光標置年調(diào)整位置
case 5: lcd_pos(0x08);break; //光標置月調(diào)整位置
case 6: lcd_pos(0x0b);break; //光標置日調(diào)整位置
case 7: lcd_pos(0x49);break; //光標置時調(diào)整位置
case 8: lcd_pos(0x4c);break; //光標置分調(diào)整位置
case 9: lcd_pos(0x4f);break; //光標置秒調(diào)整位置
default:break;
}
}
if (skey==0x02) //SET鍵按下
{ pro_key(); //轉(zhuǎn)設(shè)置按鍵處理程序
}
}
}
}
lcd_wcmd(0x0c); //設(shè)置LCD開顯示及光標不閃爍,不顯示"-"
lcd_wcmd(0x01); //清除LCD的顯示內(nèi)容
IE=0x8f; //CPU開中斷,INT0,INT1,開中斷
TR0=1; //Timer0啟動
}
//主程序,初始化及初值設(shè)定
void main()
{
lcd_init(); //初始化LCD
lcd_sef_chr(); //寫入自定義字符號
hour=0;min=0;sec=0; //開機時的時,分,秒顯示
armhour=0;armmin=0;armsec=0; //開機時的時,分,秒報警初值
year= 5; month=1;date=1; //開機時的年,月,日,星期顯示
week_proc();
alarm=1; //初始開機,啟用鬧鐘
IE = 0x8f; //CPU開中斷,INT0,INT1,Timer0,Timer1開中斷
IP = 0x04; //設(shè)置INT0為中斷最高優(yōu)先級
IT0=0;IT1=0; //外部INT0,INT1設(shè)置為電平觸發(fā)方式(注意,觸發(fā)不要選邊沿方式,易誤動)
TMOD = 0x11; //Timer0,Timer1工作于模式1, 16位定時方式
TH0 = 0xdc;TL0 = 0x00; //Timer0置10ms定時初值
TH1 = 0xff;TL1 = 0x00; //Timer1置初值
TR0 = 1; //Timer0啟動
TR1 = 0;
while(1);
}
//設(shè)置按鍵處理程序
void pro_key()
{
switch (flag)
{
case 0:alarm=!alarm; //啟用或關(guān)閉鬧鐘(alarm=1:啟用,alarm=0:關(guān)閉)
update_disbuf(0x50,"alarm_",armhour,armmin,armsec); //更新顯示數(shù)據(jù)
pro_display(); //調(diào)用顯示處理
lcd_pos(0x47);break; //光標回到原調(diào)整位置
case 1:armhour++;
if (armhour>23) armhour=0;
update_disbuf(0x50,"alarm_",armhour,armmin,armsec); //更新顯示數(shù)據(jù)
pro_display(); //調(diào)用顯示處理
lcd_pos(0x49);break; //光標回到原調(diào)整位置
case 2:armmin++;
if (armmin>59) armmin=0;
update_disbuf(0x50,"alarm_",armhour,armmin,armsec);
pro_display();
lcd_pos(0x4c);break;
case 3:armsec++;
if (armsec>59) armsec=0;
update_disbuf(0x50,"alarm_",armhour,armmin,armsec);
pro_display();
lcd_pos(0x4f);break;
case 4:year++;
if (year> 99) year= 0;
week_proc(); //星期自動運算
update_disbuf(0x50,"time_ ",hour,min,sec);
pro_display();
lcd_pos(0x05);break;
case 5:month++;
if (month>12) month=1;
week_proc(); //星期自動運算
update_disbuf(0x50,"time_ ",hour,min,sec);
pro_display();
lcd_pos(0x08);break;
case 6:date++;
if (month==1||month==3||month==5||month==7||month==8||month==10||month==12)
if (date>31) date=1; //大月31天
if (month==4||month==6||month==9||month==11)
if (date>30) date=1; //小月30天
if (month==2)
{if(leap_year()) //閏年的條件
{if (date>29) date=1;} //閏年2月為29天
else
{if (date>28) date=1;}} //平年2月為28天
week_proc(); //星期自動運算
update_disbuf(0x50,"time_ ",hour,min,sec);
pro_display();
lcd_pos(0x0b);break;
case 7:hour++;
if (hour>23) hour=0;
update_disbuf(0x50,"time_ ",hour,min,sec);
pro_display();
lcd_pos(0x49);break;
case 8:min++;
if (min>59) min=0;
update_disbuf(0x50,"time_ ",hour,min,sec);
pro_display();
lcd_pos(0x4c);break;
case 9:sec++;
if (sec>59) sec=0;
update_disbuf(0x50,"time_ ",hour,min,sec);
pro_display();
lcd_pos(0x4f);break;
default: break ;
}
}
//Timer1中斷處理程序,產(chǎn)生報警的聲音
void timer1() interrupt 3
{
TH1=0x80;
TL1=0x00;
SPK=~SPK;
t++;
}
//外部中斷INT1中斷處理程序,停止報警聲音
void int1() interrupt 2
{
if(TR1)
TR1=0;
}
這個程序代碼怎么改啊,求大神指教
作者: 1106998808 時間: 2017-11-29 15:34
很簡單的,你先把你的開發(fā)板的原理圖找到,然后改最上面的sbit特殊寄存器的位地址就可以使用了。
作者: le51 時間: 2017-11-29 20:15
把這個程序的硬件連接官謝對應(yīng)到你的開發(fā)板上的硬件連接就應(yīng)該可以了
作者: angmall 時間: 2017-11-29 20:56
這個程序代碼改了
- #include <reg51.h>
- #include <intrins.h>
- unsigned char code dis_week[]={"SUN,MON,TUE,WED,THU,FRI,SAT"};
- unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; //星期月參變數(shù)
- unsigned char data dis_buf1[16]; //lcd上排顯示緩沖區(qū)
- unsigned char data dis_buf2[16]; //lcd下排顯示緩沖區(qū)
- unsigned char data year,month,date,week; //年、月、日、星期
- unsigned char data armhour,armmin,armsec; //鬧鐘時、分、秒
- unsigned char data hour,min,sec,sec100; //時、分、秒、百分之一秒
- unsigned char data flag,vkey,skey;//設(shè)置狀態(tài)計數(shù)標志、按鍵先前值、按鍵當前值
- bit alarm; //標識是否啟用鬧鐘,1--啟用,0--關(guān)閉
- sbit rs = P2^6; //P2^0; //LCD數(shù)據(jù)/命令選擇端(H/L)
- sbit rw = P2^5; //P2^1; //LCD讀/寫選擇端(H/L)
- sbit ep = P2^7; //P2^2; //LCD使能控制
- sbit PRE = P3^2; //P3^3; //調(diào)整鍵(AN3)
- sbit SET = P3^3; //P3^4; //調(diào)整鍵(AN4)
- sbit SPK = P1^5; //P3^6;
- void delayms(unsigned char ms); //延時程序
- bit lcd_busy(); //測試LCD忙碌狀態(tài)程序
- void lcd_wcmd(char cmd); //寫入指令到LCD程序
- void lcd_wdat(char dat); //寫入數(shù)據(jù)到LCD程序
- void lcd_pos(char pos); //LCD數(shù)據(jù)指針位置程序
- void lcd_init(); //LCD初始化設(shè)定程序
- void pro_timedate(); //時間日期處理程序
- void pro_display(); //顯示處理程序
- void pro_key(); //按鍵處理程序
- void time_alarm(); //定時報警功能(鬧鐘)
- unsigned char scan_key(); //按鍵掃描程序
- unsigned char week_proc(); //星期自動計算與顯示函數(shù)
- bit leap_year(); //判斷是否為閏年
- void lcd_sef_chr(); //LCD自定義字符程序
- void update_disbuf(unsigned char t1, unsigned char t2[], unsigned char dis_h, unsigned char dis_m, unsigned char dis_s);
- //更新顯示緩沖區(qū)函數(shù)
- // 延時程序
- void delay(unsigned char ms)
- {
- while(ms--)
- { unsigned char i;
- for(i = 0; i< 250; i++)
- {
- _nop_(); //執(zhí)行一條_nop_()指令為一個機器周期
- _nop_();
- _nop_();
- _nop_();
- }
- }
- }
- //測試LCD忙碌狀態(tài)
- bit lcd_busy()
- {
- bit result;
- rs = 0;
- rw = 1;
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- result =(bit)(P0&0x80); //LCD的D0--D7中,D7=1為忙碌,D7=0為空閑
- ep = 0;
- return result;
- }
- //寫入指令到LCD
- void lcd_wcmd(char cmd)
- {
- while(lcd_busy()); //當lcd_busy為1時,再次檢測LCD忙碌狀態(tài),lcd-busy為0時,開始寫指令
- rs = 0;
- rw = 0;
- ep = 0;
- _nop_();
- _nop_();
- P0 = cmd;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 0;
- }
- //寫入數(shù)據(jù)到LCD
- void lcd_wdat(char dat)
- {
- while(lcd_busy()); //當lcd_busy為1時,再次檢測LCD忙碌狀態(tài),lcd-busy為0時,開始寫數(shù)據(jù)
- rs = 1;
- rw = 0;
- ep = 0;
- P0 = dat;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 0;
- }
- //LCD數(shù)據(jù)指針位置程序
- void lcd_pos(char pos)
- {
- lcd_wcmd(pos|0x80); //數(shù)據(jù)指針=80+地址碼(00H~27H,40H~67H)
- }
- //設(shè)定二個自定義字符,(注意:LCD1602中自定義字符的地址為0x00--0x07,即可定義8個字符)
- //這里我們設(shè)定把一個自定義字符放在0x00位置(000),另一個放在0x01位子(001)
- void lcd_sef_chr()
- { //第一個自定義字符
- lcd_wcmd(0x40); //"01 000 000" 第1行地址 (D7D6為地址設(shè)定命令形式D5D4D3為字符存放位置(0--7),D2D1D0為字符行地址(0--7))
- lcd_wdat(0x1f); //"XXX 11111" 第1行數(shù)據(jù)(D7D6D5為XXX,表示為任意數(shù)(一般用000),D4D3D2D1D0為字符行數(shù)據(jù)(1-點亮,0-熄滅)
- lcd_wcmd(0x41); //"01 000 001" 第2行地址
- lcd_wdat(0x11); //"XXX 10001" 第2行數(shù)據(jù)
- lcd_wcmd(0x42); //"01 000 010" 第3行地址
- lcd_wdat(0x15); //"XXX 10101" 第3行數(shù)據(jù)
- lcd_wcmd(0x43); //"01 000 011" 第4行地址
- lcd_wdat(0x11); //"XXX 10001" 第4行數(shù)據(jù)
- lcd_wcmd(0x44); //"01 000 100" 第5行地址
- lcd_wdat(0x1f); //"XXX 11111" 第5行數(shù)據(jù)
- lcd_wcmd(0x45); //"01 000 101" 第6行地址
- lcd_wdat(0x0a); //"XXX 01010" 第6行數(shù)據(jù)
- lcd_wcmd(0x46); //"01 000 110" 第7行地址
- lcd_wdat(0x1f); //"XXX 11111" 第7行數(shù)據(jù)
- lcd_wcmd(0x47); //"01 000 111" 第8行地址
- lcd_wdat(0x00); //"XXX 00000" 第8行數(shù)據(jù)
- //第二個自定義字符
- lcd_wcmd(0x48); //"01 001 000" 第1行地址
- lcd_wdat(0x01); //"XXX 00001" 第1行數(shù)據(jù)
- lcd_wcmd(0x49); //"01 001 001" 第2行地址
- lcd_wdat(0x1b); //"XXX 11011" 第2行數(shù)據(jù)
- lcd_wcmd(0x4a); //"01 001 010" 第3行地址
- lcd_wdat(0x1d); //"XXX 11101" 第3行數(shù)據(jù)
- lcd_wcmd(0x4b); //"01 001 011" 第4行地址
- lcd_wdat(0x19); //"XXX 11001" 第4行數(shù)據(jù)
- lcd_wcmd(0x4c); //"01 001 100" 第5行地址
- lcd_wdat(0x1d); //"XXX 11101" 第5行數(shù)據(jù)
- lcd_wcmd(0x4d); //"01 001 101" 第6行地址
- lcd_wdat(0x1b); //"XXX 11011" 第6行數(shù)據(jù)
- lcd_wcmd(0x4e); //"01 001 110" 第7行地址
- lcd_wdat(0x01); //"XXX 00001" 第7行數(shù)據(jù)
- lcd_wcmd(0x4f); //"01 001 111" 第8行地址
- lcd_wdat(0x00); //"XXX 00000" 第8行數(shù)據(jù)
- }
- //LCD初始化設(shè)定
- void lcd_init()
- {
- lcd_wcmd(0x38); //設(shè)置LCD為16X2顯示,5X7點陣,八位數(shù)據(jù)借口
- delay(1);
- lcd_wcmd(0x0c); //LCD開顯示及光標設(shè)置(光標不閃爍,不顯示"-")
- delay(1);
- lcd_wcmd(0x06); //LCD顯示光標移動設(shè)置(光標地址指針加1,整屏顯示不移動)
- delay(1);
- lcd_wcmd(0x01); //清除LCD的顯示內(nèi)容
- delay(1);
- }
- //閏年的計算
- bit leap_year()
- {
- bit leap;
- if((year%4==0&&year%100!=0)||year%400==0)//閏年的條件
- leap=1;
- else
- leap=0;
- return leap;
- }
- //星期的自動運算和處理
- unsigned char week_proc()
- { unsigned char num_leap;
- unsigned char c;
- num_leap=year/4-year/100+year/400;//自00年起到y(tǒng)ear所經(jīng)歷的閏年數(shù)
- if( leap_year()&& month<=2 ) //既是閏年且是1月和2月
- c=5;
- else
- c=6;
- week=(year+para_month[month]+date+num_leap+c)%7;//計算對應(yīng)的星期
- return week;
- }
- //更新顯示緩沖區(qū)
- void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s)
- { dis_buf1[0]=t1; //
- dis_buf1[1]=0x20; //空格
- dis_buf1[2]=50; //'2'
- dis_buf1[3]=48; //'0'
- dis_buf1[4]=year/10+48;
- dis_buf1[5]=year%10+48;
- dis_buf1[6]=0x2d;
- dis_buf1[7]=month/10+48;
- dis_buf1[8]=month%10+48;
- dis_buf1[9]=0x2d; //'-'
- dis_buf1[10]=date/10+48;
- dis_buf1[11]=date%10+48;
- dis_buf1[12]=0x20;
- dis_buf1[13]=dis_week[4*week];
- dis_buf1[14]=dis_week[4*week+1];
- dis_buf1[15]=dis_week[4*week+2];
- dis_buf2[0]=t2[0];
- dis_buf2[1]=t2[1];
- dis_buf2[2]=t2[2];
- dis_buf2[3]=t2[3];
- dis_buf2[4]=t2[4];
- dis_buf2[5]=t2[5];
- dis_buf2[6]=t2[6]; //空格
- if (alarm)
- dis_buf2[7]=0x01; //alarm=1,顯示鬧鐘啟用標致(第二個自定義字符)
- else
- dis_buf2[7]=0x20; //alarm=0,不顯示鬧鐘啟用標致
- dis_buf2[8]=dis_h/10+48;
- dis_buf2[9]=dis_h%10+48;
- dis_buf2[10]=0x3a; //':'
- dis_buf2[11]=dis_m/10+48;
- dis_buf2[12]=dis_m%10+48;
- dis_buf2[13]=0x3a;
- dis_buf2[14]=dis_s/10+48;
- dis_buf2[15]=dis_s%10+48;
- }
- //時間和日期處理程序
- void pro_timedate()
- {
- sec++;
- if(sec > 59)
- {sec = 0;
- min++;
- if(min>59)
- {min=0;
- hour++;
- if(hour>23)
- {hour=0;
- date++;
- if (month==1||month==3||month==5||month==7||month==8||month==10||month==12)
- if (date>31) {date=1;month++;} //大月31天
- if (month==4||month==6||month==9||month==11)
- if (date>30) {date=1;month++;} //小月30天
- if (month==2)
- {if( leap_year()) //閏年的條件
- {if (date>29) {date=1;month++;}} //閏年2月為29天
- else
- {if (date>28) {date=1;month++;}} //平年2月為28天
- }
- if (month>12) {month=1;year++;}
- if (year>99) year=0;
- }
- }
- }
- week_proc();
- if (sec==armsec && min==armmin && hour==armhour)
- {if (alarm)
- TR1=1; //鬧鐘啟用時,報警時間到,啟動Timer1
- }
- }
- //顯示處理程序
- void pro_display()
- {
- unsigned char i;
- lcd_pos(0x00);
- for (i=0;i<=15;i++)
- {lcd_wdat(dis_buf1[i]);}
- lcd_pos(0x40);
- for (i=0;i<=15;i++)
- {lcd_wdat(dis_buf2[i]);}
- }
- //Timer0中斷處理程序,秒的產(chǎn)生
- void timer0() interrupt 1
- {
- TH0=0xD8;
- TL0=0xF0;
- sec100++;
- if(sec100 >= 100) //1秒時間 (100*10ms=1000ms=1s)
- {sec100 = 0;
- pro_timedate();//調(diào)用時間和日期處理程序
- }
- if (sec&0x01) //"__run__"閃一秒,停一秒
- update_disbuf(0x00," ",hour,min,sec); //0x00表示顯示00位置的自定義字符
- else
- update_disbuf(0x00,"__run__",hour,min,sec);
- pro_display(); //調(diào)用顯示處理函數(shù)
- }
- //按鍵掃描程序
- unsigned char scan_key()
- {
- skey=0x00; //給變量vkey置初值
- skey|=PRE; //讀取PRE鍵的狀態(tài)
- skey=skey<<1; //將PRE鍵的狀態(tài)存于skey的B1位
- skey|=SET; //讀取SET鍵的狀態(tài),并存于skey的B0位
- return skey; //返回skey的鍵值(即PRE,SET的狀態(tài))
- }
- //外部中斷INT0中斷處理程序
- void int0() interrupt 0
- {
- TR0=0; //禁止Timer0
- IE=0; //禁止中斷
- lcd_wcmd(0x0e); //顯示光標"_",整個光標不閃爍
- alarm=1;
- update_disbuf(0x50,"alarm_",armhour,armmin,armsec); //更新顯示數(shù)據(jù),0x50表示要顯示"P"
- pro_display(); //調(diào)用顯示處理程序
- lcd_pos(0x47); //使光標位于第一個調(diào)整項下
- flag=0;
- vkey=0x03;
- while(flag^0x0a)
- {skey = scan_key(); //掃描按鍵狀態(tài)
- if (skey^vkey) //若skey與vkey相同,跳出循環(huán),相異執(zhí)行循環(huán)體
- { delay(10); //去按鍵抖動
- skey = scan_key(); //轉(zhuǎn)回掃描按鍵狀態(tài)
- if (skey^vkey) //若skey與vkey相同,跳出循環(huán),相異執(zhí)行循環(huán)體
- { vkey=skey; //將skey的值付給vkey
- if (skey==0x01) //PRE鍵按下
- { flag++; //調(diào)整標志位加1
- switch (flag) //將光標置于相應(yīng)調(diào)整位置
- {
-
- case 1: lcd_pos(0x49);break; //光標置小時報警設(shè)置位置
- case 2: lcd_pos(0x4c);break; //光標置分鐘報警設(shè)置位置
- case 3: lcd_pos(0x4f);break; //光標置秒時報警設(shè)置位置
-
- case 4: update_disbuf(0x50,"time_ ",hour,min,sec);
- pro_display();
- lcd_pos(0x05);break; //光標置年調(diào)整位置
- case 5: lcd_pos(0x08);break; //光標置月調(diào)整位置
- case 6: lcd_pos(0x0b);break; //光標置日調(diào)整位置
-
- case 7: lcd_pos(0x49);break; //光標置時調(diào)整位置
- case 8: lcd_pos(0x4c);break; //光標置分調(diào)整位置
- case 9: lcd_pos(0x4f);break; //光標置秒調(diào)整位置
-
- default:break;
- }
- }
- if (skey==0x02) //SET鍵按下
- {
- pro_key(); //轉(zhuǎn)設(shè)置按鍵處理程序
- }
- }
- }
- }
- lcd_wcmd(0x0c); //設(shè)置LCD開顯示及光標不閃爍,不顯示"-"
- lcd_wcmd(0x01); //清除LCD的顯示內(nèi)容
- IE=0x8f; //CPU開中斷,INT0,INT1,開中斷
- TR0=1; //Timer0啟動
- }
- //主程序,初始化及初值設(shè)定
- void main()
- {
- lcd_init(); //初始化LCD
- lcd_sef_chr(); //寫入自定義字符號
- hour=0;min=0;sec=0; //開機時的時,分,秒顯示
- armhour=0;armmin=0;armsec=0; //開機時的時,分,秒報警初值
- year= 5; month=1;date=1; //開機時的年,月,日,星期顯示
- week_proc();
- alarm=1; //初始開機,啟用鬧鐘
- IE = 0x8f; //CPU開中斷,INT0,INT1,Timer0,Timer1開中斷
- IP = 0x04; //設(shè)置INT0為中斷最高優(yōu)先級
- IT0=0;IT1=0; //外部INT0,INT1設(shè)置為電平觸發(fā)方式(注意,觸發(fā)不要選邊沿方式,易誤動)
- TMOD = 0x11; //Timer0,Timer1工作于模式1, 16位定時方式
- TH0 = 0xdc;TL0 = 0x00; //Timer0置10ms定時初值
- TH1 = 0xff;TL1 = 0x00; //Timer1置初值
- TR0 = 1; //Timer0啟動
- TR1 = 0;
- while(1);
- }
- //設(shè)置按鍵處理程序
- void pro_key()
- {
- switch (flag)
- {
- case 0:alarm=!alarm; //啟用或關(guān)閉鬧鐘(alarm=1:啟用,alarm=0:關(guān)閉)
- update_disbuf(0x50,"alarm_",armhour,armmin,armsec); //更新顯示數(shù)據(jù)
- pro_display(); //調(diào)用顯示處理
- lcd_pos(0x47);break; //光標回到原調(diào)整位置
- case 1:armhour++;
- if (armhour>23) armhour=0;
- update_disbuf(0x50,"alarm_",armhour,armmin,armsec); //更新顯示數(shù)據(jù)
- pro_display(); //調(diào)用顯示處理
- lcd_pos(0x49);break; //光標回到原調(diào)整位置
- case 2:armmin++;
- if (armmin>59) armmin=0;
- update_disbuf(0x50,"alarm_",armhour,armmin,armsec);
- pro_display();
- lcd_pos(0x4c);break;
- case 3:armsec++;
- if (armsec>59) armsec=0;
- update_disbuf(0x50,"alarm_",armhour,armmin,armsec);
- pro_display();
- lcd_pos(0x4f);break;
- case 4:year++;
- if (year> 99) year= 0;
- week_proc(); //星期自動運算
- update_disbuf(0x50,"time_ ",hour,min,sec);
- pro_display();
- lcd_pos(0x05);break;
- case 5:month++;
- if (month>12) month=1;
- week_proc(); //星期自動運算
- update_disbuf(0x50,"time_ ",hour,min,sec);
- pro_display();
- lcd_pos(0x08);break;
- case 6:date++;
- if (month==1||month==3||month==5||month==7||month==8||month==10||month==12)
- if (date>31) date=1; //大月31天
- if (month==4||month==6||month==9||month==11)
- if (date>30) date=1; //小月30天
- if (month==2)
- {if(leap_year()) //閏年的條件
- {if (date>29) date=1;} //閏年2月為29天
- else
- {if (date>28) date=1;}} //平年2月為28天
- week_proc(); //星期自動運算
- update_disbuf(0x50,"time_ ",hour,min,sec);
- pro_display();
- lcd_pos(0x0b);break;
-
- case 7:hour++;
- if (hour>23) hour=0;
- update_disbuf(0x50,"time_ ",hour,min,sec);
- pro_display();
- lcd_pos(0x49);break;
- case 8:min++;
- if (min>59) min=0;
- update_disbuf(0x50,"time_ ",hour,min,sec);
- pro_display();
- lcd_pos(0x4c);break;
- case 9:sec++;
- if (sec>59) sec=0;
- update_disbuf(0x50,"time_ ",hour,min,sec);
- pro_display();
- lcd_pos(0x4f);break;
- default: break ;
- }
- }
- //Timer1中斷處理程序,產(chǎn)生報警的聲音
- void timer1() interrupt 3
- {
- TH1=0x80;
- TL1=0x00;
- SPK=~SPK;
- //t++;
-
- }
- //外部中斷INT1中斷處理程序,停止報警聲音
- void int1() interrupt 2
- {
- if(TR1)
- TR1=0;
- }
復制代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |