|
基于stc15f204s的水晶倒計(jì)時(shí)牌
第一次在這發(fā)帖,如有不周請(qǐng)指正!
以前在網(wǎng)上發(fā)現(xiàn)了一個(gè)神操作,就是把搭棚電路封裝在滴膠里,美觀耐用且防止氧化。與其說(shuō)是電路制作,我覺(jué)得是藝術(shù)品。寒假正好沒(méi)事干,就搞了一個(gè)倒計(jì)時(shí)牌,把之前學(xué)的51單片機(jī)知識(shí)用一用,順便督促一下自己珍惜時(shí)間。
剛開(kāi)始是想用 STC15F104E(因?yàn)橘I(mǎi)多了)【注意,這個(gè)單片機(jī)內(nèi)部定時(shí)器是T0和T1,跟現(xiàn)在的新產(chǎn)品不一樣】 ,做了幾個(gè)功能發(fā)現(xiàn)到處出bug,而且下載器里面沒(méi)有這個(gè)型號(hào),數(shù)據(jù)手冊(cè)里面也只不過(guò)提了一兩次。后來(lái)一查發(fā)現(xiàn)這個(gè)型號(hào)早已經(jīng)停產(chǎn)了,而且它的定時(shí)器和外部中斷由BUG(怒)。于是換了個(gè)stc15w204s。工欲善其事必先利其器,計(jì)劃在面包板上先做程序,調(diào)試好確定管腳分配后再搭棚。面包板接觸不好(通。,所以做了個(gè)單片機(jī)轉(zhuǎn)接座:
1583236459511.jpg (3.58 MB, 下載次數(shù): 78)
下載附件
單片機(jī)轉(zhuǎn)接座
2020-3-3 20:08 上傳
1583236398866.jpg (4.46 MB, 下載次數(shù): 84)
下載附件
實(shí)驗(yàn)用面包板
2020-3-3 20:08 上傳
程序不是很復(fù)雜,有的地方有點(diǎn)啰嗦(大神勿噴),這里簡(jiǎn)單解釋一下,整體思路是單片機(jī)驅(qū)動(dòng)hc595,595驅(qū)動(dòng)三位數(shù)碼管的段,單片機(jī)用9012擴(kuò)流驅(qū)動(dòng)數(shù)碼管的位,int0借1838b紅外接收,再加上ds1302時(shí)鐘芯片和ds18b20溫度芯片,還剩一個(gè)管腳接了rgb自閃燈(本來(lái)可以接紅外發(fā)射實(shí)現(xiàn)數(shù)據(jù)雙向傳輸?shù),不過(guò)我懶得寫(xiě)程序和功能了)平時(shí)單片機(jī)就是while(1)等待,刷新、ir接收什么的全靠?jī)蓚(gè)定時(shí)器T0 T1和外部中斷0觸發(fā)。紅外接收程序是我自己想的,非常繁瑣(本可以簡(jiǎn)單一些,不過(guò)我這么寫(xiě)可以最大程度上減少誤觸發(fā))。
單片機(jī)代碼如下:- #include<STC15.h>
- #include<stdio.h>
- #include<INTRINS.H>
- sfr WDT_COUNTER = 0xc1;//【下載的時(shí)候請(qǐng)勾選‘上電復(fù)位由硬件啟動(dòng)看門(mén)狗’】
- //sbit CLR_WDT = WDT_COUNTER^5; //軟件置1,防止誤殺
- /*
- STC15w204s單片機(jī),。數(shù)碼管共陽(yáng),0亮1滅。
- 使用兩片74hc595擴(kuò)充管腳數(shù)目,連接ds1302時(shí)鐘芯片和1838B紅外接收頭。
- **********IR接收程序(NEC協(xié)議)************
- 基于狀態(tài)機(jī),拒絕軟件delay函數(shù),只使用一個(gè)定
- 時(shí)器和一個(gè)中斷(必須支持上升/下降沿中斷),
- 有利于系統(tǒng)資源的節(jié)約。程序錯(cuò)誤無(wú)累計(jì),利于
- 長(zhǎng)期穩(wěn)定運(yùn)行。使用定時(shí)器作為時(shí)間基準(zhǔn),如需
- 要移植程序,只需要按照源程序時(shí)間要求重新生
- 成定時(shí)器初始化函數(shù)。其中所有關(guān)鍵組件,均已
- 在其后注明【這是計(jì)劃的一部分】。
- *******************************2020年2月20日
- BUG記錄:
- int0輸入信息量過(guò)大會(huì)造成程序跑飛
- */
- typedef unsigned char u8;//【這是計(jì)劃的一部分】
- typedef unsigned int u16;
- //595引腳連接(待定)Q0對(duì)應(yīng)低位,Q7對(duì)應(yīng)高位
- sbit ser=P5^5; //也叫SI
- sbit srclk=P1^5; //刷新輸出,上升沿有效
- sbit rclk=P1^4; //內(nèi)部移位,上升沿有效
- //1838B
- sbit ir=P3^2;//【這是計(jì)劃的一部分】
- //18B20
- sbit DSPORT=P5^4;
- //DS1302
- sbit RST=P1^3; //控制器復(fù)位 高電平時(shí)才能工作,其實(shí)與復(fù)位關(guān)系不大
- sbit DSIO=P1^2; //數(shù)據(jù)
- sbit SCLK=P1^1; //時(shí)
- //led
- sbit led=P1^0;
- //有關(guān)于紅外接收的狀態(tài)標(biāo)志位,定時(shí)器用t0,中斷用int0。【這是計(jì)劃的一部分】
- bit iract=0; //紅外活動(dòng)
- u8 irstate=0; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- bit started=0; //已收到報(bào)頭,請(qǐng)忽視報(bào)尾
- bit t0reset=0; //定時(shí)器0溢出就回到等待狀態(tài)
- bit int0reset=0; //int0觸發(fā)就回到等待狀態(tài)
- bit int0negfall=0; //忽視int0的下降沿(只允許上升沿中斷)
- u8 bitamount=0; //收到的總位數(shù)(0-32)
- bit irbit=0; //當(dāng)前ir位數(shù)
- u8 ir1=0x00,ir2=0xff,ir3=0x00,ir4=0xff;//ir接受結(jié)果
- bit irreceived=0;//如有待處理的紅外信息,此位置1
- u8 irresult=0;//irdecode函數(shù)解碼結(jié)果
- //system
- u16 data count=1000;
- u8 data stat=1;//0熄屏;1正常帶溫度;2正常無(wú)溫度;3設(shè)置界面(3set,4h十位,5h個(gè)位,6d百位,7d十位,8d個(gè)位)
- u8 data days=123; //倒計(jì)時(shí)應(yīng)該顯示的天數(shù),同步存放于0000h
- u8 data wk=0x00;//上次查詢(xún)到的星期,將與此次查詢(xún)到的比較同步存放于0001h
- u8 data keynum=0;//按鍵輸入的數(shù)字
- //sbit led=P1^2;
- //顯示相關(guān)變量
- u8 code duan[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,0x11,0xc1,0x63,0x85,0x61,0x71,//0-15
- 0x02,0x9e,0x24,0x0c,0x98,0x48,0x40,0x1e,0x00,0x08,0x10,0xc0,0x62,0x84,0x60,0x70,//16-31
- 0xff,0xef,0x91};//數(shù)碼管顯示,0-9,A,b,C,d,E,F,不亮,(5)(14),_,H,(13).0-34
- u8 data num2,num1,num0;
- u8 data w=2;//數(shù)碼管的位號(hào)
- sbit wei0=P3^3;
- sbit wei1=P3^7;
- sbit wei2=P3^6;
- //18b20
- int temp;//溫度*100
- //1302
- //---DS1302時(shí)鐘初始化2016年5月7日星期六12點(diǎn)00分00秒。---//
- //---存儲(chǔ)順序是秒,分,時(shí), 日, 月, 星期, 周年,存儲(chǔ)格式是用BCD碼---//
- //u8 TIME[7] = {0, 0, 0x12, 0x07, 0x05, 0x06, 0x16};
- u8 TIME[7]= {0x00, 0x55, 0x23, 0x15, 0x10, 0x02, 0x19}; //星期是time[5],小時(shí)是time【2】
- u8 timeset[7]={0x00, 0x02, 0x13, 0x07, 0x12, 0x06, 0x19};
- //---DS1302寫(xiě)入和讀取時(shí)分秒的地址命令---//
- //---秒分時(shí)日月周年 最低位讀寫(xiě)位;-------//
- u8 code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
- u8 code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //兩者的區(qū)別只在于末位(發(fā)送的時(shí)候作為最先發(fā)送的)用于決定該命令是讀還是寫(xiě)
- //基本函數(shù)
- void hc595write();
- void intinit();
- void Timer1Init();
- //紅外相關(guān)函數(shù)
- void irinit();
- void irdecode();
- //溫度相關(guān)函數(shù)
- void Ds18b20Init();
- void Ds18b20WriteByte(unsigned char dat);
- unsigned char Ds18b20ReadByte();
- int Ds18b20ReadTemp();
- //eeprom相關(guān)函數(shù)
- void iaperase(unsigned char addrh,unsigned char addrl);
- void iapwrite(unsigned char addrh,unsigned char addrl,unsigned char dat);
- unsigned char iapread(unsigned char addrh,unsigned char addrl);
- void iaprst();
- //ds1302相關(guān)函數(shù)
- void Ds1302Write(u8 addr, u8 dat);
- u8 Ds1302Read(u8 addr);
- void Ds1302set();
- void Ds1302ReadTime();
- void intinit()
- {
- EA=1;
- ET0=1;
- //ET1=1;
- IE2=0x04; //T2使能,T2的優(yōu)先級(jí)固定為低。IE2不可位尋址,ET2在右數(shù)第三位。
- EX0=1; //P3.2中斷使能
- IT0=1; //P3.2僅接受下降沿中斷【這是計(jì)劃的一部分】
- PX0=1; //P3.2中斷優(yōu)先級(jí)高,又因?yàn)樽匀粌?yōu)先級(jí)的緣故,高于T0。
- PT0=1; //T0優(yōu)先級(jí)高
- //PT1=0; //T1優(yōu)先級(jí)低
- }
- void Timer2Init(void) //5毫秒@11.0592MHz
- {
- AUXR &= 0xFB; //定時(shí)器時(shí)鐘12T模式
- T2L = 0x00; //設(shè)置定時(shí)初值
- T2H = 0xEE; //設(shè)置定時(shí)初值
- AUXR |= 0x10; //定時(shí)器2開(kāi)始計(jì)時(shí)
- }
- void irdecode()
- {
- switch(ir3)
- {
- case 0x16:
- irresult=0;
- break;
- case 0x0c:
- irresult=1;
- break;
- case 0x18:
- irresult=2;
- break;
- case 0x5e:
- irresult=3;
- break;
- case 0x08:
- irresult=4;
- break;
- case 0x1c:
- irresult=5;
- break;
- case 0x5a:
- irresult=6;
- break;
- case 0x42:
- irresult=7;
- break;
- case 0x52:
- irresult=8;
- break;
- case 0x4a:
- irresult=9;
- break;
- case 0x45:
- irresult=10;//電源鍵
- break;
- case 0x47:
- irresult=11;//菜單鍵
- break;
- case 0x15:
- irresult=12;//播放鍵
- break;
-
- }
- }
- void irinit() //紅外接受狀態(tài)0的初始化函數(shù)【這是計(jì)劃的一部分】,狀態(tài)標(biāo)志初始化,定時(shí)器初始化,int0初始化,數(shù)據(jù)接收配置初始化
- {
- iract=0;
- irstate=0;//紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- started=0;
- t0reset=0;
- int0reset=0;
- int0negfall=0;
- EX0=1; //P3.2中斷使能
- IT0=1; //P3.2僅接受下降沿中斷【這是計(jì)劃的一部分】
- PX0=1;
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式(先清零)
- TMOD |= 0x01; //設(shè)置定時(shí)器模式(再寫(xiě)入)統(tǒng)一規(guī)定:T0,16位不自動(dòng)重裝載,12T。
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 0; //定時(shí)器0不計(jì)時(shí)
-
- EX0=1; //P3.2中斷使能
- IT0=1; //P3.2僅接受下降沿中斷
- PX0=1; //P3.2中斷優(yōu)先級(jí)高,又因?yàn)樽匀粌?yōu)先級(jí)的緣故,高于T0。
-
- bitamount=0;
-
- }
- void hc595write(void) //給595輸入數(shù)據(jù)c是數(shù)碼管,最后送進(jìn)去的那一位出現(xiàn)在q0
- {
- u8 t=0,a=0,shu=0x00;//t是循環(huán)變量,a是待發(fā)送的值,先發(fā)送級(jí)聯(lián)的那片,顯示8段,再發(fā)送直連的
- wei2=1;
- wei1=1;
- wei0=1;
- switch(w)
- {
- case 0:
- shu=duan[num0];
- break;
- case 1:
- shu=duan[num1];
- break;
- case 2:
- shu=duan[num2];
- break;
- }
- for(t=0;t<=7;t++)//數(shù)字區(qū),8位
- {
- if((shu&0x01)==0)
- ser=0;
- else
- ser=1;
- rclk=1;
- rclk=0;
- shu=shu>>1;
- }
- if(w>=2)//可以控制掃描順序
- w=0;
- else
- w++;
- srclk=1;
- srclk=0;
- switch(w)
- {
- case 0:
- wei0=0;
- break;
- case 1:
- wei1=0;
- break;
- case 2:
- wei2=0;
- break;
- }
- }
- void main() // 我是main函數(shù)
- {
- int a=3;
- led=1;
- srclk=0;
- rclk=0;
- ser=0;
- wk=iapread(0x00,0x01);
- days=iapread(0x00,0x00);
- intinit(); //【這是計(jì)劃的一部分】
- Timer2Init();
- WDT_COUNTER=0x37;//【這不是計(jì)劃的一部分】
- irinit();
- num2=24;
- num1=24;
- num0=24;//試機(jī)
- while(1)
- {
- //跑飛的時(shí)候while(1)里面的內(nèi)容仍然正常執(zhí)行
- }
- }
- void timer2() interrupt 12//正常顯示的掃描刷新步驟
- {
- if(irreceived==1)//有按鍵剛剛按下且未處理
- {
- irdecode();
- switch(irresult)
- {
- case 10://電源鍵
- {
- if(stat==0)
- {
- stat=1;
- num2=days/100;
- num1=(days%100)/10;
- num0=days%10;
- }
- else
- {
- stat=0;
- num2=32;
- num1=32;
- num0=32;
- hc595write();
- }
- break;
- }
- case 11://菜單鍵
- {
- if(stat<=2)
- {
- stat=3;//確認(rèn)進(jìn)入設(shè)置模式
- num2=34;//H
- num1=33;//_
- num0=34;//H
- }
- else
- {
- stat=1;
- }
- break;
- }
- case 12://播放鍵
- {
- if(stat==1)
- stat=2;
- if(stat==2)
- stat=1;
- break;
- }
- case 0:
- led=~led;
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- keynum=irresult;//先記錄下鍵值
- switch (stat)
- {
- case 3:
- timeset[2]=keynum*16;
- num1=keynum;
- num0=33;//_
- stat=4;
- break;
- case 4:
- timeset[2]=timeset[2]+keynum;
- num2=33;//_
- num1=13;//d
- num0=13;//d
- stat=5;
- break;
- case 5:
- days=keynum*100;
- num2=keynum;
- num1=33;//_
- num0=13;//d
- stat=6;
- break;
- case 6:
- days=days+keynum*10;
- num1=keynum;
- num0=33;//_
- stat=7;
- break;
- case 7:
- days=days+keynum;
- Ds1302set();//向ds1302寫(xiě)入小時(shí)
- iaperase(0x00,0x00);
- iapwrite(0x00,0x00,days);
- Ds1302ReadTime();
- wk=TIME[5];
- iapwrite(0x00,0x01,wk);//向eeprom寫(xiě)入正確的天數(shù)和星期
- num2=days/100;
- num1=(days%100)/10;
- num0=days%10;//更新顯示內(nèi)容
- stat=1;
- break;
- }
- break;
- }
- irreceived=0;
- }
- if(count>0)
- {
- count--;
- if(count==1000)
- WDT_COUNTER=WDT_COUNTER|0x10; //WDT喂狗【這是計(jì)劃的一部分】
- }
- else
- {
- count=2000;//count溢出之時(shí),應(yīng)向時(shí)鐘芯片詢(xún)問(wèn)日期,1000->5s
- WDT_COUNTER=WDT_COUNTER|0x10; //WDT喂狗【這是計(jì)劃的一部分】
- Ds1302ReadTime();
- if(wk!=TIME[5])//星期數(shù)發(fā)生變化
- {
- wk=TIME[5];//更新星期
- if(days>0)
- days--;//更新天數(shù)
- else
- stat=0;
- iaperase(0x00,0x00);
- iapwrite(0x00,0x00,days);
- iapwrite(0x00,0x01,wk);//向eeprom寫(xiě)入正確的天數(shù)和星期
- }
- }
- if((stat==1)&&(count==1500))//
- {
- temp=Ds18b20ReadTemp();
- num2=temp % 10000 / 1000;
- num1=(temp % 1000 / 100)+16;
- num0=temp % 100 / 10;
- }
- else if((stat==1|stat==2)&&count==1000)
- {
- num2=days/100;
- num1=(days%100)/10;
- num0=days%10;
- //num2=33;
- //num1=TIME[2]/16;
- //num0=TIME[2]%16;
- }
-
- if(stat==0)
- {
-
- }
- else
- {
- hc595write();
- }
- }
- void timer0() interrupt 1
- {
- if(t0reset==0)//定時(shí)器0溢出就回到等待狀態(tài)標(biāo)志位
- {
- if(irstate==1)
- {
- irstate=2; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- t0reset=1; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=0; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=1; //忽視int0的下降沿(只允許上升沿中斷)
- IT0=0; //P3.2=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式,2ms
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0xCD; //設(shè)置定時(shí)初值
- TH0 = 0xF8; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
- }
- else if(irstate==3)
- {
- irstate=4; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- t0reset=1; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=0; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=1; //忽視int0的下降沿(只允許上升沿中斷)
- IT0=0; //=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式 2.5ms
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0x00; //設(shè)置定時(shí)初值
- TH0 = 0xF7; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
- }
- else if(irstate==5)//重頭戲:判斷邏輯值【6-long】
- {
- irstate=6; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;
- irbit=1;
- //out=0;
-
- t0reset=0; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=0; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=1; //忽視int0的下降沿(只允許上升沿中斷)
- IT0=0; //=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式 1200us
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0xAE; //設(shè)置定時(shí)初值
- TH0 = 0xFB; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
-
- if(bitamount<=7) //【禁忌二重奏之一】
- {
- ir1=ir1>>1;
- ir1=ir1+(irbit*0x80);
- }
- else if(bitamount<=15)
- {
- ir2=ir2>>1;
- ir2=ir2+(irbit*0x80);
-
- }
- else if(bitamount<=23)
- {
- ir3=ir3>>1;
- ir3=ir3+(irbit*0x80);
- }
- else
- {
- ir4=ir4>>1;
- ir4=ir4+(irbit*0x80);
- }
-
- bitamount++;
-
- if(bitamount>=32)
- {
- irreceived=1;
- irinit();
-
- }
- }
- }
- else
- {
-
- irinit();
- }
- }
- void int0() interrupt 0
- {
- _nop_();
- _nop_();
- _nop_();
- if((ir==1)|(int0negfall==0))//如果“忽視下降沿”標(biāo)志位為1時(shí)(&)為下降沿(輸入端=0),就不能執(zhí)行下面的程序。
- {
- if(int0reset==1)//如果“觸發(fā)中斷即復(fù)位”標(biāo)志位為1,就立刻復(fù)位。
- {
-
- irinit();
-
- }
- else//好戲開(kāi)始
- {
- if(irstate==0)//報(bào)頭低開(kāi)始 0未激活;1報(bào)頭低;2報(bào)頭升;3報(bào)頭高;4報(bào)頭降;5高電平;6低電平
- {
- iract=1; //紅外活動(dòng)
- irstate=1; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- t0reset=0; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=1; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=0; //忽視int0的下降沿(只允許上升沿中斷)
- IT0=0; //=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //8毫秒@11.0592MHz 定時(shí)器時(shí)鐘12T模式
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0x33; //設(shè)置定時(shí)初值
- TH0 = 0xE3; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
-
- }
- else if(irstate==2)//報(bào)頭高開(kāi)始
- {
- irstate=3; //紅外接受狀態(tài)0-7{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平1;高電平2;低電平}
- t0reset=0; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=1; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=0; //忽視int0的下降沿(只允許上升沿中斷),下降沿此時(shí)不會(huì)觸發(fā)reset
- IT0=0; //=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式 3.5ms
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0x66; //設(shè)置定時(shí)初值
- TH0 = 0xF3; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
-
- }
- else if(irstate==4)//高電平開(kāi)始【5-first】
- {
- irstate=5; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- t0reset=0; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=0; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=0; //忽視int0的下降沿(只允許上升沿中斷)
- IT0=1; //P3.2=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式 840us
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0xFA; //設(shè)置定時(shí)初值
- TH0 = 0xFC; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
-
- //out=1;
-
- if(started==0)//收到的是報(bào)頭
- {
- started=1;
- }
- else//收到的是報(bào)尾
- {
- iract=0;
- started=0;
- irinit();
- }
- }
- else if(irstate==5)//低電平開(kāi)始【6-short】
- {
- irstate=6; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- irbit=0;
- //out=0;
-
- t0reset=1; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=0; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=1; //忽視int0的下降沿(只允許上升沿中斷)
- IT0=0; //P3.2=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式 840us
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0xFA; //設(shè)置定時(shí)初值
- TH0 = 0xFC; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
-
- if(bitamount<=7) //【禁忌二重奏之二】
- {
- ir1=ir1>>1;
- ir1=ir1+(irbit*0x80);
- }
- else if(bitamount<=15)
- {
- ir2=ir2>>1;
- ir2=ir2+(irbit*0x80);
-
- }
- else if(bitamount<=23)
- {
- ir3=ir3>>1;
- ir3=ir3+(irbit*0x80);
- }
- else
- {
- ir4=ir4>>1;
- ir4=ir4+(irbit*0x80);
- }
-
- bitamount++;
-
- if(bitamount>=32)
- {
- irreceived=1;
- irinit();
-
- }
- }
- else if(irstate==6)//收到上升沿信號(hào),由低電平轉(zhuǎn)為高電平狀態(tài)【5-repeat】
- {
- irstate=5; //紅外接受狀態(tài)0-6{未激活;報(bào)頭低;報(bào)頭升;報(bào)頭高;報(bào)頭降;高電平;低電平}
- t0reset=0; //定時(shí)器0溢出就回到等待狀態(tài)
- int0reset=0; //int0觸發(fā)就回到等待狀態(tài)
- int0negfall=0; //忽視int0的下降沿(只允許上升沿中斷)
- IT0=1; //P3.2=1僅接收下降沿中斷,=0上下皆可
-
- AUXR &= 0x7F; //定時(shí)器時(shí)鐘12T模式 840us
- TMOD &= 0xF0; //設(shè)置定時(shí)器模式
- TMOD |= 0x01; //設(shè)置定時(shí)器模式
- TL0 = 0xFA; //設(shè)置定時(shí)初值
- TH0 = 0xFC; //設(shè)置定時(shí)初值
- TF0 = 0; //清除TF0標(biāo)志
- TR0 = 1; //定時(shí)器0開(kāi)始計(jì)時(shí)
-
- //out=1;
-
- }
-
- }
- }
-
- }
- /*
- 日志:在完成了數(shù)碼管顯示和定時(shí)
- 器中斷的基礎(chǔ)上,新增了狀態(tài)機(jī)查
- 詢(xún)紅外信號(hào)輸入的功能,在15w204
- s上能穩(wěn)定運(yùn)行。2020-2-21
- */
- void Ds18b20Init()
- {
- unsigned char i,j;
- DSPORT=1; //將總線拉高4us
- _nop_();
- _nop_();
- i = 8;
- while (--i);
- DSPORT=0; //然后拉低總線480us
- i = 6;
- j = 38;
- do
- {
- while (--j);
- } while (--i);
- DSPORT=1; //然后拉高總線,如果DS18B20做出反應(yīng)會(huì)將在15us~60us后總線拉低
- i = 6;
- j = 38;
- do
- {
- while (--j);
- } while (--i);
- }
- void Ds18b20WriteByte(unsigned char dat)
- {
- unsigned char i,j,e;
- for(e=8;e>0;e--)
- {
- DSPORT=0; //每寫(xiě)入一位數(shù)據(jù)之前先把總線拉低1us
- _nop_();
- _nop_();
- _nop_();
- DSPORT=dat&0x01; //然后寫(xiě)入一個(gè)數(shù)據(jù),從最低位開(kāi)始
- i = 1;//延時(shí)68us,持續(xù)時(shí)間最少60us
- j = 184;
- do
- {
- while (--j);
- } while (--i);
- DSPORT=1; //然后釋放總線,至少1us給總線恢復(fù)時(shí)間才能接著寫(xiě)入第二個(gè)數(shù)值
- dat>>=1;
- }
- }
- unsigned char Ds18b20ReadByte()
- {
- unsigned char byte,i,j;
- for(j=8;j>0;j--)
- {
- DSPORT=0;//先將總線拉低1us
- _nop_();
- _nop_();
- _nop_();
- byte>>=1;
- DSPORT=1;//然后釋放總線
- _nop_();//延時(shí)15us等待數(shù)據(jù)穩(wěn)定[]
- i = 39;
- while (--i);
- if(DSPORT)
- byte|=0x80;
- i = 122;//delay45us
- while (--i);
- }
- return byte;
- }
- int Ds18b20ReadTemp()
- {
- int temp=0;
- int tp;
- u8 i,j;
- unsigned char tmh,tml;
- Ds18b20Init();
- Ds18b20WriteByte(0xcc);
- Ds18b20WriteByte(0x44);
- _nop_();//delay125us
- _nop_();
- i = 2;
- j = 84;
- do
- {
- while (--j);
- } while (--i);
- Ds18b20Init();
- Ds18b20WriteByte(0xcc);
- Ds18b20WriteByte(0xbe);
- tml=Ds18b20ReadByte();
- tmh=Ds18b20ReadByte();
-
- temp=tmh;
- temp<<=8;
- temp|=tml;
- if((temp&0xf800)==0xf800) //*0.0625是把16進(jìn)制轉(zhuǎn)化位10進(jìn)制所需,原始信息里的16代表1攝氏度。
- {
- temp=temp-1;//如果溫度是零下,此處未加入負(fù)溫度標(biāo)志位,所以顯示的還是正的
- temp=~temp;
- tp=temp;
- temp=tp*0.0625*100+0.5;
- }
- else
- {
- tp=temp;//如果溫度是零上
- temp=tp*0.0625*100+0.5;
- }
- return temp;
- }
- /*
- 日志 移植了某大佬的ds18b20程序,
- 并使之能在stc-y5內(nèi)核單片機(jī)上運(yùn)
- 行。正常情況下輸出的16bit信息可
- 以表示12位精度的溫度,但是stc單
- 片機(jī)不支持浮點(diǎn)數(shù)運(yùn)算,所以temp
- 是乘了100的。所有延時(shí)函數(shù)(微秒
- 級(jí))均已內(nèi)置,無(wú)需調(diào)用,也不費(fèi)
- 什么時(shí)間。 2020-2-24
- */
- //eeprom操作--IAP法
- void iaprst() //復(fù)位
- {
- IAP_CONTR=0;
- IAP_CMD=0;
- IAP_TRIG=0;
- IAP_ADDRH=0x80;
- }
- unsigned char iapread(unsigned char addrh,unsigned char addrl)
- {
- unsigned char dat;
- IAP_CONTR=0x83; //適用于12mhz以下的頻率
- IAP_CMD=1;
- IAP_ADDRL=addrl;
- IAP_ADDRH=addrh;
- IAP_TRIG=0x5a;
- IAP_TRIG=0xa5;
- _nop_();
- _nop_();
- dat=IAP_DATA;
- iaprst();
- return dat;
- }
- void iapwrite(unsigned char addrh,unsigned char addrl,unsigned char dat)
- {
- IAP_CONTR=0x83;//適用于12mhz以下的頻率
- IAP_CMD=2;
- IAP_ADDRL=addrl;
- IAP_ADDRH=addrh;
- IAP_DATA=dat;
- IAP_TRIG=0x5a;
- IAP_TRIG=0xa5;
- _nop_();
- _nop_();
- iaprst();
- }
- void iaperase(unsigned char addrh,unsigned char addrl)
- {
- IAP_CONTR=0x83;//適用于12mhz以下的頻率
- IAP_CMD=3;
- IAP_ADDRL=addrl;
- IAP_ADDRH=addrh;
- IAP_TRIG=0x5a;
- IAP_TRIG=0xa5;
- _nop_();
- _nop_();
- iaprst();
- }
- /*
- 日志 增加了關(guān)于eeprom的操作的函數(shù)
- ,現(xiàn)學(xué)現(xiàn)賣(mài),一共就三個(gè)函數(shù)(iapinit
- 不需要管),204s就只有兩個(gè)扇區(qū),
- 0000-01ff,0200-03ff,每個(gè)地址號(hào)
- 都能存儲(chǔ)一個(gè)char,一共是1024個(gè)。
- 使用方法:(先讀出原有數(shù)據(jù),)再
- 擦除扇區(qū)(擦除地址是扇區(qū)的首地址
- ),然后寫(xiě)入新值,(最后讀出來(lái))。
- 打算用0000存儲(chǔ)倒計(jì)時(shí)還剩多少天,
- 0001存儲(chǔ)當(dāng)前的日期。程序上電先把
- 日期和倒數(shù)讀到ram里,每隔幾秒詢(xún)
- 問(wèn)1302,若有不同,則ram日期更新
- ,倒數(shù)減一(檢測(cè)大于0),重寫(xiě)
- eeprom。 2020-2-25
- */
- /*******************************************************************************
- * 函 數(shù) 名 : Ds1302Write
- * 函數(shù)功能 : 向DS1302命令(地址+數(shù)據(jù))
- * 輸 入 : addr,dat
- * 輸 出 : 無(wú)
- *******************************************************************************/
- void Ds1302Write(u8 addr, u8 dat)
- {
- u8 n;
- RST = 0;
- _nop_();
- SCLK = 0;//先將SCLK置低電平。
- _nop_();
- RST = 1; //然后將RST(CE)置高電平。
- _nop_();
- for (n=0; n<8; n++)//開(kāi)始傳送八位地址命令
- {
- DSIO = addr & 0x01;//數(shù)據(jù)從低位開(kāi)始傳送
- addr >>= 1;
- SCLK = 1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
- _nop_(); //時(shí)鐘高電平時(shí)數(shù)據(jù)需要保持不動(dòng)
- SCLK = 0;
- _nop_();
- }
- for (n=0; n<8; n++)//寫(xiě)入8位數(shù)據(jù)
- {
- DSIO = dat & 0x01;
- dat >>= 1;
- SCLK = 1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
- _nop_();
- SCLK = 0;
- _nop_();
- }
-
- RST = 0;//傳送數(shù)據(jù)結(jié)束
- _nop_();
- }
- /*******************************************************************************
- * 函 數(shù) 名 : Ds1302Read
- * 函數(shù)功能 : 讀取一個(gè)地址的數(shù)據(jù)
- * 輸 入 : addr
- * 輸 出 : dat
- *******************************************************************************/
- u8 Ds1302Read(u8 addr)
- {
- u8 n,dat,dat1;
- RST = 0;
- _nop_();
- SCLK = 0;//先將SCLK置低電平。
- _nop_();
- RST = 1;//然后將RST(CE)置高電平。
- _nop_();
- for(n=0; n<8; n++)//開(kāi)始傳送八位地址命令
- {
- DSIO = addr & 0x01;//數(shù)據(jù)從低位開(kāi)始傳送
- addr >>= 1;
- SCLK = 1;//數(shù)據(jù)在上升沿時(shí),DS1302讀取數(shù)據(jù)
- _nop_();
- SCLK = 0;//DS1302下降沿時(shí),放置數(shù)據(jù)
- _nop_();
- }
- _nop_();
- for(n=0; n<8; n++)//讀取8位數(shù)據(jù)
- {
- dat1 = DSIO;//從最低位開(kāi)始接收
- dat = (dat>>1) | (dat1<<7);
- SCLK = 1;
- _nop_();
- SCLK = 0;//DS1302下降沿時(shí),放置數(shù)據(jù)
- _nop_();
- }
- RST = 0;
- _nop_(); //以下為DS1302復(fù)位的穩(wěn)定時(shí)間,必須的。
- SCLK = 1;
- _nop_();
- DSIO = 0;
- _nop_();
- DSIO = 1;
- _nop_();
- return dat;
- }
- /*******************************************************************************
- * 函 數(shù) 名 : Ds1302Init
- * 函數(shù)功能 : 初始化DS1302.
- * 輸 入 : 無(wú)
- * 輸 出 : 無(wú)
- *******************************************************************************/
- void Ds1302set()
- {
- u8 n;
- Ds1302Write(0x8E,0X00); //關(guān)閉寫(xiě)保護(hù)功能
- for (n=0; n<7; n++)//寫(xiě)入7個(gè)字節(jié)的時(shí)鐘信號(hào):分秒時(shí)日月周年 !!!此操作會(huì)破壞原有的時(shí)間數(shù)據(jù)!!
- {
- Ds1302Write(WRITE_RTC_ADDR[n],timeset[n]);
- }
- Ds1302Write(0x8E,0x80); //打開(kāi)寫(xiě)保護(hù)功能
- }
- /*******************************************************************************
- * 函 數(shù) 名 : Ds1302ReadTime
- * 函數(shù)功能 : 讀取時(shí)鐘信息
- * 輸 入 : 無(wú)
- * 輸 出 : 無(wú)
- *******************************************************************************/
- void Ds1302ReadTime()
- {
- u8 n;
- for (n=0; n<7; n++)//讀取7個(gè)字節(jié)的時(shí)鐘信號(hào):分秒時(shí)日月周年
- {
- TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
- }
-
- }
- /*
- 添加了ds1302函數(shù),通過(guò)全局變量傳遞
- 數(shù)據(jù)。通過(guò)每5秒鐘檢測(cè)一下星期并與
- ram里面的值比較,若有變化就日期減
- 一,并更新eeprom里面的值。注意ds1302
- 的數(shù)據(jù)格式,比如’13點(diǎn)’不是0x0c,
- 而是0x13,此之謂8421bcd碼.
- */
復(fù)制代碼 stc15.h可以用stc下載工具添加了mcu型號(hào)到keil中后再keil的文件夾里面找到,所有的函數(shù)都在里面了,(幫助沒(méi)黑幣的小白真正實(shí)現(xiàn)白嫖),標(biāo)有這是計(jì)劃的一部分的是與ir接收相關(guān)的函數(shù)(包括看門(mén)狗設(shè)置)。說(shuō)實(shí)在的,這是我首次給51單片機(jī)寫(xiě)這么長(zhǎng)的代碼。里面有的函數(shù)是我之前學(xué)的時(shí)候借鑒壇里大神的,在此表示感謝。

硬件制作
搭棚過(guò)程是先從數(shù)碼管做起的(隔壁五家的垃圾數(shù)碼管雖然便宜,可挑了半天才找到個(gè)好的)
搭棚的過(guò)程沒(méi)怎么拍全,因?yàn)楫?dāng)時(shí)自己也沒(méi)有做下去的信心
|
評(píng)分
-
查看全部評(píng)分
|