找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 949|回复: 6
收起左侧

单片机温度控制,想把温度下限设置成负的,不知道怎么弄

[复制链接]
ID:985137 发表于 2022-3-12 10:29 | 显示全部楼层 |阅读模式
#include <reg51.h>

#define uint unsigned int
#define uchar unsigned char

sbit DQ=P2^3;   //ds18b20与单片机连接口

sbit RS=P2^5;   //液晶控制线接口
sbit RW=P2^6;
sbit EN=P2^7;



uchar data disdata[5];
uint tvalue,CurrentT=0;   //温度值
uchar tflag;              //温度正负标志

               
#define LCD_BUS P0

sbit SetKey = P2^0; //设置按键
sbit UpKey  = P2^1; //加按键
sbit DnKey  = P2^2; //减按键
sbit BEEP   = P2^4; //蜂鸣器

sbit Heat  = P1^0;  //加热继电器控制
sbit Cool  = P1^1;  //降温继电器控制


unsigned char AlarmTempLow=0,AlarmTempTop=30,Set=0;






void delayms(uint ms)   //延时xx毫秒
{
        uchar i;
        while(ms--)
        {
                 for(i=0;i<120;i++);
        }
}



void command(uint com)         //LCD写指令
{
   RS=0;                                //RS为0
   LCD_BUS=com;             //装载指令
   delayms(5);                 //延时5ms
   EN=1;                                 //LCD使能
   delayms(5);                //延时5ms
   EN=0;                                //LCD不使能
}

void write_dat(uchar dat)          //LCD写数据
{
   RS=1;                                        //RS为1
   LCD_BUS=dat;                     //装载数据
   delayms(5);                         //延时5ms
   EN=1;                                         //LCD使能
   delayms(5);                         //延时5ms
   EN=0;                                         //LCD不使能
}

void writestring(uchar x,uchar y,uchar *s) //LCD 写字符串
{     
        if (y == 0)  command(0x80 + x);     //表示第一行
        else         command(0xC0 + x);      //表示第二行

        while (*s)                         //判断是否字符串的结尾
        {     
     write_dat( *s);    //显示当前字符
                s ++;                             //字符串地址加1
        }
}

void writeChar(uchar x,uchar y,uchar s) //LCD 写字符串
{     
        if (y == 0)  command(0x80 + x);     //表示第一行
        else         command(0xC0 + x);      //表示第二行

        {     
     write_dat( s);    //显示当前字符
        }
}


void LCD_Initial()                //LCD初始化
{

   EN=0;                                  //LCD不使能
   RW=0;                                  //RW为0
   command(0x38);                //发送初始化指令
   command(0x0c);                //发送初始化指令
   command(0x06);          //发送初始化指令
   command(0x01);          //发送初始化指令
   command(0x80+0x02);        //发送LCD初始位置
}


/*************************DS1820程序****************************/
void delay_18B20(unsigned int i)//延时1微秒
{
   while(i--);
}

void ds1820rst(void)/*ds1820复位*/
{
        unsigned char x=0;
        DQ = 1;          //DQ复位
        delay_18B20(4); //延时
        DQ = 0;          //DQ拉低
        delay_18B20(100); //精确延时大于480us
        DQ = 1;          //拉高
        delay_18B20(40);
}

uchar ds1820rd(void)/*读数据*/
{
        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);
                DQ=1;
        }
   return(dat);
}

void ds1820wr(uchar wdata)/*写数据*/
{
        unsigned char i=0;
   for (i=8; i>0; i--)    //写一个字节数据到DS18B20
   {
                DQ = 0;
                DQ = wdata&0x01;  //写一位数据
                delay_18B20(10);  //延时
                DQ = 1;           //拉高数据线
                wdata>>=1;        //准备下一位
   }
}

unsigned int Read_Temperature(void)/*读取温度值并转换*/
{
        uchar a,b;
        ds1820rst();   
        ds1820wr(0xcc);//*跳过读序列号*/
        ds1820wr(0x44);//*启动温度转换*/
        ds1820rst();   
        ds1820wr(0xcc);//*跳过读序列号*/
        ds1820wr(0xbe);//*读取温度*/
        a=ds1820rd();  //读取低位数据
        b=ds1820rd();  //读取高位数据
        tvalue=b;   
        tvalue<<=8;
        tvalue=tvalue|a;   //取得16位数据
   if(tvalue<0x0fff)   tflag=0; //判断是否正温度
   else   {tvalue=~tvalue+1;tflag=1;}    //负温度,数据取反,温度标志位为1
        tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
        CurrentT=tvalue;//保存当前温度
        return(tvalue);//返回温度值
}

