我在蓝桥杯的板子上看到,他的是寄生电源供电,也就是没有外接电源,靠总线高电平供电,低电平电容放电。编程之处略有不同。
网上很多资料,我还是只说最难懂的点
一、注意事项
1.温度转换命令【44h】后面要加延时,而且总线要置1,提供上拉电流。
send(0xcc);
send(0x44);
DAT = 1;
delay1s();
2.
为了提高可移植性,可以这样写
uchar way;
send(0xcc);
send(0xb4);
way = read();//读取温度状态
DAT = 1; //释放总线
if(way == 1)
{
#define waibu
}
#ifdef waibu
......
#else
......
#endif
......
3.注意:
每次命令都得初始化
常用命令
初始化时序:
总线拉低500微秒,再释放总线(拉高)。然后进入接收模式。如果设备正常会发送应答信号,也就是低电平把总线拉低200微秒。
uchar i = 0;
DAT = 1;
DAT = 0;
delay600us();
DAT = 1;
dealay100us();
while(DAT == 1)
{
if(i == 5)
{
return 0;
}
i++
}
return 1;
写时序:
1.总线置一
2.总线置零
3.等5微秒
4.总线保持60微妙(写0)
总线拉高,保持60微秒(写1)
5.总线置1保持1微秒以上
DAT = 1;
DAT = 0;
delay5us();
DAT = 0;
//DAT = 1; 写1
delay60us();
DAT = 1;
读时序:
1.总线置一
2.总线置零
3.等4微秒
4.总线置一(释放总线)
5.等
读一个位:
DAT = 1;
DAT = 0;
delay();
DAT = 1;
delay();
uchar dat;
dat = DAT;
DAT = 1;
读一个字节:
uchar readByte()
{
uchar i,dat=0;
uchar da=0;
for(i=0;i<8;i++)
{
DATA=0;
_nop_();
DATA=1;
delay4us();
da=DATA;
da<<=7;
dat=(dat>>1)|da;
delay60us();
}
return dat;
}
温度换算是负温度减一取反乘精度
正温度直接乘精度
注意:在上电复位的时候,温度寄存器中的值为0x0550,即+85摄氏度。所以在应用开发中,有些朋友一直读到的数据都是85.5摄氏度,就说明DS18B20根本没有进行温度转换,你读到的是上电复位的初始值。
——————————————分割线————————————————
干货来了!!!!!!!!!!!!!!!!!!!!正式开始编程!
首先,先测试一下能不能用
那么就是初始化一下看看返回值是不是0
经过两天的测试,检测不到这个玩意。。
全文完
大家自己做,应该是可以的。代码没问题,
后来检测到了,大家继续往后看
#include "ds18b20.h"
////单总线延时函数
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
void Delay_OneWire1(unsigned int t)
{
while(t--);
}
void Delay_us(void)
{
unsigned char i;
i = 30;
while (--i);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
// unsigned char index = 0;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
Delay_us();
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80); // 延时大于480us
DQ = 1;
Delay_OneWire(5); // 14
initflag = DQ; // initflag等于1初始化失败
Delay_OneWire(50);
return initflag;
}
————————分割线————————————————
更新于2020.3.29
服了,又可以了。我脑子瓦特了
箭头这里是电阻上拉的意思。所以不能等时间太久,不然就等不到,所以才显示的检测不到硬件。
这里原来是50,我改成5了,立马就检测到了
返回值是0
唉
然后我们检测一下供电方式。这里也是一个大坑,无力吐槽蓝桥杯这个板子的奇葩设计。。
uchar rd_temperature(void)
{
uchar dq;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xb4);
Delay_OneWire(5);
dq = DQ;
return dq;
}
看起来是寄生电源供电,实际上是外部电源供电。。。
因为寄生电源供电的话,vdd和gnd都接地,这个不是
所以这段代码的返回值是1。。。
我都是用串口检测的
下一步开始测温度
int rd_temperature(void)
{
uchar LOW = 0,HIGH = 0;
int temp = 0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay1000ms() ;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LOW = Read_DS18B20();
HIGH = Read_DS18B20();
temp = (HIGH << 8) | (LOW);
return temp;
}
主函数这里数据处理一下
int GOODORNOT = 0;
Init();
uartInit();
while(1)
{
GOODORNOT = rd_temperature();
GOODORNOT = GOODORNOT*0.0625+0.5;
uartSendByte((uchar)(GOODORNOT/10)+'0');
uartSendByte((uchar)(GOODORNOT%10)+'0');
delay(50000);
}
成功
全文完
有问题的可以留言评论