很高兴,终于调出来了

2020-02-05 08:52发布

本人是个单片机菜鸟,什么都不会,这是我改的一个程序,与大家分享!!!!;注意是用ds18b20设计的温度报警程序;写的有点撇!!!!!!!
请大家别见笑,
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
19条回答
liudaolunhui
1楼-- · 2020-02-07 01:02
各位大哥谁有关于温度传感器的程序
mystarlight
2楼-- · 2020-02-07 03:26
楼主不错啊
Ilove51andAVR
3楼-- · 2020-02-07 08:26
回复【13楼】liudaolunhui 晓鹏
           各位大哥谁有关于温度传感器的程序
-----------------------------------------------------------------------

送给你一个我修改的程序,这个程序花了我大量精力和很多心思去注释的,希望大家共同进步!

/******************************************************
原程序从中国电子开发网WWW.OURDEV.CN中某高手修改而来,经过本人改动,已经完全可以正常显示温度
日期:2011.10.07
版本号:20111007.0349

P2.0-个位 //位选
P2.1-十位 //位选
P2.2-百位 //位选
P2.3-千位 //位选
P0.0-->P0.7:  a-->dp //段选a-g,dp
P1.2-温感器DS18B20的信号端
*********************************************************/
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

sbit DQ=P1^2; //定义DS18B20端口DQ
sbit DIN=P0^7; //小数点
sbit gewei=P2^0;   //个位位选
sbit shiwei=P2^1;  //十位位选
sbit baiwei=P2^2;  //百位位选
sbit qianwei=P2^3; //千位位选

unsigned char code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xfe,0xf7,0xbf};//共阳极数码管段码,为0-9,空白和上标-,下标_,中间-
unsigned char code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09}; //专门给小数查表用的,原理请见下面部分说明。
/*
本人注:DS18B20的小数位数是由4位二进制数表示,单位为0.0625度,这样,0-15表示了从,0-15*0.0625度,再根据需要(四舍五入)保留1位小数,就成那样了。
如:
0000(0x00)就是0*0.0625=0.0度,在ditab[16]中就是第1个位置0x00;
0001(0x01)就是1*0.0625=0.1度,在ditab[16]中就是第2个位置0x01(四舍五入保留1位小数);
0010(0x02)就是2*0.0625=0.1度,在ditab[16]中就是第3个位置0x01(四舍五入保留1位小数);
0011(0x03)就是3*0.0625=0.2度,在ditab[16]中就是第4个位置0x02(四舍五入保留1位小数);
0100(0x04)就是4*0.0625=0.3度,在ditab[16]中就是第5个位置0x03(四舍五入保留1位小数);
0101(0x05)就是5*0.0625=0.3度,在ditab[16]中就是第6个位置0x03(四舍五入保留1位小数);
0110(0x06)就是6*0.0625=0.4度,在ditab[16]中就是第7个位置0x04(四舍五入保留1位小数);
0111(0x07)就是7*0.0625=0.4度,在ditab[16]中就是第8个位置0x04(四舍五入保留1位小数);
1000(0x08)就是8*0.0625=0.5度,在ditab[16]中就是第9个位置0x05(四舍五入保留1位小数);
1001(0x09)就是9*0.0625=0.6度,在ditab[16]中就是第10个位置0x06(四舍五入保留1位小数);
1010(0x0a)就是10*0.0625=0.6度,在ditab[16]中就是第11个位置0x06(四舍五入保留1位小数);
1011(0x0b)就是11*0.0625=0.7度,在ditab[16]中就是第12个位置0x07(四舍五入保留1位小数);
1100(0x0c)就是12*0.0625=0.8度,在ditab[16]中就是第13个位置0x08(四舍五入保留1位小数);
1101(0x0d)就是13*0.0625=0.8度,在ditab[16]中就是第14个位置0x08(四舍五入保留1位小数);
1110(0x0e)就是14*0.0625=0.9度,在ditab[16]中就是第15个位置0x09(四舍五入保留1位小数);
1111(0x0f)就是15*0.0625=0.9度,在ditab[16]中就是第16个位置0x09(四舍五入保留1位小数);
*/

unsigned char high_byte=0,low_byte=0;//low_byte=温度值低8位;high_byte=温度值高8位.
unsigned char presence; //DS18B20初始化成功标志:=0表示成功,=1表示失败。
unsigned char zhengshu=0; //最终的温度值(整数部分),小数部分为:xiaoshu(在另一个函数里定义)

