基于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)
|