這種要求的程序很簡單,也用不著138、573,給你一個示例參考,另加鬧鐘也是輕而易舉的事。黑幣你就自己留著吧。
- #include <reg51.H>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define key_S 8 //宏定義短按(約20ms)
- #define key_L key_S*30 //宏定義長按(約600ms)
- #define key_I key_S*20 //宏定義長按連+間隔(約200ms)
- //DS1302引腳連接定義
- sbit DSIO = P3^2;
- sbit REST = P3^0;
- sbit SCLK = P3^1;
- sbit key1 = P3^3;
- uchar code table[]={//共陰數碼管段碼"0~f-."
- 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x80};
- uchar dis_buf[8]={0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00}; //數碼管顯示緩存數組
- //DS1302讀取和寫入時分秒日月周年的地址
- uchar code READ_RTC_ADDR[7]= {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; //讀出地址
- uchar code WRITE_RTC_ADDR[7]= {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //寫入地址
- // 秒 分 時 日 月 周 年
- uchar TIME[7]={0x00, 0x00, 0x12, 0x04, 0x01, 0x03, 0x23};//讀取Ds1302 存儲順序是秒分時日月周年
- //---全局變量聲明---
- uint Cnt2ms; //2.5ms計數變量
- uint num; //計數變量
- uchar KeySec; //鍵值變量
- bit flashing; //閃爍標志
- //---本地函數聲明---//
- void Ds1302Init(); //DS1302初始化
- void Ds1302Write(uchar addr, uchar dat);//向1302芯片寫入地址和數據
- uchar Ds1302Read(uchar addr); //從1302讀數據
- void Ds1302ReadTime(); //讀取秒分時日月周年信息
- uchar BCD_D(uchar bcd); //BCD碼轉十進制函數
- uchar D_BCD(uchar Dec); //十進制轉BCD碼函數
- void Timer0Init(void); //定時器T0初始化
- //==============DS1302驅動部分=====================
- //寫1302時鐘數據
- void Ds1302Write(uchar addr, uchar dat)
- {
- uchar i;
- REST= 0;
- SCLK= 0;
- REST= 1;
- for(i=0;i<8;i++) // 寫地址
- {
- DSIO=addr & 0x01; //數據從低位開始傳送
- addr>>=1;
- SCLK = 1; //數據在上升沿時,DS1302讀取數據
- SCLK = 0;
- }
- for(i=0;i<8;i++) //寫數據
- {
- DSIO=dat & 0x01;
- dat>>= 1;
- SCLK = 1; // 數據在上升沿時,DS1302讀取數據
- SCLK = 0;
- }
- REST = 0; // 傳送數據結束
- }
- //讀1302時鐘數據
- uchar Ds1302Read(uchar addr)
- {
- uchar i,dat,dat1;
- REST = 0;
- SCLK = 0;
- REST = 1;
- for(i=0; i<8; i++) // 開始傳送八位地址命令
- {
- DSIO = addr & 0x01; // 數據從低位開始傳送
- addr >>= 1;
- SCLK = 1; // 上升沿有效,DS1302讀取數據
- SCLK = 0;
- }
- for(i=0;i<8;i++) // 讀取8位數據
- {
- dat1 = DSIO; // 從最低位開始接收
- dat=(dat>>1)|(dat1<<7);
- SCLK = 1; // 上升沿有效,DS1302讀取數據
- SCLK = 0;
- }
- REST = 0; // 以下為DS1302復位的穩定時間,必須的。
- SCLK = 1;
- DSIO = 0;
- DSIO = 1;
- return dat;
- }
- //初始化DS1302
- void Ds1302Init()
- {
- uchar i;
- Ds1302Write(0x8E,0x00); // 禁止寫保護功能
- for(i=0;i<3;i++) // 寫入3個字節的時鐘信號:分秒時
- Ds1302Write(WRITE_RTC_ADDR[i],TIME[i]);
- Ds1302Write(0x8E,0x80); // 打開寫保護功能
- }
- //BCD碼轉十進制函數
- uchar BCD_D(uchar bcd)
- {
- return ((bcd>>4)*10)+(bcd & 0x0f);
- }
- //十進制轉BCD碼函數,返回BCD碼
- uchar D_BCD(uchar Dec)
- {
- return (Dec/10*16+Dec%10);
- }
- //讀取時鐘信息
- void Ds1302ReadTime()
- {
- uchar i;
- for(i=0;i<3;i++) //讀取3個字節的時鐘信號:秒分時
- TIME[i]=BCD_D(Ds1302Read(READ_RTC_ADDR[i]));//BCD轉換成十進制保存
- }
- //按鍵服務函數
- void key_scan()
- {
- static uint time=0; //計數變量
- if(!key1) //按鍵按下
- {
- time++;
- if(time>=key_L) //長按
- {
- switch(KeySec)
- {
- case 1: TIME[2]++;if(TIME[2]>23)TIME[2]=0;break;
- case 2: TIME[1]++;if(TIME[1]>59)TIME[1]=0;TIME[0]=0;break;
- }
- time=key_I; //連+間隔
- num=2000; //自復位變量賦值(5秒)
- }
- }
- else //松手
- {
- if(time>key_S && time<key_I)//短按
- {
- num=2000; //自復位變量賦值(5秒)
- KeySec++;
- if(KeySec>2)
- {
- // KeySec=0;
- num=1;
- }
- }
- time=0;
- }
- }
- // 數碼管顯示函數
- void display()
- {
- uchar i;
- if(KeySec==0) //常態顯示
- {
- dis_buf[0]=table[TIME[2]/10];
- dis_buf[1]=table[TIME[2]%10];
- dis_buf[3]=table[TIME[1]/10];
- dis_buf[4]=table[TIME[1]%10];
- dis_buf[6]=table[TIME[0]/10];
- dis_buf[7]=table[TIME[0]%10];
- }
- if(KeySec==1) //調整時
- {
- if(!key1)//持續不變表示鍵長按連加,時不閃爍
- {
- dis_buf[0]=table[TIME[2]/10];
- dis_buf[1]=table[TIME[2]%10];
- }
- else //松手 時閃爍
- {
- if(flashing)
- {
- dis_buf[0]=table[TIME[2]/10];
- dis_buf[1]=table[TIME[2]%10];
- }
- else
- {
- dis_buf[0]=0x00;
- dis_buf[1]=0x00;
- }
- }
- dis_buf[3]=table[TIME[1]/10];
- dis_buf[4]=table[TIME[1]%10];
- dis_buf[6]=table[TIME[0]/10];
- dis_buf[7]=table[TIME[0]%10];
- }
- if(KeySec==2) //調整分
- {
- dis_buf[0]=table[TIME[2]/10];
- dis_buf[1]=table[TIME[2]%10];
- if(!key1)//持續不變表示鍵長按連加,分不閃爍
- {
- dis_buf[3]=table[TIME[1]/10];
- dis_buf[4]=table[TIME[1]%10];
- }
- else //松手 分閃爍
- {
- if(flashing)
- {
- dis_buf[3]=table[TIME[1]/10];
- dis_buf[4]=table[TIME[1]%10];
- }
- else
- {
- dis_buf[3]=0x00;
- dis_buf[4]=0x00;
- }
- }
- dis_buf[6]=table[TIME[0]/10];
- dis_buf[7]=table[TIME[0]%10];
- }
- P2=0xff;
- P0=dis_buf[i];
- P2=~(0x01<<i);
- i=++i%8;
- }
- //初始化定時器
- void Timer0Init(void) //2500微秒@12.000MHz
- {
- TMOD |= 0x01; //設置定時器模式
- TL0 = 0x3C; //設置定時初始值
- TH0 = 0xF6; //設置定時初始值
- TF0 = 0; //清除TF0標志
- TR0 = 1; //定時器0開始計時
- }
- //主函數
- void main()
- {
- uchar t;
- Ds1302Init();
- Timer0Init(); //初始化定時器
- while(1)
- {
- if(TF0) //周期2.5ms
- {
- TF0=0;
- TL0 = 0x3C; //設置定時初始值
- TH0 = 0xF6; //設置定時初始值
- if(++Cnt2ms==400)Cnt2ms=0;
- key_scan();//按鍵掃描
- if(num!=0)
- {
- if(Cnt2ms%80==0)//0.2s 設置狀態時、分快閃
- flashing=~flashing;
- num--;
- if(num==0)//按鍵停止操作5秒自動恢復正常顯示
- {
- for(t=1;t<3;t++)//數據轉碼導入寫入緩存
- TIME[t]=D_BCD(TIME[t]);//十進制轉BCD碼
- Ds1302Init();//寫入實時時間
- KeySec=0;//鍵值清0
- }
- }
- else //設置時間時 不讀取DS1302實時時間
- {
- Ds1302ReadTime();//讀DS1302實時時間
- }
- display();// 數碼管顯示函數
- }
- }
- }
復制代碼
|