void Temp_Display(uchar a,uchar b,uchar c,uchar d); //温度显示函数,(用于18B20温感器)
void Disp_Temperature(); //计算、转换 温度函数,(用于18B20温感器)

/**********************************************************/
//DS18B20对时间要求很严,但只能长不能短
void delay_18B20(unsigned int i)//延时函数,(用于18B20温感器)
{
   while(--i);
}

/**********************************************************/
void LED_OFF()
{
        gewei=1; //个位灯灭
        shiwei=1; //十位灯灭
        baiwei=1; //百位灯灭
        qianwei=1; //千位灯灭
//        P2|=0x0f; //关闭所有显示 //0x0f=00001111,P2的其它位保持原有状态不变
}
void gewei_on()
{
        gewei=0; //个位灯亮
//        P2|=0x0e; //0x0e=00001110,先关闭个位、十位、百位,P2的其它位保持原有状态不变
//        P2&=0xfe; //0xfe=11111110,只显示小数位,P2的其它位保持原有状态不变
}
void shiwei_on()
{
        shiwei=0; //十位灯亮
//        P2|=0x0d; //0x0d=00001101,先关闭小数、十位、百位,P2的其它位保持原有状态不变
//        P2&=0xfd; //0xfd=11111101,只显示个位,P2的其它位保持原有状态不变
}
void baiwei_on()
{
        baiwei=0; //百位灯亮
//        P2|=0x0b; //0x0b=00001011,先关闭小数、个位、百位,P2的其它位保持原有状态不变
//        P2&=0xfb; //0xfb=11111011,只显示十位,P2的其它位保持原有状态不变
}
void qianwei_on()
{
        qianwei=0; //千位灯亮
//        P2|=0x07; //0x07=00000111,先关闭小数、个位、十位,P2的其它位保持原有状态不变
//        P2&=0xf7; //0xf7=11110111,只显示百位,P2的其它位保持原有状态不变
}


/*****ds18b20初始化函数*********************/
unsigned char Init_DS18B20(void)//初始化DS18B20,(用于18B20温感器)
{
        DQ=1;                                        //DQ复位
        delay_18B20(8);        //稍做延时
        DQ=0;                                        //单片机将DQ拉低
        delay_18B20(80);        //精确延时大于480us
        DQ=1;                                        //拉高总线
        delay_18B20(14);        //别的程序括号内的值为:8
        presence=DQ;                //稍做延时后,如果presence=0则初始化成功,presence=1则初始化失败
        delay_18B20(20);        //注意:初始化不成功,问题有可能出现在此行上的延时数值。 //别的程序括号内的值为:100

//        DQ = 1; //别的程序会多出本条语句

        return(presence); //返回信号,presence=0则初始化成功,presence=1则初始化失败
}

/*****ds18b20读一个字节*********************/
unsigned char ReadOneChar(void)//读一个字节,(用于18B20温感器)
{
        unsigned char i=0;
        unsigned char dat=0;

        for(i=8;i>0;i--)
        {
                _nop_(); //保证两次读操作时间间隔1us以上
                DQ=0; //给脉冲信号
                _nop_(); //保证主机拉低总线1us以上
                dat>>=1;
                DQ=1; //给脉冲信号
               
                if(DQ) //主机对总线采样的数 判断//如果DQ=1才执行下面的语句,如果=0不执行,并返回上面执行dat>>=1;这样就相当于把0读出来了。
                        dat|=0x80; //0x80=10000000
                delay_18B20(4); //等待读操作结束
        }
        return(dat);
}

/*****ds18b20写一个字节*********************/
void WriteOneChar(unsigned char dat)//写一个字节,(用于18B20温感器)
{
        unsigned char i=0;

        for(i=8;i>0;i--)
        {
                _nop_(); //保证两次写操作时间间隔1us以上
                DQ=0;
                _nop_(); //保证主机拉低总线1us以上
                DQ=dat&0x01; //假设dat=0x9b,即10011011,与0x01相与后结果为0x01,即00000001,而DQ电平只有一位取最低位为1,同理,如果最低位为0则取0。
                delay_18B20(5); //写时间间隔必须最少持续60us
                DQ=1;
                dat>>=1; //0x9b右移一位为0x4d,即01001101。照此循环8次,把dat的值从低位开始依次传送给18B20。
        }
}

