時(shí)鐘目前能正常走時(shí),大概1天快12秒
鄙人愚昧,部分問題未能解決,
還望各位高手出手相救,出謀劃策
【按鍵掃描問題】:
調(diào)時(shí)間時(shí):1,調(diào)小時(shí)分鐘 加鍵不是按一次加一,是亂加,
小時(shí)能調(diào)到24時(shí),退出設(shè)置顯示0時(shí)
2,調(diào)小時(shí)分鐘 減鍵不是按一次減一,是亂減
[size=13.63636302948px] 3,調(diào)秒時(shí),加鍵減鍵亂加減,秒能調(diào)到8*,9*秒
[size=13.63636302948px] 4,退出設(shè)置秒清零,設(shè)置的秒未能保存,時(shí)和分能保存
[size=13.63636302948px] 5,時(shí)間能調(diào)到24時(shí),退出設(shè)置顯示0時(shí)
[size=13.63636302948px] 當(dāng)有按鍵按下時(shí)數(shù)碼管全滅不顯示,按鍵松開數(shù)碼管顯示
[size=13.63636302948px] 6,啟動(dòng)定時(shí)器中斷,能輕微看見數(shù)碼管閃爍
[size=13.63636302948px] //7,鬧鐘有問題,麻煩增加鬧鐘函數(shù),
[size=13.63636302948px] // 鬧鐘開指示燈亮,鬧鐘關(guān)指示燈滅
[size=13.63636302948px] 8,如何提高走時(shí)精度[size=13.63636302948px] 這里是源工程文件
加按鍵測(cè)試01.zip
(33.2 KB, 下載次數(shù): 22)
2015-1-14 01:04 上傳
點(diǎn)擊文件名下載附件
[size=13.63636302948px]源程序:
- /************************
- ds1302數(shù)碼管顯示時(shí)間
- ************************/
- /*****頭文件*****/
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /*****DS1302引腳定義*****/
- sbit rst = P0^7; /*實(shí)時(shí)時(shí)鐘復(fù)位線引腳*///(所有的數(shù)據(jù)傳輸在rst置1時(shí)進(jìn)行,rst為0時(shí)終止傳輸)
- sbit io = P0^6; /*實(shí)時(shí)時(shí)鐘數(shù)據(jù)線引腳*/
- sbit clk = P0^5; /*實(shí)時(shí)時(shí)鐘時(shí)鐘線引腳*/
- sbit ACC0 = ACC^0; /*累加寄存器的第0位*/
- sbit ACC7 = ACC^7; /*累加寄存器的第7位*/
- sbit LED1 = P3^0; /*未定義(高電平亮)(3mm紅發(fā)紅光)*/
- sbit LED2 = P3^1; /*鬧鐘指示燈(低電平亮)(亮:鬧鐘開;滅:鬧鐘關(guān))(alarm clock)(3mm白發(fā)綠光)*/
- sbit tele = P3^2; /*紅外遙控?cái)?shù)據(jù)線引腳(telecontrol)*/
- sbit motor = P3^3; /*振子,馬達(dá),震動(dòng)(低電平轉(zhuǎn))(vibration,motor)*/
- sbit beep = P3^4; /*蜂鳴器(低電平響)*/
- /*****按鍵定義*****/
- sbit key1 = P3^7; /*設(shè)置鍵*/
- sbit key2 = P3^6; /*加鍵*/
- sbit key3 = P3^5; /*減鍵*/
- uchar keynum; /*按鍵計(jì)數(shù)*/
-
- /*****數(shù)碼管數(shù)組*****/
- uchar code smg_du[]= /*共陽(yáng)數(shù)碼管段碼表*//*P2引腳*/
- {0xc0,0xf9,0xa4,0xb0,0x99, /*0-9*/
- 0x92,0x82,0xf8,0x80,0x90,0xbf};
- uchar code smg_we[]= /*數(shù)碼管位碼*//*P1引腳*/
- {0xC1,0xC2,0xC4, /*從左到右*/
- 0xC8,0xD0,0xE0}; /*位置1,2,3,4,5,6*/
- /*****時(shí)間初值*****/
- uchar table_shijian[7]={15,7,12,30,23,59,55}; /*年周月日時(shí)分秒*/
- uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80}; /*定義寫寄存器(年周月日時(shí)分秒)*/
- uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81}; /*定義讀寄存器(年周月日時(shí)分秒)*/
- uchar disp[6]; //存放轉(zhuǎn)換成十進(jìn)制后并分離出個(gè)位十位的數(shù)/*6個(gè)顯示元素(6個(gè)數(shù)碼管)*/
-
- /******函數(shù)聲明*****/
- void write_ds1302byte(uchar com); /*寫一個(gè)字節(jié)*/
- void write_ds1302(uchar com,uchar dat); /*寫一個(gè)字節(jié)命令和一個(gè)字節(jié)數(shù)據(jù)*/
- uchar read_ds1302(uchar com); /*讀一字節(jié)數(shù)據(jù)*/
- void ds1302_init(void); /*初始化ds1302*/
- void read_rtc(void); /*讀取時(shí)間*/
- void display(void); /*顯示處理函數(shù)*/
- void display_shijian(void); /*顯示函數(shù)*/
- void delay(uchar z); /*延時(shí)*/
- void tiaoshi(void); /*按鍵掃描*/
- void Timer0Init(); /*定時(shí)器初始化*/
- void Timer0zd(); /*定時(shí)器中斷*/
- /************************************************************************/
- /************主函數(shù)***************/
- void main(void)
- {
- delay(200); //等待系統(tǒng)穩(wěn)定
- LED1=0; //關(guān)閉未定義LED (P3.0)
- // Timer0Init(); //初始化定時(shí)器0
- ds1302_init(); //初始化ds1302/*一次即可*/
- while(1) /*大循環(huán)*/
- {
- tiaoshi(); /*調(diào)用按鍵掃描函數(shù)*/
- display(); /*調(diào)用顯示處理函數(shù)*/
- display_shijian(); /*調(diào)用顯示時(shí)間函數(shù)*/
- if(keynum==0) /*如果按鍵沒有動(dòng)作則執(zhí)行以下指令*/
- {
- read_rtc(); /*調(diào)用讀時(shí)間函數(shù)*/
- }
- }
- }
- /*****定時(shí)器*****/
- //void Timer0Init() //20毫秒@11.0592MHz
- //{
- // TMOD |= 0x01; //定時(shí)器0模式1定時(shí)器時(shí)鐘12T模式
- // TL0 = 0x00; //設(shè)置定時(shí)初值
- // TH0 = 0xb8; //設(shè)置定時(shí)初值
- // TF0 = 0; //清除TF0標(biāo)志
- // TR0 = 1; //開定時(shí)器0
- // ET0 = 1; //開定時(shí)器中斷
- // EA = 1; //開總中斷
- //}
- ////
- //void Timer0zd() interrupt 1
- //{
- // TL0 = 0x00; //設(shè)置定時(shí)初值
- // TH0 = 0xb8; //設(shè)置定時(shí)初值
- //
- // display();
- ////display_shijian(); /*調(diào)用顯示時(shí)間函數(shù)*/
- //// read_rtc(); /*調(diào)用讀時(shí)間函數(shù)*/
- // if(keynum==0) /*如果按鍵沒有動(dòng)作則執(zhí)行以下指令*/
- // {
- // read_rtc(); /*調(diào)用讀時(shí)間函數(shù)*/
- // }
- //}
- /*****延時(shí)函數(shù)*****/
- void delay(uchar z) /*延時(shí)≈1毫秒*/
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=115;y>0;y--);
- }
- /*****按鍵掃描模塊*****/
- void tiaoshi(void)
- {
- if(key1==0) //如果設(shè)置鍵按下
- {
- delay(10); //延時(shí)消抖
- if(key1==0) //判斷,防誤操作
- {
- while(!key1); //松手檢測(cè)
- write_ds1302(0x8e,0x00); //關(guān)閉寫保護(hù)(可以寫操作)
- write_ds1302(0x80,0x80); //晶振停振時(shí)鐘停止秒停
- keynum++; //設(shè)置鍵按鍵計(jì)數(shù)自動(dòng)加1*/
- switch(keynum) //設(shè)置鍵按鍵次數(shù)統(tǒng)計(jì)*/
- {
- case 1:P2=smg_du[disp[1]];P1=smg_we[1];delay(100);break; /*按1次*//*調(diào)小時(shí)*//*數(shù)碼管第二位閃爍*//*時(shí)個(gè)位*/
- case 2:P2=smg_du[disp[3]];P1=smg_we[3];delay(100);break; /*按2次*//*調(diào)分鐘*//*數(shù)碼管第四位閃爍*//*分個(gè)位*/
- case 3:P2=smg_du[disp[5]];P1=smg_we[5];delay(100);break; /*按3次*//*調(diào)秒鐘*//*數(shù)碼管第六位閃爍*//*秒個(gè)位*/
- case 4:keynum=0;write_ds1302(0x80,0x00);write_ds1302(0x8e,0x80);break; /*按4次*//*退出設(shè)置*//*啟動(dòng)晶振開始走時(shí)*//*開寫保護(hù)*/
- default:break;
- }
- }
- }
- if(keynum!=0) //如果keynum不是0說明設(shè)置鍵有動(dòng)作
- { //則執(zhí)行以下指令
- if(key2==0) //如果加鍵被按下
- { //則執(zhí)行以下指令
- delay(10); //延時(shí)消抖
- while(!key2) //松手檢測(cè)
- switch(keynum) /*設(shè)置鍵按鍵計(jì)數(shù)*/
- {
- case 1: /*加鍵按一次*//*時(shí)加1*/
- table_shijian[4]=read_ds1302(read_add[4]); //讀出當(dāng)前的小時(shí)
- table_shijian[4]=((((table_shijian[4]&0xf0)>>4)*10)+(table_shijian[4]&0x0f)); //將當(dāng)前的時(shí)轉(zhuǎn)換成十進(jìn)制數(shù)
- table_shijian[4]++;
- if(table_shijian[4]==24) table_shijian[4]=0;
- table_shijian[4]=(((table_shijian[4]/10)<<4)|table_shijian[4]%10); //將時(shí)部分十進(jìn)制數(shù)轉(zhuǎn)換為十六進(jìn)制數(shù)
- write_ds1302(write_add[4],table_shijian[4]);break; //寫入ds1302時(shí)位置
-
- case 2: /*加鍵按一次*//*分加1*/
- table_shijian[5]=read_ds1302(read_add[5]); //讀出當(dāng)前的分鐘
- table_shijian[5]=((((table_shijian[5]&0xf0)>>4)*10)+(table_shijian[5]&0x0f)); //將當(dāng)前的分鐘轉(zhuǎn)換成十進(jìn)制數(shù)
- table_shijian[5]++;
- if(table_shijian[5]==60) table_shijian[5]=0;
- table_shijian[5]=(((table_shijian[5]/10)<<4)|table_shijian[5]%10); //將分鐘部分十進(jìn)制數(shù)轉(zhuǎn)換為十六進(jìn)制數(shù)
- write_ds1302(write_add[5],table_shijian[5]);break; //寫入ds1302分位置
-
- case 3: /*加鍵按一次*//*秒加1*/
- table_shijian[6]=read_ds1302(read_add[6]); //讀出當(dāng)前的秒
- table_shijian[6]=((((table_shijian[6]&0xf0)>>4)*10)+(table_shijian[6]&0x0f)); //將當(dāng)前的秒轉(zhuǎn)換成十進(jìn)制數(shù)
- table_shijian[6]++;
- if(table_shijian[6]==60) table_shijian[6]=0;
- table_shijian[6]=(((table_shijian[6]/10)<<4)|table_shijian[6]%10); //將秒部分十進(jìn)制數(shù)轉(zhuǎn)換為十六進(jìn)制數(shù)
- write_ds1302(write_add[6],table_shijian[6]);break; //寫入ds1302秒位置
- }
- }
- }
- if(keynum!=0) //如果keynum不是0說明設(shè)置鍵有動(dòng)作
- { //則執(zhí)行以下指令
- if(key3==0) //如果減鍵被按下
- { //則執(zhí)行以下指令
- delay(10); //延時(shí)消抖
- while(!key3) //松手檢測(cè)
- switch(keynum) /*設(shè)置鍵按鍵計(jì)數(shù)*/
- {
- case 1: /*減鍵按一次*//*時(shí)減1*/
- table_shijian[4]=read_ds1302(read_add[4]); //讀出當(dāng)前的時(shí)
- table_shijian[4]=((((table_shijian[4]&0xf0)>>4)*10)+(table_shijian[4]&0x0f)); //將當(dāng)前的時(shí)轉(zhuǎn)換成十進(jìn)制數(shù)
- table_shijian[4]--;
- if(table_shijian[4]==-1) table_shijian[4]=23;
- table_shijian[4]=(((table_shijian[4]/10)<<4)|table_shijian[4]%10); //將時(shí)部分十進(jìn)制數(shù)轉(zhuǎn)換為十六進(jìn)制數(shù)
- write_ds1302(write_add[4],table_shijian[4]);break; //寫入ds1302時(shí)位置
-
- case 2: /*減鍵按一次*//*分減1*/
- table_shijian[5]=read_ds1302(read_add[5]); //讀出當(dāng)前的分
- table_shijian[5]=((((table_shijian[4]&0xf0)>>4)*10)+(table_shijian[5]&0x0f)); //將當(dāng)前的分轉(zhuǎn)換成十進(jìn)制數(shù)
- table_shijian[5]--;
- if(table_shijian[5]==-1) table_shijian[5]=59;
- table_shijian[5]=(((table_shijian[5]/10)<<4)|table_shijian[5]%10); //將分部分十進(jìn)制數(shù)轉(zhuǎn)換為十六進(jìn)制數(shù)
- write_ds1302(write_add[5],table_shijian[5]);break; //寫入ds1302分位置
-
- case 3: /*減鍵按一次*//*秒減1*/
- table_shijian[6]=read_ds1302(read_add[6]); //讀出當(dāng)前的秒
- table_shijian[6]=((((table_shijian[6]&0xf0)>>4)*10)+(table_shijian[6]&0x0f)); //將當(dāng)前的秒轉(zhuǎn)換成十進(jìn)制數(shù)
- table_shijian[6]--;
- if(table_shijian[6]==-1) table_shijian[6]=59;
- table_shijian[6]=(((table_shijian[6]/10)<<4)|table_shijian[6]%10); //將秒部分十進(jìn)制數(shù)轉(zhuǎn)換為十六進(jìn)制數(shù)
- write_ds1302(write_add[6],table_shijian[6]);break; //寫入ds1302秒位置
- }
- }
- }
- }
- /*****ds1302模塊*****/
- /*****寫一個(gè)字節(jié)*****/
- void write_ds1302byte(uchar com)
- {
- uchar i; //定義一個(gè)變量i
- for(i=0;i<8;i++) //連續(xù)寫8個(gè)二進(jìn)制位數(shù)據(jù)
- {
- clk=0; //拉低時(shí)鐘線,為脈沖上升沿寫入數(shù)據(jù)做好準(zhǔn)備
- io=com&0x01; //取出com的第0位數(shù)據(jù)寫入1302//(數(shù)據(jù)和0x01與)每次傳輸?shù)妥止?jié)
- com=com>>1; //將com的數(shù)據(jù)位右移1位
- clk=1; //時(shí)鐘線上升沿寫入數(shù)據(jù)
- }
- }
- /*****寫一個(gè)字節(jié)命令和一個(gè)字節(jié)數(shù)據(jù)*****/
- void write_ds1302(uchar com,uchar dat)
- {
- rst=0; _nop_(); //禁止數(shù)據(jù)傳輸//空操作(相當(dāng)于短暫延時(shí))
- clk=0; _nop_(); //確保寫數(shù)據(jù)前時(shí)鐘線被拉低//空操作
- rst=1; _nop_(); //啟動(dòng)數(shù)據(jù)傳輸//空操作
- write_ds1302byte(com); //寫命令地址
- write_ds1302byte(dat); //寫數(shù)據(jù)
- rst=0; _nop_(); //禁止數(shù)據(jù)傳遞(操作完趕緊拉低防止誤操作)//空操作
- io=0; _nop_(); //釋放io
- clk=1; _nop_(); //將時(shí)鐘線電平置于已知狀態(tài)
- }
- /*****讀一個(gè)字節(jié)命令讀一個(gè)字節(jié)數(shù)據(jù)*****/
- uchar read_ds1302(uchar com)
- {
- uchar i,value;
- clk=1; _nop_(); //確保寫數(shù)據(jù)前時(shí)鐘線被拉高//空操作
- io=1; _nop_(); //數(shù)據(jù)線拉高
- rst=1; _nop_(); //啟動(dòng)數(shù)據(jù)傳輸//空操作
- write_ds1302byte(com); //寫入命令字后/進(jìn)行讀操作之前要進(jìn)行寫命令(地址),以確定是讀那個(gè)
- for(i=0;i<8;i++) //連續(xù)讀8個(gè)二進(jìn)制位數(shù)據(jù)
- {
- clk=0; //拉低時(shí)鐘線,形成脈沖下降沿讀數(shù)據(jù)
- value=value>>1; //將value的各數(shù)據(jù)位右移1位,先讀出的是字節(jié)的最低位
- if(io) //如果讀出的數(shù)據(jù)是1
- value=value|0x80; //將1取出,寫在value的最高位
- clk=1; //將clk拉高,為下次下降沿讀出數(shù)據(jù)做好準(zhǔn)備
- }
- rst=0; //禁止數(shù)據(jù)傳輸
- return(value); //將讀出的數(shù)據(jù)返回
- }
- /*****初始化DS1302*****/
- void ds1302_init(void)
- {
- uchar i,a,b;
- // uchar CH;
- write_ds1302(0x8e,0x00); //關(guān)閉寫保護(hù)(可以寫操作)
- // write_ds1302(0x80,0x80); //裝初值前晶振停止,秒停
- for(i=0;i<7;i++)
- {
- a=table_shijian[i]%10; //個(gè)位
- b=table_shijian[i]/10; //十位
- table_shijian[i]=a+b*16; //轉(zhuǎn)換為十六進(jìn)制
- }
- // CH=read_ds1302(0x81); //先對(duì)ds1302進(jìn)行讀回秒寄存器,
- //
- // if(CH&0x80) //判斷秒寄存器最高位(CH)是否為1
- // { //如為1,說明晶振停止工作,ds1302處于低功耗待命狀態(tài),對(duì)它寫入初值
- // //如為0,說明晶振開始振動(dòng),ds1302處于工作狀態(tài),(說明在斷電時(shí)還起用了備用電池,所以ds1302還處于工作狀態(tài))
- // //如果每次上電要求都寫入初值,就無(wú)需這步操作,
- // for(i=0;i<7;i++) //寫入數(shù)據(jù)(年周月日時(shí)分秒)
- // {
- // write_ds1302(write_add[i],table_shijian[i]); //寫入命令,寫數(shù)據(jù)
- // }
- // }
- for(i=0;i<7;i++) //連續(xù)寫7個(gè)數(shù)據(jù)(年周月日時(shí)分秒)
- {
- write_ds1302(write_add[i],table_shijian[i]); //寫入命令,寫數(shù)據(jù)//對(duì)號(hào)入座
- }
-
- // write_ds1302(0x80,0x00); //啟動(dòng)晶振開始走時(shí),秒走
- write_ds1302(0x90,0xa5); //使能充電,1個(gè)二極管,2K電阻
- write_ds1302(0x8e,0x80); //打開寫保護(hù)(禁止寫操作)
- }
- //*****讀取時(shí)間*****/
- void read_rtc(void)
- {
- uchar i;
- for(i=0;i<7;i++) //連續(xù)讀7個(gè)數(shù)據(jù)(年周月日時(shí)分秒)
- {
- table_shijian[i]=read_ds1302(read_add[i]); //數(shù)據(jù)對(duì)應(yīng)寄存器的地址
- }
- }
- /************顯示處理**************/
- void display(void)
- {
- disp[0]=table_shijian[4]/16; /*時(shí)的十位*/
- disp[1]=table_shijian[4]%16; /*時(shí)的個(gè)位*/
- /*disp[2]=10;*/
- disp[2]=table_shijian[5]/16; /*分的十位*/
- disp[3]=table_shijian[5]%16; /*分的個(gè)位*/
- /*disp[5]=10; */
- disp[4]=table_shijian[6]/16; /*秒的十位*/
- disp[5]=table_shijian[6]%16; /*秒的個(gè)位*/
- }
- /*****顯示時(shí)間*****/
- void display_shijian(void)
- {
- uchar i;
- for(i=0;i<6;i++) /*連續(xù)寫入6位,時(shí)時(shí)分分秒秒*/
- {
- P1=smg_we[i]; /*數(shù)碼管位選*/
- P2=smg_du[disp[i]]; /*數(shù)碼管段選*/
- delay(2); /*延時(shí)*/
- P2=0xff; /*消隱*/
- // delay(2); /*延時(shí)*///這個(gè)延時(shí)影響數(shù)碼管閃爍
- }
- }
復(fù)制代碼
|