基于51單片機的溫度控制器設計
功能較為完善
單片機源程序如下:
- #include "reg52.h"
- #include "ct107.h"
- #include "iic.h"
- #include "EEPROM.H"
- #include "18b20.h"
- #include "i2c.h"
- bit flag_get,keyflag; //定義采集溫度標志位和按鍵標志位
- sbit PWM=P3^4; //定義脈沖端口
- sbit LED1=P0^0;
- sbit LED2=P0^1;
- sbit LED3=P0^2;
- sbit LED4=P0^3;
- sbit LED5=P0^4;
- sbit LED6=P0^5;
- sbit LED7=P0^6;
- sbit LED8=P0^7;
- unsigned char code smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //數碼管段選“0~9”
- unsigned char code smg_we[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //數碼管位選
- unsigned char UpT,DoT,NowT; //上限溫度,下限溫度,目前溫度
- unsigned int temp; //定義中間變量
- unsigned char dat[8]; //定義顯示數組
- unsigned int Ad_data;
- void key(); //按鍵函數
- void diswork(); //顯示處理函數
- void Write_byte(unsigned char add,unsigned char dat); //向EEPROM寫一個字節
- unsigned char read_byte(unsigned char add); //從EEPROM讀一個字節
- unsigned int ReadTemperature(void); //讀當前溫度
- void deplay_50us(unsigned char t); //50us延時函數
- void work(); //判斷采用何種措施函數
- void Ad_read(void); //電壓讀取
- main() //主函數
- {
- ct107_init(); //初始化板(關蜂鳴器,繼電器,LED等)
- TMOD=0X12; //定義定時器1為16位,定時器0為8位重載定時器
- TH1=(65536-2000)/256; //定時2ms
- TL1=(65536-2000)%256;
- TH0=256-100; //定時0.1ms
- TL0=256-100;
- TR1=1; //開定時器T1
- ET1=1; //開定時器T1中斷
- TR0=1; //開定時器T0
- EA=1; //開總中斷
- while(1)
- {
-
- key();
-
-
- if(flag_get==1) //定時讀取當前溫度
- {
- Ad_read();
-
-
- temp=ReadTemperature();
- NowT=temp>>4; //讀溫度整數部分
- flag_get=0;
- }
- UpT=read_byte(0x00); //從EEPROM讀出上限溫度
- DoT=read_byte(0x01); //從EEPROM讀出下限溫度
-
-
-
- work();
- diswork();
- }
-
- }
- /*--------------------------------------------------------------------------
- 判斷采用何種措施函數
- -------------------------------------------------------------------------*/
- void work()
- {
- if(NowT>UpT) //當目前溫度高于上限溫度是開T0中斷,產生1KHz占空比為30%的方波
- {
- ET0=1;
-
-
- LED1=0;
- LED2=1;
- LED3=1;
- LED4=1;
- LED5=1;
- LED6=1;
- LED7=1;
- LED8=1;
- P2|=Y4C;
- P2&=0x1f;
-
- }
- else
- if(NowT>DoT) //溫度在上下限之間時,關中斷,P3^4口保持高電平
- {
- ET0=0;
- PWM=1;
-
-
- LED1=1;
- LED2=0;
- LED3=1;
- LED4=1;
- LED5=1;
- LED6=1;
- LED7=1;
- LED8=1;
- P2|=Y4C;
- P2&=0x1f;
- }
- if(NowT<DoT) //溫度低于下限溫度時開繼電器,關蜂鳴器避免干擾
- {
- P2&=0x1f;
- BUZZ=0;
- RELAY=1;
- P2|=Y5C;
- P2&=0x1f;
-
- LED1=1;
- LED2=1;
- LED3=0;
- LED4=1;
- LED5=1;
- LED6=1;
- LED7=1;
- LED8=1;
- P2|=Y4C;
- P2&=0x1f;
- }
- else
- {
- P2&=0x1f;
- BUZZ=0;
- RELAY=0;
- P2|=Y5C;
- P2&=0x1f;
- }
- }
- /*-------------------------------------------------------------------------------
- 按鍵掃描函數
- -------------------------------------------------------------------------------*/
- void key()
- {
- if((P3&0x0f)!=0x0f)
- {
- if(!keyflag)
- {
- deplay_50us(200);
- if((P3&0x0f)!=0x0f)
- {
- keyflag=1;
- switch(P3&0x0f)
- {
- case 0x07:if(UpT<99)UpT++;break;
- case 0x0b:if(DoT<UpT-1)DoT++;break;
- case 0x0d:if(UpT-1>DoT)UpT--;break;
- case 0x0e:if(DoT>0)DoT--;break;
- default:break;
- }
- if(UpT<=DoT|UpT>99|DoT<0) //保護程序,一旦存儲數據出錯可以使數據回到設定值,使系統穩定
- {
- UpT=30;
- DoT=0;
- }
- Write_byte(0x00,UpT); //將數據寫入EEPROM
- deplay_50us(18);
- Write_byte(0x01,DoT);
- deplay_50us(18);
- }
- }
- }
- else
- keyflag=0;
- }
- /*----------------------------------------------
- 顯示數據處理函數
- ----------------------------------------------*/
- void diswork()
- {
- dat[0]=UpT/10;
- dat[1]=UpT%10;
- dat[2]=DoT/10;
- dat[3]=DoT%10;
- dat[4]=Ad_data/10;
- dat[5]=Ad_data%10;
- dat[6]=NowT/10;
- dat[7]=NowT%10;
- }
- /*----------------------------------------
- 寫入內存一個字節
- -----------------------------------------*/
- void Write_byte(unsigned char add,unsigned char dat)
- {
- ET1=0;
- init_iic(); //可以不初始化,函數已有嚴格的時序控制
- Start(); //起始信號
- Send(AddWr); //器件地址
- Ack(); //應答
- Send(add); //存放地址
- Ack();
- Send(dat); //存放數據
- Ack();
- Stop(); //停止信號
- ET1=1;
- }
- /*-----------------------------------------
- 讀內存一個字節
- -----------------------------------------*/
- unsigned char read_byte(unsigned char add)
- {
- unsigned char rdat;
- ET1=0;
- init_iic(); //可以不初始化,函數已有嚴格的時序控制
- Start(); //起始信號
- Send(AddWr); //發送寫器件地址
- Ack();
- Send(add);
- Ack();
- Start(); //起始信號
- Send(AddRd); //讀器件地址
- Ack();
- rdat=Read(); //讀數據
- NoAck(); //好像是告訴器件接收完畢
- Stop(); //停止信號
- ET1=1;
- return rdat;
- }
- /*------------------------------------------------------
- 讀取溫度
- -------------------------------------------------------*/
- unsigned int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned int b=0;
- unsigned int t=0;
- Init_DS18B20();
- WriteOneChar(0xCC); // 跳過讀序號列號的操作
- WriteOneChar(0x44); // 啟動溫度轉換
- delay(50);
- Init_DS18B20();
- EA=0;
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度
- a=ReadOneChar(); //低位
- b=ReadOneChar(); //高位
- b<<=8;
- t=a+b;
- EA=1;
- return(t);
- }
- /*----------------------------------------------------------
- 定時器0中斷,產生1Khz占空比為30%的方波
- ----------------------------------------------------------*/
- void tm0_isr() interrupt 1
- {
- static j;
- if(j<3)
- PWM=1;
- else
- PWM=0;
- j++;
- if(j==10)
- {
- j=0;
- }
- }
- /*-----------------------------------------------------------
- 定時器中斷
- ------------------------------------------------------------*/
- void tm1_isr() interrupt 3 //定時掃描數碼管和溫度
- {
- static i,k;
- unsigned char com[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; //用于控制數碼管的亮滅
- TH1=(65536-1800)/256;
- TL1=(65536-1800)%256;
-
- if(i==4)
- {
- P2&=0x1f;
- P0=0xff;
- P2=Y7C;
- P2&=0x1f;
- P0=smg_we[i]&com[i];
- P2=Y6C;
- P2&=0x1f;
- P0=smg_du[dat[i]]+0x80;
- P2=Y7C;
- P2&=0x1f;
- i++;
- }
- else
- {
- P2&=0x1f;
- P0=0xff;
- P2=Y7C;
- P2&=0x1f;
- P0=smg_we[i]&com[i];
- P2=Y6C;
- P2&=0x1f;
- P0=smg_du[dat[i]];
- P2=Y7C;
- P2&=0x1f;
- i++;
- }
- if(i==8)
- {
- i=0;
- k++;
- if(k==25)
- {
- k=0;
- flag_get=1;//標志位有效
- }
- }
- }
- /*-----------------------------------------------------------
- 大約50us的延時函數
- -----------------------------------------------------------*/
- void deplay_50us(unsigned char t)
- {
- unsigned char j;
- for(;t>0;t--)
- for(j=19;j>0;j--);
- }
- void Ad_read(void)
- {
-
- Ad_data=adc_pcf8591(0);
- Ad_data=Ad_data*50/256;
- }
復制代碼
Keil代碼下載:
溫度.zip
(91.34 KB, 下載次數: 13)
2021-11-4 09:22 上傳
點擊文件名下載附件
|