|
單片機(jī)源程序如下:
- //宏定義
- #define uchar unsigned char
- #define uint unsigned int
- //包含頭文件
- #include <reg52.h>
- #include <18b20.h>
- #include <stdlib.h>
- #include <intrins.h>
- #include <eeprom52.h>
- #define Imax 14000 //此處為晶振為11.0592時(shí)的取值,
- #define Imin 8000 //如用其它頻率的晶振時(shí),
- #define Inum1 1450 //要改變相應(yīng)的取值。
- #define Inum2 700
- #define Inum3 3000
- sbit K1=P1^1;
- sbit K2=P1^2;
- sbit K3=P1^3; //按鍵定義
- sbit PWM=P3^6; //PWM輸出
- sbit BUZZ=P1^4; //蜂鳴器控制腳
- sbit RSD=P2^0; //熱釋電引腳
- unsigned char Im[4]={0x00,0x00,0x00,0x00};
- uchar displaydata[4]; //顯示暫存數(shù)組
- //全局變量
- char f,dang,count,count1,a_a; //檔位
- unsigned long m,Tc;
- unsigned char IrOK; //定義紅外工作變量
- void jisuan(); //聲明計(jì)算函數(shù)
- uchar mode;
- char sec_b=0;
- bit flag_b=0;
- uint TH,TL; //上下限變量
- uchar baif,suiji;
- unsigned char code duan[17]={
- 0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x47,0xDF,0xD7, 0xCF,0xDA,0x98,0xDC,0x9B,0x8B}; //接線(xiàn)從高到低:g c dp d e b f a
- //0、1、2、3、4、5、6、7、8、9、A、b、c、d、E、F的顯示碼 //
- unsigned char code wei[8]={ //數(shù)碼管的位選
- 0xef,0xdf,0xbf,0x7f,0xfe,0xfd,0xfb,0xf7};
- uchar code zhuanhuan[4]={10,5,3,0};//轉(zhuǎn)換數(shù)組
- void write_eeprom() //內(nèi)部eeprom寫(xiě)函數(shù)
- {
- SectorErase(0x2000); //清空
- SectorErase(0x2c00);
- SectorErase(0x2e00);
- byte_write(0x2c00,TH/256);
- byte_write(0x2c01,TH%256);
- byte_write(0x2c02,TL/256);
- byte_write(0x2c03,TL%256); //將上下限數(shù)據(jù)保存到eeprom
- byte_write(0x2c04,dang);
- byte_write(0x2c05,mode);
- byte_write(0x2060,0x01);
-
- }
- /******************把數(shù)據(jù)從單片機(jī)內(nèi)部eeprom中讀出來(lái)*****************/
- void read_eeprom()
- {
- mode = byte_read(0x2c05);
- dang = byte_read(0x2c04);
- TH = byte_read(0x2c00)*256+byte_read(0x2c01);
- TL = byte_read(0x2c02)*256+byte_read(0x2c03);
- a_a = byte_read(0x2060);
-
- }
- /**************開(kāi)機(jī)自檢eeprom初始化*****************/
- void init_eeprom()
- {
- a_a = byte_read(0x2060);
- if(a_a != 1) //新的單片機(jī)初始單片機(jī)內(nèi)問(wèn)eeprom
- {
-
- a_a = 1;
- write_eeprom(); //保存數(shù)據(jù)
- }
- }
- void delay(uint z) //延時(shí)函數(shù)
- {
- uint z1,z2;
- for(z1=0;z1<z;z1++)
- for(z2=0;z2<110;z2++);
- }
- void display() //顯示函數(shù)
- {
- uchar i;
- if(mode==0) //無(wú)極變速
- {
- displaydata[0]=0x00;
- displaydata[1]=duan[disdata[1]];
- displaydata[2]=duan[disdata[2]]|0x20;
- displaydata[3]=duan[disdata[3]];
- }
- else if(mode==1) //上限
- {
- displaydata[0]=0xce; //H 11001110
- displaydata[1]=duan[TH%1000/100];
- displaydata[2]=duan[TH%100/10]|0x20;
- displaydata[3]=duan[TH%10];
- }
- else if(mode==2) //下限
- {
- displaydata[0]=0x1a; //L 00111000
- displaydata[1]=duan[TL%1000/100];
- displaydata[2]=duan[TL%100/10]|0x20;
- displaydata[3]=duan[TL%10];
- }
- else if(mode==3) //檔位0到3檔
- {
- displaydata[0]=duan[dang];
- displaydata[1]=0x80; //01000000
- displaydata[2]=duan[disdata[1]];
- displaydata[3]=duan[disdata[2]];
- }
- else if(mode==4)
- {
- displaydata[0]=0xda; //b自然風(fēng)
- displaydata[1]=duan[disdata[1]];
- displaydata[2]=duan[disdata[2]]|0x20;
- displaydata[3]=duan[disdata[3]];
- }
-
- for(i=0;i<4;i++) //循環(huán)4次顯示4位數(shù)碼管
- {
- P2=wei[i]; //選中位
- P0=displaydata[i]; //送入顯示碼
- delay(3); //延時(shí)
- P2=0xff; //關(guān)閉位
- P0=0x00; //復(fù)位顯示碼
- }
- }
- void key() //按鍵函數(shù)
- {
- if(K1==0||(Im[2]==0x47&&IrOK==1)) //按鍵1按下或者遙控器上的按鍵按下
- {
- delay(5); //延時(shí)去抖
- if(K1==0||(Im[2]==0x47&&IrOK==1)) //再次判斷按鍵按下
- {
- BUZZ=0;
- delay(20);
- BUZZ=1; //按鍵音
- mode++; //模式加
- if(mode>4) //模式加到大于4
- mode=0; //模式清零
- // Im[2]=0;
- IrOK=0; //變量清零
- write_eeprom(); //寫(xiě)入eeprom數(shù)據(jù)
- while(!K1); //按鍵釋放
- }
- }
- if(K2==0||(Im[2]==0x40&&IrOK==1))
- {
- delay(5);
- if(K2==0||(Im[2]==0x40&&IrOK==1))
- {
- BUZZ=0;
- delay(20);
- BUZZ=1;
- if(mode==1) //模式等于1時(shí)
- {
- TH++; //上限加
- if(TH>999) //上限加到大于99.9度
-
- TH=TL+1; //上限等于下限加一
- }
- else if(mode==2) //模式等于2時(shí)
- {
- TL++; //下限加
- if(TL>=TH) //下限加到大于等于上限
- TL=TH-1; //下限等于上限減一
- }
- else if(mode==3) //模式等于3時(shí)
- {
- dang++; //檔位加一
- if(dang>3) //檔位大于3時(shí)
- dang=0; //檔位清零
- }
- Im[2]=0;
- IrOK=0; //紅外變量清零
- write_eeprom(); //寫(xiě)入eeprom數(shù)據(jù)
- while(!K2); //按鍵釋放
- }
- }
- if(K3==0||(Im[2]==0x19&&IrOK==1))
- {
- delay(5);
- if(K3==0||(Im[2]==0x19&&IrOK==1))
- {
- BUZZ=0;
- delay(20);
- BUZZ=1;
- if(mode==1)
- {
- TH--;
- if(TH<=TL)
- TH=TL+1;
- }
- else if(mode==2)
- {
- TL--;
- if(TL>=TH)
- TL=TH-1;
- }
- else if(mode==3)
- {
- dang--;
- if(dang<0)
- dang=3;
- }
- Im[2]=0;
- IrOK=0;
- write_eeprom();
- while(!K3);
- }
- }
- }
- void jisuan() //計(jì)算函數(shù)
- {
- if((mode==0||mode==1||mode==2)&&RSD==1) //模式0、1、2并且熱釋電有信號(hào)時(shí)
- {
- if(tvalue<=TL) //溫度小于下限時(shí)
- PWM=1; //關(guān)閉輸出,占空比0%
- else if(tvalue>=TH) //溫度大于等于上限
- PWM=0; //打開(kāi)輸出,占空比100%
- else //其他狀態(tài)時(shí)
- {
- baif=(((tvalue-TL)*50)/(TH-TL)); //占空比控制變量計(jì)算得到
- //計(jì)算方法:當(dāng)前溫度減去下限值乘以5再除以上限減下限
- if(count1>baif) //根據(jù)變量判斷占空比大小
- PWM=1; //關(guān)閉風(fēng)扇
- else
- PWM=0; //打開(kāi)風(fēng)扇
- }
- }
- else if(mode==3) //模式3時(shí)
- {
- if(count1>(zhuanhuan[dang]*5)) //根據(jù)檔位計(jì)算出占空比
- PWM=0;
- else
- PWM=1;
- }
- else if((mode==4&&flag_b==0)&&RSD==1) //模式4時(shí),熱釋電有信號(hào)
- {
- suiji=rand(); //讀隨機(jī)函數(shù)
- suiji=suiji%23; //隨機(jī)數(shù)計(jì)算
- if(10>suiji) //判斷隨機(jī)數(shù)是否小于10
- PWM=0; //輸出開(kāi)
- else //隨機(jī)數(shù)大于等于10
- PWM=1; //輸出關(guān)
- flag_b=1; //變量置1
- }
- if(RSD==0&&mode!=3) //熱釋電沒(méi)有信號(hào)時(shí)
- PWM=1; //關(guān)閉輸出
- }
- void main() //主函數(shù)
- {
- uint count; //定義變量
- EA=1; //打開(kāi)中斷總開(kāi)關(guān)
- EX1=1; //打開(kāi)外部中斷1
- IT1=1; //下降沿有效
- TMOD=0x11; //定時(shí)器工作方式
- TR0=0; //關(guān)閉T0
- TH0=0;
- TL0=0; //初值0
- ET1=1; //T1允許中斷
- TR1=1; //T1打開(kāi)中斷
- TH1=0xfc;
- TL1=0x18; //T1初值1ms
- mode=0; //初始模式0
- TH=300;
- TL=200; //上下限初始值
- init_eeprom(); //初始化eeprom
- read_eeprom(); //讀取eeprom數(shù)據(jù)
- while(1) //進(jìn)入循環(huán)
- {
- jisuan(); //計(jì)算函數(shù)
- count++; //變量加
- if(count>200) //加到大于200
- {
- count=0; //清零
- TR1=0; //關(guān)閉定時(shí)器T1
- read_wendu(); //讀取溫度
- TR1=1; //打開(kāi)定時(shí)器T1
- }
- jisuan(); //計(jì)算函數(shù)
- display(); //顯示函數(shù)
- key(); //按鍵函數(shù)
- jisuan(); //計(jì)算函數(shù)
- }
- }
- void timer1() interrupt 3 //定時(shí)器T1工作函數(shù)
- {
- TH1=0xfc;
- TL1=0x18; //重新賦初值
- count1++; //加
- if(count1>50)
- {
- count1=0;
- if(mode==4&&flag_b==1) //模式等于4時(shí),變量為1
- {
- sec_b++; //變量加
- if(sec_b>=8) //加到8時(shí)
- {
- sec_b=0; //清零
- flag_b=0; //清零
- }
- }
- }
- }
- void intersvr1(void) interrupt 2 //紅外工作函數(shù)
- {
- TR0=1;
- Tc=TH0*256+TL0;//提取中斷時(shí)間間隔時(shí)長(zhǎng)
- TH0=0;
- TL0=0; //定時(shí)中斷重新置零
- if((Tc>Imin)&&(Tc<Imax))
- {
- m=0;
- f=1;
- return;
- } //找到啟始碼
- if(f==1)
- {
- if(Tc>Inum1&&Tc<Inum3)
- {
- Im[m/8]=Im[m/8]>>1|0x80; m++;
- }
- if(Tc>Inum2&&Tc<Inum1)
- {
- Im[m/8]=Im[m/8]>>1; m++; //取碼
- }
- if(m==32)
- {
- m=0;
- f=0;
-
- if(Im[2]==~Im[3])
- {
- IrOK=1;
- TR0=0;
- }
- else
- {
- IrOK=0; //取碼完成后判斷讀碼是否正確
- }
- }
- //準(zhǔn)備讀下一碼
- }
- }
-
- Ds18b20
- sbit DQ=P1^0;//ds18b20與單片機(jī)連接口
- uchar data disdata[5];
- uint tvalue;//溫度值
- uchar tflag;//溫度正負(fù)標(biāo)志
- /******************************ds1820程序***************************************/
- void delay_18B20(uchar k)//延時(shí)1微秒
- {
- while(k--);
- }
- void ds1820rst()/*ds1820復(fù)位*/
- {
-
- DQ = 1; //DQ復(fù)位
- delay_18B20(4); //延時(shí)
- DQ = 0; //DQ拉低
- delay_18B20(100); //精確延時(shí)大于480us
- DQ = 1; //拉高
- delay_18B20(40);
- }
-
- uchar ds1820rd()/*讀數(shù)據(jù)*/
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- { DQ = 0; //給脈沖信號(hào)
- dat>>=1;
- DQ = 1; //給脈沖信號(hào)
- if(DQ)
- dat|=0x80;
- delay_18B20(10);//延時(shí)106us
- }
- return(dat);
- }
- void ds1820wr(uchar wdata)/*寫(xiě)數(shù)據(jù)*/
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = wdata&0x01;
- delay_18B20(10);//延時(shí)106us
- DQ = 1;
- wdata>>=1;
- }
- }
-
-
- uint read_wendu()/*讀取溫度值并轉(zhuǎn)換*/
- {
- uchar a,b;
- ds1820rst();
- ds1820wr(0xcc);//*跳過(guò)讀序列號(hào)*/
- ds1820wr(0x44);//*啟動(dòng)溫度轉(zhuǎn)換*/
- ds1820rst();
- ds1820wr(0xcc);//*跳過(guò)讀序列號(hào)*/
- ds1820wr(0xbe);//*讀取溫度*/
- a=ds1820rd();
- b=ds1820rd();
- tvalue=b;
- tvalue<<=8;
- tvalue=tvalue|a;
- if(tvalue<0x0fff)
- tflag=0;
- else
- {
- tvalue=~tvalue+1;
- tflag=1;
- }
- tvalue=tvalue*(0.625);//溫度值擴(kuò)大10倍,精確到1位小數(shù)
- disdata[1]=tvalue%1000/100;//十位數(shù)
- disdata[2]=tvalue%100/10;//個(gè)位數(shù)
- disdata[3]=tvalue%10;//小數(shù)位
- return(tvalue);
- }
- eeprom
- #ifndef _EEPROM52_H_
- #define _EEPROM52_H_
- /********STC89C51扇區(qū)分布*******
- 第一扇區(qū):1000H--11FF
- 第二扇區(qū):1200H--13FF
- 第三扇區(qū):1400H--15FF
- 第四扇區(qū):1600H--17FF
- 第五扇區(qū):1800H--19FF
- 第六扇區(qū):1A00H--1BFF
- 第七扇區(qū):1C00H--1DFF
- 第八扇區(qū):1E00H--1FFF
- *****************/
- /********STC89C52扇區(qū)分布*******
- 第一扇區(qū):2000H--21FF
- 第二扇區(qū):2200H--23FF
- 第三扇區(qū):2400H--25FF
- 第四扇區(qū):2600H--27FF
- 第五扇區(qū):2800H--29FF
- 第六扇區(qū):2A00H--2BFF
- 第七扇區(qū):2C00H--2DFF
- 第八扇區(qū):2E00H--2FFF
- *****************/
- #define RdCommand 0x01 //定義ISP的操作命令
- #define PrgCommand 0x02
- #define EraseCommand 0x03
- #define Error 1
- #define Ok 0
- #define WaitTime 0x01 //定義CPU的等待時(shí)間
- sfr ISP_DATA=0xe2; //寄存器申明
- sfr ISP_ADDRH=0xe3;
- sfr ISP_ADDRL=0xe4;
- sfr ISP_CMD=0xe5;
- sfr ISP_TRIG=0xe6;
- sfr ISP_CONTR=0xe7;
- /* ================ 打開(kāi) ISP,IAP 功能 ================= */
- void ISP_IAP_enable(void)
- {
- EA = 0; /* 關(guān)中斷 */
- ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
- ISP_CONTR = ISP_CONTR | WaitTime; /* 寫(xiě)入硬件延時(shí) */
- ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
- }
- /* =============== 關(guān)閉 ISP,IAP 功能 ================== */
- void ISP_IAP_disable(void)
- {
- ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
- ISP_TRIG = 0x00;
- EA = 1; /* 開(kāi)中斷 */
- }
- /* ================ 公用的觸發(fā)代碼 ==================== */
- void ISPgoon(void)
- {
- ISP_IAP_enable(); /* 打開(kāi) ISP,IAP 功能 */
- ISP_TRIG = 0x46; /* 觸發(fā)ISP_IAP命令字節(jié)1 */
- ISP_TRIG = 0xb9; /* 觸發(fā)ISP_IAP命令字節(jié)2 */
- _nop_();
- }
- /* ==================== 字節(jié)讀 ======================== */
- unsigned char byte_read(unsigned int byte_addr)
- {
- EA = 0;
- ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址賦值 */
- ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
- ISP_CMD = ISP_CMD | RdCommand; /* 寫(xiě)入讀命令 */
- ISPgoon(); /* 觸發(fā)執(zhí)行 */
- ISP_IAP_disable(); /* 關(guān)閉ISP,IAP功能 */
- EA = 1;
- return (ISP_DATA); /* 返回讀到的數(shù)據(jù) */
- }
- /* ================== 扇區(qū)擦除 ======================== */
- void SectorErase(unsigned int sector_addr)
- {
- unsigned int iSectorAddr;
- iSectorAddr = (sector_addr & 0xfe00); /* 取扇區(qū)地址 */
- ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
- ISP_ADDRL = 0x00;
- ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */
- ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
- ISPgoon(); /* 觸發(fā)執(zhí)行 */
- ISP_IAP_disable(); /* 關(guān)閉ISP,IAP功能 */
- }
- /* ==================== 字節(jié)寫(xiě) ======================== */
- void byte_write(unsigned int byte_addr, unsigned char original_data)
- {
- EA = 0;
- // SectorErase(byte_addr);
- ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */
- ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */
- ISP_CMD = ISP_CMD | PrgCommand; /* 寫(xiě)命令2 */
- ISP_DATA = original_data; /* 寫(xiě)入數(shù)據(jù)準(zhǔn)備 */
- ISPgoon(); /* 觸發(fā)執(zhí)行 */
- ISP_IAP_disable(); /* 關(guān)閉IAP功能 */
- EA =1;
- }
- #endif
復(fù)制代碼
|
-
-
chengxu.doc
2018-5-14 15:38 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
68 KB, 下載次數(shù): 15, 下載積分: 黑幣 -5
|