查看: 1255|回复: 0
打印 上一主题 下一主题

18B20温度传感器读到整数数据死机。求解

[复制链接]
跳转到指定楼层
沙发
发表于 2015-10-7 13:04:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如题,18B20温度传感器,一般情况下读温度都正常。但是读到整数的时候。如20°,30°,40°,都会死机。
现象:温度到整数的时候,如50.0°   显示数字不再变化,实际温度有变化。插拔温度传感器没有反应,给板子重新上电复位后又显示正常。死机的单片机其他操作正常。
但是如果从49.8直接跳到50.3,也就是传感器没有读到50.0°这个温度则正常
传感器接4.7k上拉电阻。5v供电 温度采集代码如下,stm8s单片机
void _delay_us(uint us)
{
         us*= 3;
   while(-- us);
}
void delay_1ms(uint a)
{
    uint i;
    while(a--)
    _delay_us(1000);
}

//18B20初始化函数
void init_Ds18B20(void)
{
                uchar n,j;        
                PA_DDR|=0x08;
                PA_CR1|=0x08;   //设置IO口为推挽输出模式
    DQ=1;
    _delay_us(30);
    DQ=0;
                _delay_us(600); //总线保持低电平在480 - 960微秒之间
    DQ=1;
    _delay_us(100);
    n=DQ;
    _delay_us(400);    //以上语句为检查是否存在18B20,若n=0说明 18B20存在
}
//18B20写子函数
void write_byte(uchar date)
{
    uchar i;

                PA_DDR|=0x08;
                PA_CR1|=0x08;   //设置IO口为推挽输出模式        
                delay_1ms(2);
    for(i=0;i<8;i++)  //请参考18B20时序图
    {
                                DQ=0;
       _delay_us(2);
       DQ=date&0x01;
       _delay_us(60);
       DQ=1;
       date>>=1;
    }
    _delay_us(4);
}
//18B20读子函数
uchar read_byte(void)
{
    uchar i,value;
                delay_1ms(2);
    for(i=0;i<8;i++)
    {
        PA_DDR|=0x08;
                                PA_CR1|=0x08;   //设置IO口为推挽输出模式

        DQ=0;
        value>>=1;     //先读地位,因此没读一次数向左移动 一位
        DQ=1;

        PA_DDR&=~0x08;
                                PA_CR1|=0x08;   //设置IO口为推挽输出模式

        if((PA_IDR&0x08)==0x08)  //如果IO口电压为高,则value中对应的位为1,否则为0
                                        value|=0x80;
        _delay_us(60);
    }
    return value;            //将读的数返回
}
//读温度数据并处理子函数
void readtemperature(void)
{
    uchar a,b,p,j;               
                init_Ds18B20();     //初始化18B20
    write_byte(0xcc);   //逃过ROM,一个IO口有多个 18B20时需 要读ROM
    write_byte(0x44);   //启动温度检测
    DQ=1;
                _delay_us(600);         //延时,等待温度检测完成
                init_Ds18B20();     //每次操作前要初始化18B20
                write_byte(0xcc);   //跳过ROM
    write_byte(0xbe);   //从储存器读数据
    a=read_byte();      //读地位温度数据
    b=read_byte();      //读高位温度数据
                if(b>0x07)          //如果温度为负数,b会大于0x07,故当b大于0x07时,让1602在温度前面显示“-”
                        q=1;
    p=(a&0x0f)*625/100;  //小数部分数据处理,由于小数部分有 四位,故分辨率为1/16,16×625刚好为10000,这里再除于100是精确到小数点后两位
//理论上18B20可以精确到小数点后四位,但由于分辨率只有1/16,即0.06左右,小数点后第三第四位已经没有实际意义
    b=(b<<4)+(a>>4);     //将低位温度数据的高四位和高位温度 数据的 低四位拼成温度数据的整数部分
                table2[5]=p%10;  //小数点后第二位数据,加上30是为了和1602中字符代码一致
                table2[4]=p/10;
                table2[3]=0x2e;       //小数点代码
                table2[2]=b%10;  
                table2[1]=b/10;   //整数部分
                table2[0]=0x80;        //空字符代码,就是不显示任何字符
    if(q==1)               
                        table2[0]=0x2d;        //”-“代码,若温度为-,则显示  
}
复制代码转载

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

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