可以用紅外遙控器控制的數碼管時鐘,不同按鍵控制寫入ds1302的時間值,從而調整時間。也可通過按鍵顯示溫度,每次顯示后將溫度值順序記入24c02。可以通過仿真查看24c02內的值。不同遙控器需要更改紅外讀入的鍵值,才能正常使用。仿真中用按鍵代替了紅外顯示溫度。實物在普中開發板上運行通過。部分程序借用普中開發板附帶代碼修改而成。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (16.37 KB, 下載次數: 43)
下載附件
2020-5-4 16:01 上傳
單片機源程序如下:
- /*******************************************************************************
- 8 digits LED display Ds1302 Real time clock with IR remote adjust and temperature display
- ********************************************************************************/
- #include<reg52.h>
- #include<intrins.h>
- sbit SCL = P2^1; /* 定義位變量 */ // I2C總線的時鐘信號
- sbit SDA = P2^0; // I2C總線的數據信號
- sbit DS1302_CK = P3^6; //時鐘
- sbit DS1302_IO = P3^4; //數據
- sbit DS1302_CE = P3^5;// DS1302復位
- sbit LS138A = P2^2;
- sbit LS138B = P2^3;
- sbit LS138C = P2^4;
- sbit BEEP = P1^5;
- sbit IRIN = P3^2;
- unsigned char t0,miao,fen,shi;
- unsigned int tabe2[8];
- unsigned char IRCOM[7];
- unsigned char AT24C02Address = 0;
- unsigned char code tabe1[]={~0xC0,~0xF9,~0xA4,~0xB0,~0x99,~0x92,~0x82,~0xF8,~0x80,~0x90,~0x40,};
- void display();
- void display_date();
- void display_temp();
- void Read_RTC();
- extern unsigned int ReadTemperature(void);
- extern void InitDS1302();
- extern void DS1302SingleWrite(unsigned char reg, unsigned char dat);
- extern unsigned char DS1302SingleRead(unsigned char reg);
- extern void DS1302SingleWriteRAM(unsigned char ram, unsigned char dat);
- extern unsigned char DS1302SingleReadRAM(unsigned char ram);
- extern void AT24C02_Write1Byte( unsigned char AT24C02_Address, unsigned char AT24C02_1Byte);
- /******************************************************************/
- /* 讀時鐘數據 */
- /******************************************************************/
- void Read_RTC(void) //讀取 日歷
- {
- //unsigned char i,*p;
- //p=read_rtc_address; //地址傳遞
- //for(i=0;i<7;i++) //分7次讀取 秒分時日月周年
- //{
- //tmpdate[i]=Read_Ds1302(*p);
- //p++;
- //}
- miao=DS1302SingleRead(0x80); miao=(miao>>4)*10+(miao&0x0f);
- fen= DS1302SingleRead(0x81); fen=(fen>>4)*10+(fen&0x0f);
- shi= DS1302SingleRead(0x82); shi=(shi>>4)*10+(shi&0x0f);
- }
- void delay(unsigned int a)
- {
- unsigned char i;
- while(a--)
- {
- for(i=0;i<=80;i++)
- ;
- }
-
- }
- void delayIR(unsigned char x) //x*0.14MS
- {
- unsigned char y;
- while(x--)
- {
- for (y = 0; y<13; y++) {}
- }
- }
- //=================================BEEP驅動===========================================//
- //sbit Bell_Out = P3 ^ 0;//元件是動圈式揚聲器(并非有源蜂鳴器),需要MCU驅動發聲
- /********************************************************************************************/
- void bell( unsigned char a,unsigned char b,unsigned char c,unsigned char d)
- {
- for(;a>0;a--){//第一個聲音的長度
- BEEP = !BEEP;//取反揚聲器驅動口,以產生音頻
- delay(b);//音調設置延時
- }
- for(;c>0;c--){//同上
- BEEP = !BEEP;
- delay(d);//
- }
- BEEP = 1;
- }
- /********************************************************************************************/
- //--------------------------------------------揚聲器--按鍵音
- //void beep_k(void){beep(10,60,5,250); }
- //--------------------------------------------揚聲器--鬧鐘報警
- //void beep_a(void){beep(250,16,150,40); }//BELL
- //--------------------------------------------揚聲器--成功音
- //void beep_y(void){beep(50,30,100,50); }//BELL
- //--------------------------------------------揚聲器--無效音
- //void beep_n(void){beep(50,80,100,100); }//BELL
- /********************************************************************************************/
- void beep(void)
- {
- unsigned char i;
- for (i=0;i<100;i++)
- {
- delay(1);
- BEEP=!BEEP; //BEEP reverse
- }
- BEEP=1; //close buzzer
- }
- void main()
- {
- BEEP = 1; //close buzzer
- IT0=1; //enable timer 0
- //IT1=1;
- EX0=1; //enable int 0
- EX1=1; //enable int 1
- TMOD=0x01,TH0=0x3c,TL0=0xb0, EA=1;//定時器0方式1, enable all int
- ET0=1; //INT0下降沿有效
- TR0=1;
-
- InitDS1302();
- //DS1302SingleWrite(0x83,0x11); //set DATE
- //DS1302SingleWrite(0x84,0x12); //set MONTH
- //DS1302SingleWrite(0x85,0x05); //set DAY Sun=0,Mon=1
- //DS1302SingleWrite(0x86,0x14); //set YEAR
- // DS1302SingleWriteRAM(0x00,0x21); //set Alarm1 Hour
- // DS1302SingleWriteRAM(0x01,0x15); //set Alarm1 Minute
- //DS1302SingleWriteRAM(0x02,0x18); //set Alarm2 Hour
- //DS1302SingleWriteRAM(0x03,0x15); //set Alarm2 Minute
- while(1)
- {
- display();
- if (fen==0&miao<3)
- bell(4,1,8,1);
- //if (DS1302SingleReadRAM(0x00) == ((shi/10)*16+shi%10)
- // &DS1302SingleReadRAM(0x01) == ((fen/10)*16+fen%10))
-
- // {bell(4,1,8,1);}
-
- //if (DS1302SingleReadRAM(0x02) == ((shi/10)*16+shi%10)
- // &DS1302SingleReadRAM(0x03) == ((fen/10)*16+fen%10))
- // {bell(4,1,8,1); }
-
- }
- }
- //外部中斷0 IR Remote
- void IR_IN() interrupt 0 //using 0
- {
- unsigned char j,k,N=0;
- P0=0x00;
- //char bx;
- EX0 = 0; //關掉外部中斷防止中斷的再次發生進入檢測引導碼階段(9ms的低電平4.5ms的高電平)
- delayIR(15);
- if (IRIN==1)
- { EX0 =1; //9ms的檢測檢測結束從新打開外部中斷
- return;
- }
- //確認IR信號出現
- while (!IRIN) //等IR變為高電平,跳過9ms的前導低電平信號。
- {delayIR(1);}
- for (j=0;j<4;j++) //收集四組數據
- {
- for (k=0;k<8;k++) //每組數據有8位
- {
- while (IRIN) //等 IR 變為低電平,跳過4.5ms的引導高電平信號。
- {delayIR(1);}
- while (!IRIN) //等 IR 變為高電平
- {delayIR(1);}
- while (IRIN) //計算IR高電平時長(0和1的低電平的時長一樣的,只要判斷高電平時長超過0.56ms并小于1.12ms為1否則為0)
- {
- delayIR(1);
- N++;
- if (N>=30)
- {
- EX0=1;
- return;
- } //0.14ms計數過長自動離開。
- } //高電平計數完畢
- IRCOM[j]=IRCOM[j] >> 1; //數據最高位補“0”
- if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //高電平持續時間大于1.12ms則數據最高位補“1”
- N=0;
- } //end for k
- } //end for j
-
- if (IRCOM[2]!=~IRCOM[3]) // 判斷有沒有誤碼(有責放棄沒有判斷鍵碼)
- { EX0=1;
- return;
- }
- beep();
- DS1302SingleWrite(0x8e,0x00); //allow write to DS1302
- switch(IRCOM[2])
- {
- case 0x40: if (fen>0) {fen--;} else{fen=59;} DS1302SingleWrite(0x81,((fen/10)*16+fen%10)); break;//minute-1,write to ds1302
- case 0x43: fen++; if (fen>=60) {fen=0;} DS1302SingleWrite(0x81,((fen/10)*16+fen%10)); break;//minute+1
- case 0x15: if (shi>0) {shi--;} else{shi=23;} DS1302SingleWrite(0x82,((shi/10)*16+shi%10)); break;//hour-1
- case 0x09: shi++; if (shi>=24) {shi=0;} DS1302SingleWrite(0x82,((shi/10)*16+shi%10)); break;//hour+1
- case 0x47: miao=0; DS1302SingleWrite(0x80,0x00); break;//second=0
- case 0x44:
-
- display_date(); //display year,month,date
- break;
- case 0x45:
- display_temp();
- }
- DS1302SingleWrite(0x8e,0x80); // protect write to DS1302
- EX0 = 1;
- }
- void display()
- {
- unsigned char i;
- tabe2[7]=tabe1[miao%10];
- tabe2[6]=tabe1[miao/10];
- tabe2[5]=0x40;
- tabe2[4]=tabe1[fen%10];
- tabe2[3]=tabe1[fen/10];
- tabe2[2]=0x40;
- tabe2[1]=tabe1[shi%10];
- tabe2[0]=tabe1[shi/10];
- for(i=0;i<8;i++)
- {
- switch(i)
- {
- case 0:LS138A=0; LS138B=0; LS138C=0; break;
- case 1:LS138A=1; LS138B=0; LS138C=0; break;
- case 2:LS138A=0; LS138B=1; LS138C=0; break;
- case 3:LS138A=1; LS138B=1; LS138C=0; break;
- case 4:LS138A=0; LS138B=0; LS138C=1; break;
- case 5:LS138A=1; LS138B=0; LS138C=1; break;
- case 6:LS138A=0; LS138B=1; LS138C=1; break;
- case 7:LS138A=1; LS138B=1; LS138C=1; break;
-
- }
- P0=tabe2[i];
- delay(5);
- }
- }
- /* every second timer update second,minute,hour 2 times.*/
- void timer0(void) interrupt 1
- {
-
- TH0=0x3c,TL0=0xb0;
- t0++;
- //display();
- if(t0==10)
- {
-
- t0= 0;
- Read_RTC();
-
- }
- }
- void display_date(void)
- {
- unsigned char i;
- miao=DS1302SingleRead(0x83); miao=(miao>>4)*10+(miao&0x0f);
- fen= DS1302SingleRead(0x84); fen=(fen>>4)*10+(fen&0x0f);
- shi= DS1302SingleRead(0x86); shi=(shi>>4)*10+(shi&0x0f);
- for (i=1;i<255;i++)
- display();
-
- }
- void display_temp(void)
- {
- unsigned char n;
- P0=0x00;
- miao = 0;
- fen = ReadTemperature();
- shi = 0;
- AT24C02_Write1Byte(AT24C02Address,fen);
- AT24C02Address++;
- for (n=1;n<255;n++)
- display();
- }
- void ButtonPress() interrupt 2 //using INT1
- {
-
- display_temp();
- }
復制代碼
51hei.png (7.12 KB, 下載次數: 41)
下載附件
2020-5-4 16:02 上傳
所有資料51hei提供下載:
紅外遙控器調節時間的數碼管時鐘.zip
(34.97 KB, 下載次數: 67)
2020-5-4 06:12 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|