/*****读取ds18b20当前温度*********************/
void Read_Temperature()//读取温度,(用于18B20温感器)
{

/*
        Init_DS18B20();
        WriteOneChar(0xCC); //跳过读序号列号的操作 //0xCC=11001100
        WriteOneChar(0x4E); //写入"写暂存器"命令,修改TH和TL和分辨率配置寄存器 //0x4E=01001110
//先写TH,再写TL,最后写配置寄存器
        WriteOneChar(0x6e); //写入想设定的温度报警上限 //0X6e=01101110
        WriteOneChar(0x00); //写入想设定的温度报警下限
        WriteOneChar(0x3f); //写配置寄存器,格式为0 R1 R0 1,1 1 1 1 //0X3f=00111111
//R1R0=00分辨率为9位,R1R0=11分辨率为12位
        delay_18B20(80); //经本人测试,本行延时好像无用,可省略不写
*/
//以上注释可省略不写,因为不写出来,DS18B20会采用默认值为12位分辨率。写出来就多此一举,还浪费时间。

        Init_DS18B20(); //初始化ds1820
        WriteOneChar(0xCC); //跳过读序列号的操作 //0xCC=11001100
        WriteOneChar(0x44); //启动温度转换
        delay_18B20(80); //经本人测试,本行延时好像无用,可省略不写

        Init_DS18B20(); //初始化ds1820
        WriteOneChar(0xCC); //跳过读序列号的操作 //0xCC=11001100
        WriteOneChar(0xBE); //读取温度寄存器(共可读9个寄存器),前两个就是温度
        delay_18B20(80); //经本人测试,本行延时好像无用,可省略不写

        low_byte=ReadOneChar(); //第1次读取到的数据是温度值低8位
        high_byte=ReadOneChar(); //第2次读取到的数据是读取温度值高8位
}


/*****温度显示函数*********************/
void Temp_Display(uchar a,uchar b,uchar c,uchar d)//显示温度,(用于18B20温感器)
{

        LED_OFF();
        P0=table[a]; //显示小数位
        gewei_on(); //个位灯亮
        delay_18B20(300);

        LED_OFF();
        P0=table; //显示个位
        DIN=0; //小数点在第二位显示
        shiwei_on(); //十位灯亮
        delay_18B20(300);
       
        LED_OFF();
        P0=table[c]; //显示十位
        baiwei_on(); //百位灯亮
        delay_18B20(300);

        LED_OFF();
        P0=table[d]; //显示百位
        qianwei_on(); //千位灯亮
        delay_18B20(300);

        LED_OFF();
}

/*****计算、转换 温度*********************///这是本人参考别人改进后加上的
void Disp_Temperature() //计算、转换 温度函数,(用于18B20温感器)
{
        unsigned char xiaoshu=0; //用来存储小数数值的变量(非位选变量)
        unsigned char ge=0,shi=0,bai=0; //位选变量

        zhengshu=(high_byte<<4)+(low_byte>>4); //把温度高8位和低8位的整数部分合成一个完整的整数,小数部分去掉。
//经过本人测试,假如现在温度是25.0625度(0000 0001 1001 0001),高8位high_byte=0000 0001,低8位low_byte=1001 0001。
//(接上句)那么high_byte左移4位变为:0001 0000,low_byte右移4位变为:0000 1001。这两者相加(即相或)=0001 1001,转换为
//(接上句)十进制就是25度。至于小数部分,另外处理,本节主要讲解温度值是如何转换来的。

        xiaoshu=ditab[low_byte&0x0f];  //去掉整数部分,保留小数;并查表得小数位的值

        ge=zhengshu%10;
        shi=zhengshu%100/10;
        bai=zhengshu/100;

        if(bai==0) //如果百位,或百位和十位均为0,则不显示,达到消隐的目的
        {
                bai=10;
                if(shi==0)
                        shi=10;
        }
        Temp_Display(xiaoshu,ge,shi,bai);
}


/*********************************************************/
void main(void)
{
        while(1)
        {
                Read_Temperature(); //读取ds18b20当前温度

                if(presence==1) //如果初始化失败,则执行下面的语句:
                        LED_OFF(); //关闭所有显示
                else
                        Disp_Temperature(); //显示温度
        }
}
sramsun2011
4楼-- · 2020-02-07 08:51
 精彩回答 2  元偷偷看……
sramsun2011
5楼-- · 2020-02-07 11:19
继续加油!
liudaolunhui
6楼-- · 2020-02-07 12:30
多谢各位前辈!!!很久没来逛了

一周热门 更多>