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