void Display_Temperature()                //显示温度
{
        uchar flagdat;
   disdata[0]=tvalue/1000+0x30;//百位数
   disdata[1]=tvalue%1000/100+0x30;//十位数
   disdata[2]=tvalue%100/10+0x30;//个位数
   disdata[3]=tvalue%10+0x30;//小数位

   if(tflag==0)   flagdat=0x20;//正温度不显示符号
   else   flagdat=0x2d;//负温度显示负号:-
        if(tflag==1)
        {
                writeChar(10,0,flagdat);//显示符号位
                writeChar(11,0,disdata[0]);//显示百位
                writeChar(12,0,disdata[1]);//显示十位
                writeChar(13,0,disdata[2]);//显示个位
                writeChar(14,0,0X2E);//显示小数点
                writeChar(15,0,disdata[3]);//显示小数位
        }
        else
        {
                writeChar(10,0,disdata[0]);//显示百位
                writeChar(11,0,disdata[1]);//显示十位
                writeChar(12,0,disdata[2]);//显示个位
                writeChar(13,0,0X2e);//显示小数点
                writeChar(14,0,disdata[3]);//显示小数位
                writeChar(15,0,' ');//显示小数位
        }
}

void SetFun(void) //进入设置参数子函数
{
        unsigned char i1=0,i2=0,i3=0,i4=0,i5=0,i6=0;
        if(SetKey==0)  //设置按键
        {
                delayms(20);   //延时防抖
                if(SetKey==0)  //设置按键
                {
                        if(Set<2)        Set++;   //设置按键次数累计
                        else Set=0;
                }
                switch(Set) //根据设置按键次数,指向对应设置位置
                {
                        case 0:  writestring(0,1," ");writestring(8,1," ");break;//清除设置符号
                        case 1:        writestring(0,1,">");writestring(8,1," ");break;//指向设置下限
                        case 2:        writestring(0,1," ");writestring(8,1,">");break;//指向设置上限
                }
                while(SetKey==0);//等待按键松开
        }
       
        if((UpKey==0)&&(Set!=0))//加按键按下
        {
                delayms(20);//延时防抖
                if(UpKey==0)//加按键按下
                {
                        switch(Set)//根据设置按键次数,设置上下限
                        {
                                case 1:        if(AlarmTempLow<99) AlarmTempLow++;else AlarmTempLow=99; break;//设置下限
                                case 2:        if(AlarmTempTop<99) AlarmTempTop++;else AlarmTempTop=99; break;//设置上限
                        }
                        i1 = AlarmTempLow/100;             //获得下限温度值的百位
                   i2 = (AlarmTempLow%100)/10;         //获得下限温度值的十位
                        i3 = AlarmTempLow%10;                 //获得下限温度值的个位
                       
                        i4 = AlarmTempTop/100;              //获得上限温度值的百位
                   i5 = (AlarmTempTop%100)/10;         //获得上限温度值的十位
                        i6 = AlarmTempTop%10;                 //获得上限温度值的个位

                        writestring(5,1,"   ");       //清除之前的内容
                        writestring(13,1,"     ");    //清除之前的内容
                        if(i1!=0)        writeChar(5,1,i1+'0');                  //在第二行第5位 ,显示下限温度值的百位
                        if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');         //在第二行第5位 ,显示下限温度值的十位
                        if(i1!=0) writeChar(6,1,i2+'0');                    //在第二行第6位 ,显示下限温度值的十位
                        if((i1==0)&&(i2==0))        writeChar(5,1,i3+'0');      //在第二行第5位 ,显示下限温度值的个位
                        else if((i1==0)&&(i2!=0))        writeChar(6,1,i3+'0');  //在第二行第6位 ,显示下限温度值的个位
                        if((i1!=0))         writeChar(7,1,i3+'0');                 //在第二行第7位 ,显示下限温度值的个位
                       
                        if(i4!=0)        writeChar(13,1,i4+'0');                 //在第二行第13位 ,显示上限温度值的百位
                        if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');        //在第二行第13位 ,显示上限温度值的十位
                        if(i4!=0) writeChar(14,1,i5+'0');                   //在第二行第14位 ,显示上限温度值的十位
                        if((i4==0)&&(i5==0))        writeChar(13,1,i6+'0');     //在第二行第13位 ,显示上限温度值的个位
                        else if((i4==0)&&(i5!=0))        writeChar(14,1,i6+'0'); //在第二行第14位 ,显示上限温度值的个位
                        if((i4!=0)) writeChar(15,1,i6+'0');                 //在第二行第15位 ,显示上限温度值的个位
                        while(UpKey==0);       //等待按键松开
                }
        }
       
        if((DnKey==0)&&(Set!=0))//减按键
        {
                delayms(20);
                if(DnKey==0)//减按键
                {
                        switch(Set)//根据设置按键次数,设置上下限
                        {
                                case 1:        if(AlarmTempLow>0) AlarmTempLow--;else AlarmTempLow=0; break;//设置下限
                                case 2:        if(AlarmTempTop>0) AlarmTempTop--;else AlarmTempTop=0; break;//设置上限
                        }
                        i1 = AlarmTempLow/100;          //获得下限温度值的百位
                   i2 = AlarmTempLow%100/10;         //获得下限温度值的十位
                        i3 = AlarmTempLow%10;                 //获得下限温度值的个位
                       
                        i4 = AlarmTempTop/100;          //获得上限温度值的百位
                   i5 = AlarmTempTop%100/10;         //获得上限温度值的十位
                        i6 = AlarmTempTop%10;                 //获得上限温度值的个位
                        writestring(5,1,"   ");    //清除之前的内容
                        writestring(13,1,"     ");//清除之前的内容
                        if(i1!=0)        writeChar(5,1,i1+'0');//在第二行第5位 ,显示下限温度值的百位
                        if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');//在第二行第5位 ,显示下限温度值的十位
                        if(i1!=0) writeChar(6,1,i2+'0');//在第二行第6位 ,显示下限温度值的十位
                        if((i1==0)&&(i2==0))        writeChar(5,1,i3+'0');//在第二行第5位 ,显示下限温度值的个位
                        else if((i1==0)&&(i2!=0))        writeChar(6,1,i3+'0');//在第二行第6位 ,显示下限温度值的个位
                        if((i1!=0))         writeChar(7,1,i3+'0');//在第二行第7位 ,显示下限温度值的个位
                       
                        if(i4!=0)        writeChar(13,1,i4+'0');//在第二行第13位 ,显示上限温度值的百位
                        if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');//在第二行第13位 ,显示上限温度值的十位
                        if(i4!=0) writeChar(14,1,i5+'0');//在第二行第14位 ,显示上限温度值的十位
                        if((i4==0)&&(i5==0))        writeChar(13,1,i6+'0');//在第二行第13位 ,显示上限温度值的个位
                        else if((i4==0)&&(i5!=0))        writeChar(14,1,i6+'0');//在第二行第14位 ,显示上限温度值的个位
                        if((i4!=0)) writeChar(15,1,i6+'0');//在第二行第15位 ,显示上限温度值的个位
                       
                        while(DnKey==0);
                }
        }
}



