本帖最后由 lids 于 2018-12-21 08:41 編輯
描述: 4位共陽1寸數碼管時鐘,顯示88:88樣式,正常走時的時候,“:”1秒亮滅1次;調時間的的時候冒號熄滅
調時:按KEY1按鍵第1次分鐘位閃爍,再按KEY2一次分鐘加1,按KEY3一次分鐘減1,長按連加連減;
按KEY1按鍵第2次小時位閃爍,再按KEY2一次小時加1,按KEY3一次小時減1,長按連加連減;
按KEY1按鍵第3次,秒從零開始累加,時鐘回到正常走時;
校時的時候先調好時、分,分鐘要比參考時間的分鐘加1分,
再看參考時間的秒數到了59再按KEY1按鍵的第3次,這樣對時就比較準了,因為KEY1按鍵按第3次后秒會清零。
加備用電池,掉電走時
KEY2鍵第2功能:非調時狀態,為光控開關;
KEY3鍵第2功能:非調時狀態,為顯示切換開關;
DS18B20做溫度檢測, 可顯示3個界面:1.實時時鐘與溫度輪流顯示、2.只顯示溫度、3.只顯示時間;
溫度顯示范圍: -9.9℃~99.9℃;
增加數碼管調亮度功能,自動10級亮度,P1.0接5.1K電阻上拉、光敏電阻下拉分壓;
環境光線越亮,數碼管越亮,反之數碼管越暗,晚上看不刺眼。
實物通過.
12MHz晶振,STC12C5A60S2+DS1302時鐘芯片+DS18B20,
P0口接段位,P2^4~P2^7接pnp三極管控制4個共陽極。
制作出來的實物圖如下:
1.jpg (43 KB, 下載次數: 100)
下載附件
2018-12-18 19:23 上傳
2.jpg (54 KB, 下載次數: 98)
下載附件
2018-12-18 19:23 上傳
附件里有完整C文件,PCB文件,原理圖
- /*********************************************************************************
- 描述: 4位共陽數碼管時鐘,顯示88:88樣式,正常走時的時候,“:”1秒閃爍2次;調時間的的時候冒號熄滅
- 調時:按KEY1按鍵第1次分鐘位閃爍,再按KEY2一次分鐘加1,按KEY3一次分鐘減1,長按連加連減;
- 按KEY1按鍵第2次小時位閃爍,再按KEY2一次小時加1,按KEY3一次小時減1,長按連加連減;
- 按KEY1按鍵第3次,秒從零開始累加,時鐘回到正常走時;
- 校時的時候先調好時、分,分鐘要比參考時間的分鐘加1分,
- 再看參考時間的秒數到了59再按KEY1按鍵的第3次,這樣對時就比較準了。
- 加備用電池,掉電走時
-
- KEY2鍵第2功能:非調時狀態,為光控開關;
- KEY3鍵第2功能:非調時狀態,為顯示切換開關;
- DS18B20做溫度檢測,實時時鐘與溫度輪流顯示;
- 溫度顯示范圍: -9.9℃~99.9℃;
- 增加數碼管調亮度功能,按鍵10級亮度P1.0接5.1K電阻上拉、光敏電阻下拉分壓;
- 環境光線越亮,數碼管越亮,反之數碼管越暗。
- 實物通過.
- 12MHz晶振,STC12C5A60S2+DS1302時鐘芯片+DS18B20,
- P0口接段位,P2^4~P2^7接pnp三極管控制4個共陽極。
- **********************************************************************************/
- #include <STC12C5A60S2.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit TSCLK = P2^0;//時鐘線
- sbit TIO = P2^1;//數據線
- sbit TRST = P2^2;//使能端
- sbit key1 = P3^0; //設置鍵
- sbit key2 = P3^1; //加 /光控開關鍵(校時的時候做加鍵,反之為光控開關)
- sbit key3 = P3^2; // 減/顯示切換鍵
- sbit DQ = P2^3; //DS18B20數據口
- sbit w1 = P2^4; //設置位驅動口
- sbit w2 = P2^5;
- sbit w3 = P2^6;
- sbit w4 = P2^7;
- sbit w5 = P3^7; //此位不顯示
- sbit dd = P1^4; //蜂鳴器控制端
- uchar xs=0; //顯示切換計數變量
- uchar knum,shan_cont;
- char shi,fen,miao;
- uchar ba=40;
- uint mh,mh_count,count;
- bit shan; //校時閃爍標志位
- uchar s=0; //顯示負號
- uint temp; //溫度值
- bit flag; //輪流顯示標志位
- bit flag_gk; //光控標志位
- bit flag_js=0; //自動校時標志
- bit flag_fm; //蜂鳴器啟動標志
- uchar fm; //蜂鳴器計時變量
- /***************************************定義轉換控制寄存器控制位*****************************************/
- #define ADC_POWER 0X80 //電源控制位
- #define ADC_FLAG 0X10 //轉換結束標志位
- #define ADC_START 0X08 //轉換開始位
- /*********************************************定義AD轉換速度*********************************************/
- #define ADC_SPEEDLL_540 0X00
- #define ADC_SPEEDLL_360 0X20
- #define ADC_SPEEDLL_180 0X40
- #define ADC_SPEEDLL_90 0X60
- /***********寫時分秒地址************/
- #define write_shi 0x84
- #define write_fen 0x82
- #define write_miao 0x80
- #define write_ram 0xc0
- /***********讀時分秒地址************/
- #define read_shi 0x85
- #define read_fen 0x83
- #define read_miao 0x81
- #define read_ram 0xc1
- uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x46,0xbf};//共陽段碼 (0--9、黑屏、C、-)
- /*********************************************************************************************************
- ** 函數功能 :延時函數
- ** 函數說明 :利用軟件延時,占用CPU
- ** 入口參數 :time:需要延時的時間,
- ** 出口參數 :無
- *********************************************************************************************************/
- void Delay_ms(uint time)
- {
- uint i,j;
- for(i = 0;i < time;i ++)
- for(j = 0;j < 45;j ++);
- }
- /******************************/
- //void Delay_1(uint time)
- //{
- // uint i,j;
- // for(i = 0;i < time;i ++)
- // for(j = 0;j < 600;j ++);
- //}
- /*********************************************************************************************************
- ** 函數功能 :延時函數
- ** 函數說明 :利用軟件延時,占用CPU,經調試最小單位大約為1us
- ** 入口參數 :time:需要延時的時間,單位us
- ** 出口參數 :無
- *********************************************************************************************************/
- void delay(uchar n)
- {
- while (n--)
- {
- _nop_();
- _nop_();
- }
- }
- /*************蜂鳴器*****************/
- //void didi(uchar i)
- //{
- // uchar x;
- // for(x = i; x >0; x--)
- // {
- // dd = 0;
- // Delay_1(200);
- // dd = 1;
- // Delay_1(200);
- // }
- //}
- /*****************DS18B20******************/
- void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command
- {
- DQ = 1; //DQ復位,不要也可行。
- delay(1); //稍做延時
- DQ = 0; //單片機拉低總線
- //delay(250); //精確延時,維持至少480us
- delay(240);
- delay(240);
- DQ = 1; //釋放總線,即拉高了總線
- delay(240); //此處延時有足夠,確保能讓DS18B20發出存在脈沖。
- }
- uchar Read_One_Byte() //讀取一個字節的數據read a byte date
- //讀數據時,數據以字節的最低有效位先從總線移出
- {
- uchar i = 0;
- uchar dat = 0;
- for(i=8;i>0;i--)
- {
- DQ = 0; //將總線拉低,要在1us之后釋放總線
- //單片機要在此下降沿后的15us內讀數據才會有效。
- delay(1); //至少維持了1us,表示讀時序開始
- dat >>= 1; //讓從總線上讀到的位數據,依次從高位移動到低位。
- DQ = 1; //釋放總線,此后DS18B20會控制總線,把數據傳輸到總線上
- delay(7); //延時7us,此處參照推薦的讀時序圖,盡量把控制器采樣時間放到讀時序后的15us內的最后部分
- if(DQ) //控制器進行采樣
- {
- dat |= 0x80; //若總線為1,即DQ為1,那就把dat的最高位置1;若為0,則不進行處理,保持為0
- }
- delay(60); //此延時不能少,確保讀時序的長度60us。
- }
- return (dat);
- }
- void Write_One_Byte(uchar dat)
- {
- uchar i = 0;
- for(i=8;i>0;i--)
- {
- DQ = 0; //拉低總線
- delay(1); //至少維持了1us,表示寫時序(包括寫0時序或寫1時序)開始
- DQ = dat&0x01; //從字節的最低位開始傳輸
- //指令dat的最低位賦予給總線,必須在拉低總線后的15us內,
- //因為15us后DS18B20會對總線采樣。
- delay(60); //必須讓寫時序持續至少60us
- DQ = 1; //寫完后,必須釋放總線,
- dat >>= 1;
- delay(1);
- }
- }
- uint Get_Tmp() //獲取溫度get the temperature
- {
- float tt;
- uchar L,M;
- Init_Ds18b20(); //初始化
- Write_One_Byte(0xcc); //忽略ROM指令
- Write_One_Byte(0x44); //溫度轉換指令
- Init_Ds18b20(); //初始化
- Write_One_Byte(0xcc); //忽略ROM指令
- Write_One_Byte(0xbe); //讀暫存器指令
- L = Read_One_Byte(); //讀取到的第一個字節為溫度LSB
- M = Read_One_Byte(); //讀取到的第一個字節為溫度MSB
- //模擬顯示-0.5度,實際測溫需注解掉下面這兩句
- // L = 0xf8;
- // M = 0xff;
-
- //模擬顯示+0.5度,實際測溫需注解掉下面這兩句
- // L = 0x08;
- // M = 0x00;
- temp = M; //先把高八位有效數據賦于temp
- temp <<= 8; //把以上8位數據從temp低八位移到高八位
- temp = temp|L; //兩字節合成一個整型變量
- if(M >= 0x08) //判斷是否為負數
- {
- temp = ~temp + 1;//負數是以補碼的形式存放的需要取反加1
- s = 0xbf; //顯示負數符號
- }
- else s = 0; //為正數則不顯示負數符號
- tt = temp*0.0625; //得到真實十進制溫度值
- //因為DS18B20可以精確到0.0625度
- //所以讀回數據的最低位代表的是0.0625度
- temp = tt*10+0.5; //放大十倍
- //這樣做的目的將小數點后第一位也轉換為可顯示數字
- //同時進行一個四舍五入操作。
- return temp;
- }
- /****************溫度顯示函數**************/
- void Display_tem(uint temp) //顯示程序
- {
- uchar A1,A2,A3;
- A1 = temp/100; //百位
- A2 = temp%100/10; //十位
- A3 = temp%10; //個位
-
- if(A1 > 0 && s == 0 )
- {
- P0 = 0xff;
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[A1]; //顯示百位
- w1 = 0;
- Delay_ms(ba);
- }
- else
- {
- if(A1 == 0 && s == 0)
- {
- P0 = 0xff;
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[10]; //百位為0不顯
- w1 = 0;
- Delay_ms(ba);
- }
- else
- if(s != 0)
- {
- P0 = 0xff;
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = s; //百位為負數顯示-
- w1 = 0;
- Delay_ms(ba);
- }
-
-
- }
-
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[A2]&0X7F; //顯示十位,使用的是有小數點的數組(因為temp值擴大了10倍,雖然是十位,實際為個位)
- w2 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[A3];
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0x46; //顯示C字樣
- w4 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0;
- P0 = 0xff;
- Delay_ms(ba);
- }
- void display( uchar shi,uchar fen) //時間顯示函數
- {
- /*****正常顯示******/
- if(knum == 0)
- {
- if(shi/10 > 0)
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi/10]; //顯示小時十位
- w1 = 0;
- Delay_ms(ba);
- }
- else
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[10]; //小時十位為0不顯示
- w1 = 0;
- Delay_ms(ba);
-
- }
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- if(mh_count>=50)
- P0 = table[shi%10]&0x7f; //顯示小時個位
- else
- P0 = table[shi%10];
- w2 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- if(mh_count>=50)
- P0 = table[fen/10]&0x7f; //顯示分鐘十位
- else
- P0 = table[fen/10];
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w2 = 1; w3 = 1; w1 = 1;
- Delay_ms(50-ba);
- P0 = table[fen%10]; //顯示分鐘個位
- w4 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0; //這里掃描一個空位,數碼管前4位亮度就均勻了,第4位與前3位亮度一致,不然第4位要比前3位亮
- P0 = 0xff;
- Delay_ms(ba);
- }
- /********校時小時位閃爍************/
- // P0 = 0xff;
- if(knum==1)
- {
- if( shan==0 )
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = 0xff; //顯示小時十位
- w1 = 0;
- Delay_ms(ba);
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;;
- w2 = 0;
- Delay_ms(ba);
- }
-
- else
- {
- w2 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi/10]; //顯示小時十位
- w1 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi%10];
- w2 = 0;
- Delay_ms(ba);
- }
- P0 = 0xff;
- w1 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[fen/10];
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w2 = 1; w3 = 1; w1 = 1;
- Delay_ms(50-ba);
- P0 = table[fen%10]; //顯示分鐘個位
- w4 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0; //這里掃描一個空位,數碼管前4位亮度就均勻了,第4位與前3位亮度一致,不然第4位要比前3位亮
- P0 = 0xff;
- Delay_ms(ba);
- }
- /*******校時分鐘位閃爍*******/
- if(knum==2 )
- {
- if(shan==0)
- {
- w2 = 1; w1 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = 0xff; //顯示小時十位
- w3 = 0;
- Delay_ms(ba);
- P0 = 0xff;
- w1 = 1; w3 = 1; w2 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;;
- w4 = 0;
- Delay_ms(ba);
- }
- else
- {
- w2 = 1; w1 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[fen/10]; //顯示小時十位
- w3 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w3 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = table[fen%10];
- w4 = 0;
- Delay_ms(ba);
- }
- P0 = 0xff;
- w3 = 1; w2 = 1; w4 = 1;
- Delay_ms(50-ba);
- P0 = table[shi/10];
- w1 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w4 = 1; w3 = 1; w1 = 1;
- Delay_ms(50-ba);
- P0 = table[shi%10]; //顯示分鐘個位
- w2 = 0;
- Delay_ms(ba);
-
- P0 = 0xff;
- w1 = 1; w2 = 1; w3 = 1;
- Delay_ms(50-ba);
- P0 = 0xff;
- w5 = 0; //這里掃描一個空位,數碼管前4位亮度就均勻了,第4位與前3位亮度一致,不然第4位要比前3位亮
- P0 = 0xff;
- Delay_ms(ba);
- }
-
- }
- void t0_init()
- {
- // TMOD |= 0x02; //定時器0,8位自動重裝模式
- // TH0=TL0= 0X9c; //100微秒初值 @12MHz
- // TH0=TL0= 0Xce; //50微秒初值 @12MHz
- TMOD |= 0x01; //定時器0,16位模式
- TL0 = 0xF0; //設置定時初值 10毫秒初值 @12MHz
- TH0 = 0xD8; //設置定時初值
- EA=1;
- ET0=1;
- TR0 = 1;
- // EADC=1;
- }
- //void InitADC()
- //{
- // P1ASF = 0x01;//使能P1.0口ADC功能
- // ADC_RES = 0; //初始AD轉換結果為零
- // ADC_CONTR = 0xc8; //1100 1000 ,打開AD轉換電源,轉換速度180個時鐘周期,ADC_FLAG清零,ADC_START置1啟動AD,選擇P1.0為AD輸入通道
- // Delay_ms(1);
- //}
- /*********************************************************************************************************
- ** 函數功能 :內置ADC的初始化配置
- ** 函數說明 :使用內置ADC時需要先配置對應的P1口的管腳為模擬輸入
- ** 入口參數 :port:需要配置為模擬輸入的通道,使用或運算可以同時配置多個管腳
- ** 如:ADC_Init(ADC_PORT0 | ADC_PORT1 | ADC_PORT2)調用此函數后可以同時配置P1^0,P1^1,P1^2為模擬輸入
- ** 出口參數 :無
- *********************************************************************************************************/
- void ADC_Init()
- {
- P1ASF=0x01;//設置AD轉換通道 P1.0
- ADC_RES=0;//清空轉換結果
- ADC_CONTR=ADC_POWER | ADC_SPEEDLL_540;//打開AD轉化器電源
- // IE=0XA0;//開啟總中斷,ADC中斷
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- /*********************************************************************************************************
- ** 函數功能 :獲取ADC對應通道的值,查詢法
- ** 函數說明 :每次只能獲取一個通道的值,不同通道需要分別調用該函數獲取
- ** 入口參數 :
- ** 出口參數 :
- *********************************************************************************************************/
- uchar GetADCResult()//讀取通道ch的電壓值
- {
- // unsigned int ADC_RESULT = 0;//用來存放結果
- // float result;
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL_540 | ADC_START;//開始轉換,并設置測量通道為P1^0
- _nop_();//需經過四個CPU時鐘延時,上述值才能保證被設進ADC_CONTR控制寄存器
- _nop_();
- _nop_();
- _nop_();
- while(!(ADC_CONTR & ADC_FLAG));//等待轉換結束
- ADC_CONTR &= ~ADC_FLAG;//軟件清除中斷控制位
- // ADC_RESULT = ADC_RES;
- // ADC_RESULT = (ADC_RESULT << 2) | (0x02 & ADC_RESL); //默認數據存儲方式:高八位在ADC_RES,低二位在ADC_RESL低二位
- // result = ADC_RESULT * 5.0 / 1024.0 ; //基準電壓為電源電壓5V,10的分辨率,即1024
- // return result;
- return ADC_RES;
- }
- void timer0() interrupt 1
- {
- TL0 = 0xF0; //重裝定時初值 10毫秒初值 @12MHz
- TH0 = 0xD8; //重裝定時初值
-
- mh_count++; //冒號閃爍變量
- if(mh_count==100) //1秒時間到
- {
- mh_count=0;
- count++;
- if(count==5)
- {
- count=0;
- flag = !flag;
- }
- }
- if(knum != 0) //調時間的時候,閃爍的位表示為調節的位
- {
- shan_cont++;
- if(shan_cont==30) //設置時,300ms閃爍時間,可根據實際效果調整
- {
- shan_cont=0;
- shan = !shan;
- }
- }
- if(flag_fm) //如果蜂鳴器啟動標志為1
- {
- dd = 0; //蜂鳴器響
- fm++; //計時變量自加
- if(fm == 30) //到300ms,蜂鳴器停
- {
- fm = 0; //計時變量清零
- dd = 1; // 蜂鳴器停
- flag_fm = 0;//啟動標志清零
- }
- }
- }
- //寫DS1302數據
- void Write_DS1302_DAT(uchar cmd, uchar dat)
- {
- uchar i;
- TRST = 0; //拉低使能端
- TSCLK = 0;//拉低數據總線
- TRST = 1; //拉高使能端,產生上升沿開始寫數據
- for(i = 0; i < 8; i++)//每次寫1位,寫8次
- {
- TSCLK = 0; //拉低時鐘總線
- TIO = cmd & 0x01; //寫1位數據,從最低位開始寫
- TSCLK = 1; //拉高時鐘總線,產生上升沿數據被DS1302讀走
- cmd >>=1; //右移一位
- }
- for(i = 0; i < 8; i++)//每次寫1位,寫8次
- {
- TSCLK = 0; //拉低時鐘總線
- TIO = dat & 0x01; //寫1位數據,從最低位開始寫
- TSCLK = 1; //拉高時鐘總線,產生上升沿數據被DS1302讀走
- dat >>= 1; //右移一位
- }
- }
- //讀DS1302數據
- uchar Read_DS1302_DAT(uchar cmd)
- {
- uchar i, dat;
- TRST = 0; //拉低使能端
- TSCLK = 0; //拉低數據總線
- TRST = 1; //拉高使能端,產生上升沿開始寫數據
- for(i = 0; i < 8; i++)//每次寫1位,寫8次
- {
- TSCLK = 0; //拉低時鐘總線
- TIO = cmd & 0x01;//寫1位數據,從最低位開始寫
- TSCLK = 1; //拉高時鐘總線,產生上升沿數據被DS1302讀走
- cmd >>=1; //右移一位
- }
- for(i = 0; i < 8; i++)//每次讀1位,讀8次
- {
- TSCLK = 0; //拉低時鐘總線,產生下降沿,DS1302把數據放到TIO上
- dat >>= 1; //右移一位
- if(TIO) dat |= 0x80;//讀取數據,從最低位開始
- TSCLK = 1; //拉高時鐘總線,以備下一次產生下降沿
- }
- return dat; //返回讀出數據
- }
- //數據轉BCD碼
- uchar Dat_Chg_BCD(uchar dat)
- {
- uchar dat1, dat2;
- dat1 = dat / 10;
- dat2 = dat % 10;
- dat2 = dat2 + dat1 * 16;
- return dat2;
- }
- //BCD碼轉換為數據
- uchar BCD_Chg_Dat(uchar dat)
- {
- uchar dat1, dat2;
- dat1 = dat / 16;
- dat2 = dat % 16;
- dat2 = dat2 + dat1 * 10;
- return dat2;
- }
- void init_1302() //初始化函數 設置時間
- { //加備用電池,掉電走時
- // if((Read_DS1302_DAT(0x81)& 0x80) != 0) //讀出秒數據,再跟80h(0x80)與運算看結果,結果是0則不需要初始化1302;是80h就要初始化!
-
- if(Read_DS1302_DAT(read_ram) != 0xaa) //如果第00個RAM位置不等于0xaa,就初始化1302
- {
- Write_DS1302_DAT(0x8e, 0);//清除寫保護
- Write_DS1302_DAT(write_miao, Dat_Chg_BCD(58));//58秒(并且進行BCD碼轉換)
- Write_DS1302_DAT(write_fen, Dat_Chg_BCD(10));//10分
- Write_DS1302_DAT(write_shi, Dat_Chg_BCD(9));//9時
- Write_DS1302_DAT(write_ram,0xaa);//寫入初始化標志RAM(第00個RAM位置)
- Write_DS1302_DAT(0x8e, 0x80);//開寫保護
- }
- }
- void read_sf()
- {
- miao = BCD_Chg_Dat(Read_DS1302_DAT(0x81));//讀秒寄存器(并且進行BCD碼轉換)
- fen = BCD_Chg_Dat(Read_DS1302_DAT(0x83));//讀分寄存器
- shi = BCD_Chg_Dat(Read_DS1302_DAT(0x85));//讀時寄存器
- // display(shi,fen);
- }
- void zdjs() //自動校時,這方法測試可行,每天減去快出的秒數
- {
- if((shi==7)&&(fen==30)&&(miao==6)) // 時鐘每天快6秒
- {
- if(flag_js==0)
- {
- Write_DS1302_DAT(0x8e,0x00); //寫保護取消
- Write_DS1302_DAT(write_miao,0x00); //寫秒0,這里是假如每天快6秒,每到這個時候就減去6秒
- Write_DS1302_DAT(0x8e,0x80); //啟動寫保護
- flag_js=1; //標志位置1,不然這里會成一個死循環
- }
- }
- if((shi==7)&&(fen==35)&&(miao==0))
- flag_js=0; //標志位清零,準備第二天校時
- }
- void keysan()
- {
- static bit kf1=0, kf3=0,kf2=0; //自鎖標志,這里一定要加static(或者用全局變量),否則按鍵不靈
- static uint i=0,j=0,k=0,m=0,n=0; //消抖延時變量
-
- if(key1==1) //設置 //IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位
- {
- i=0; //按鍵消抖計時變量清零
- kf1=0; //按鍵自鎖標志清零
- }
- else if(kf1 == 0) //有按鍵按下,且是第一次被按下
- {
- flag_fm = 1; //啟動蜂鳴器
- ++i;
- if(i>10) //i>10 ADC查詢方式用
- {
- i=0;
- kf1=1; //自鎖按鍵置位,避免一直觸發
- knum++;
- if(knum==1)
- {
- Write_DS1302_DAT(0x8e,0x00); //寫保護取消
- Write_DS1302_DAT(write_miao,0x80); // 寫秒80,時鐘停止走時;
-
- }
- if(knum==3)
- {
- knum = 0;
- Write_DS1302_DAT(write_miao,0x00);
- Write_DS1302_DAT(0x8e,0x80); //保護啟動
- }
- }
- }
- /************顯示和光控切換****************/
- if(knum == 0)
- {
- if(key3==1) //設置 //IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位
- {
- m=0; //按鍵消抖計時變量清零
- kf3=0; //按鍵自鎖標志清零
- }
- else if(kf3 == 0) //有按鍵按下,且是第一次被按下
- { flag_fm = 1; //啟動蜂鳴器
- ++m;
- if(m>10) //i>10 ADC查詢方式用
- {
- m=0;
- kf3=1; //自鎖按鍵置位,避免一直觸發
- xs++;
- if(xs==3)
- {
- xs = 0;
-
- }
- }
- }
- if(key2==1) //設置 //IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標志位
- {
- n=0; //按鍵消抖計時變量清零
- kf2=0; //按鍵自鎖標志清零
- }
- else if(kf2 == 0) //有按鍵按下,且是第一次被按下
- { flag_fm = 1; //啟動蜂鳴器
- ++n;
- if(n>10) //i>10 ADC查詢方式用
- {
- n=0;
- kf2=1; //自鎖按鍵置位,避免一直觸發
- flag_gk = !flag_gk;
- }
- }
- }
- ///-------加--------///
- if(knum != 0)
- {
- if(key2==0) //加
- {
-
- j++;
- // if(j >= 5000) //長按連加 ADC中斷方式用
- if(j >= 100) //長按連加 ADC查詢方式用
-
- { //flag_fm = 0;
- if(knum==2)
- {
- fen++;
- fen=fen/10*16+fen%10; //轉為16進制
- if(fen==0x60)
- fen=0x00;
- Write_DS1302_DAT(write_fen,fen);
- read_sf(); //讀出時間,然后顯示
- }
-
- if(knum==1)
- {
- shi++;
- shi=shi/10*16+shi%10; //轉為16進制
- if(shi==0x24)
- shi=0x00;
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
-
- j=90; //這里j的值可以設置連加的快慢,j的值越大就越快
- //因為初值越大,加到100的時間就越短
- flag_fm = 1; //啟動蜂鳴器
- }
- }
-
- else
- {
- if(j>10 && j<100) //短按
- {
- flag_fm = 1; //啟動蜂鳴器
- if(knum==2)
- {
- fen++;
- fen=fen/10*16+fen%10; //轉為16進制
- if(fen==0x60)
- fen=0x00;
- Write_DS1302_DAT(write_fen,fen);
- read_sf(); //讀出時間,然后顯示
- }
-
- if(knum==1)
- {
- shi++;
- shi=shi/10*16+shi%10; //轉為16進制
- if(shi==0x24)
- shi=0x00;
-
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
-
- j=0;
- }
- }
-
- //----------減-----------//
- if(key3==0) //減
- { flag_fm = 1; //啟動蜂鳴器
- k++;
- if(k >= 100) //長按
- {
- if(knum==2)
- {
- fen--;
- fen=fen/10*16+fen%10; //轉為16進制
- if(fen==-1)
- fen=0x59;
- Write_DS1302_DAT(write_fen,fen);
- read_sf();
- }
- if(knum==1)
- {
- shi--;
- shi=shi/10*16+shi%10; //轉為16進制
- if(shi==-1)
- shi=0x23;
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
- k=90;
- }
- }
- else
- {
- if(k>10 && k<100) //短按
- {
- flag_fm = 1; //啟動蜂鳴器
- if(knum==2)
- {
- fen--;
- fen=fen/10*16+fen%10; //轉為16進制
- if(fen==-1)
- fen=0x59;
- Write_DS1302_DAT(write_fen,fen);
- read_sf();
- }
- if(knum==1)
- {
- shi--;
- shi=shi/10*16+shi%10; //轉為16進制
- if(shi==-1)
- shi=0x23;
- Write_DS1302_DAT(write_shi,shi);
- read_sf();
- }
- }
- k=0; //消抖變量清零,為下次按鍵做準備
- }
- }
- }
- void main()
- {
- // uchar i;
- t0_init();
- init_1302();
- // InitADC();
- ADC_Init();
- flag_fm = 1; //啟動蜂鳴器
- while(1)
- {
- read_sf();
- switch(xs)
- {
- case 0:if(flag==0 && knum == 0) //時間、溫度輪流顯示,5秒切換一次
- {Display_tem(Get_Tmp());}
- else
- display( shi,fen); break;
- case 1: display( shi,fen); break; //顯示時間
- case 2: Display_tem(Get_Tmp()); break;//顯示溫度
- default: break;
- }
- keysan();
- zdjs();//自動校時
- // if(shi>=5 && shi<=21) //5~21 亮度最大
- // ba=20;
- // else ba=1; //22~4 亮度最小
- // if(ADC_RES>5 && ADC_RES<25) ba=40;
- // if(ADC_RES>25 && ADC_RES<50) ba=39; //10級亮度,ba值越大,LED越亮
- // if(ADC_RES>50 && ADC_RES<80) ba=35;
- // if(ADC_RES>80 && ADC_RES<100) ba=30;
- // if(ADC_RES>100 && ADC_RES<130) ba=25;
- // if(ADC_RES>130 && ADC_RES<150) ba=20;
- // if(ADC_RES>150 && ADC_RES<180) ba=15;
- // if(ADC_RES>180 && ADC_RES<200) ba=10;
- // if(ADC_RES>200 && ADC_RES<230) ba=5;
- // if(ADC_RES>230 && ADC_RES<250) ba=1;
- /**************************/
- if(!flag_gk) //如果光控標志為0,就為自動亮度 ;默認為自動亮度
- {
- if(GetADCResult()>5 && GetADCResult()<25) ba=40;
- if(GetADCResult()>25 && GetADCResult()<50) ba=39; //10級亮度,ba值越大,LED越亮
- if(GetADCResult()>50 && GetADCResult()<80) ba=35;
- if(GetADCResult()>80 && GetADCResult()<100) ba=30;
- if(GetADCResult()>100 && GetADCResult()<130) ba=25;
- if(GetADCResult()>130 && GetADCResult()<150) ba=20;
- if(GetADCResult()>150 && GetADCResult()<180) ba=15;
- if(GetADCResult()>180 && GetADCResult()<200) ba=10;
- if(GetADCResult()>200 && GetADCResult()<230) ba=5;
- if(GetADCResult()>230 && GetADCResult()<250) ba=1;
- }
- else ba = 40; // 否則為最大亮度
- /*********************/
- if((shi>=5 && shi<=21) && fen ==0 && miao == 0) //整點報時
- {
- flag_fm = 1;
- }
- }
- }
- /*------------------------------------------------
- ADC中斷處理函數
- ------------------------------------------------*/
- //void adc_isr() interrupt 5 using 1
- //{
- //// unsigned int temp;
- //// temp=ADC_RES; //AD取8位結果
- //// result=temp*0.01953125*1000; //ad結果換算成電壓值, 將5V分成256份,每份5v/256=0.01953125v ,再擴大1000倍
- //// ge=result/1000;
- //// shifen=result%1000/100;
- //// baifen=result%100/10;
- //
- // ADC_CONTR = 0xc8;//開啟轉換
- //}
復制代碼 全部資料51hei下載地址:
1寸數碼管時鐘資料.rar
(283.97 KB, 下載次數: 265)
2018-12-18 19:25 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|