如题,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; //”-“代码,若温度为-,则显示
}
复制代码转载
|