void Alarm(void)//报警子函数
{
        if((CurrentT>=(AlarmTempTop*10))||(CurrentT<=(AlarmTempLow*10))||(tflag==1)) //超出设定范围
                {
                        BEEP=0;//启动报警
                }
                else //在设定范围内
                {
                        BEEP=1;//取消报警
                }
}


void main(void)
{
        unsigned char i=0;
        //P3=0xef;
        P2=0xef;P1=0xff;BEEP=1;//端口初始化,
        LCD_Initial();         //LCD 初始化
       
        Read_Temperature(); //读取温度值
        writestring(1,0,"DS18B20 Alarmer");          //显示“DS18B20 Alarmer”
        delayms(1000);                //延时1S
        writestring(0,0,"Current T=      ");          //显示“Current T= ”
        writestring(0,1," Low=0   Top=30 ");          //显示“ Low=10  Top=40 ”
       
        //NG=0;
        while(1)
        {
                 Read_Temperature();        //        //读取温度值
                Display_Temperature();                //显示温度值
                SetFun();//参数设置,按键功能
                Alarm();//报警子函数
                if((CurrentT<(AlarmTempTop*10))&&(CurrentT>(AlarmTempLow*10)))//当前温度在设置范围内
                {
                        Cool=1;Heat=1;//不加热,不降温
                }
                else if((CurrentT>=(AlarmTempTop*10)))//当前温度高过设定值上限
                {
                        Cool=0;Heat=1;//不加热,降温
                }
                else if((CurrentT<=(AlarmTempLow*10))||(tflag==1))//当前温度低于下限
                {
                        Cool=1;Heat=0;//加热,不降温
                }
        }       

}

批注 2022-03-12 102710.png
回复

使用道具 举报

ID:466505 发表于 2022-3-12 10:37 | 显示全部楼层
用有符号数不行??
回复

使用道具 举报

ID:551638 发表于 2022-3-12 13:01 | 显示全部楼层
判断,然后手动加
回复

使用道具 举报

ID:985137 发表于 2022-3-12 14:42 | 显示全部楼层
hcfat51h 发表于 2022-3-12 10:37
用有符号数不行??

不懂?
回复

使用道具 举报

ID:161164 发表于 2022-3-12 15:10 | 显示全部楼层
显示归显示,按键归按键
改了一部份
余下的加热保温控制你再想一下
2022-03-12_150413.png


                       
       
                                                        
回复

使用道具 举报

ID:985137 发表于 2022-3-14 09:33 | 显示全部楼层
lkc8210 发表于 2022-3-12 15:10
显示归显示,按键归按键
改了一部份
余下的加热保温控制你再想一下

老哥,SPL_tflag怎么定义呀
回复

使用道具 举报

ID:161164 发表于 2022-3-14 10:52 | 显示全部楼层
2248373991 发表于 2022-3-14 09:33
老哥,SPL_tflag怎么定义呀

bit SPL_tflag = 0;
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表