Ds18b20有3根引脚,供电、接地、单总线。
在往单片机发送数据的时候18b20发送的是数字量,结构的优势让18b20可以避免进行手动的ADC转换。将模拟温度转换成数字。
采集的流程分为:
采集流程:
复位 //18b20的复位
主机发送0xcc; //从寄存器0xcc开始读取
主机发送0x44; //温度变化,内部ADC开始转换
延时,18b20将转换的值写入寄存器中
复位
发送0xcc;
发送0xBE //开始读取温度
读取2个字节
问题:由于P37接通之后,如果51和18b20一个想拉高电平,另外一个想拉低电平,会出现怎样的抉择
双方都要拉高时,上拉电阻的作用就体现了
在加上拉电阻,双方都拉高的时候,上拉电阻可以上高电平更准确,相当于再使一把劲。
如果有任何一方要拉低,那么就直接相当于接地,无论有没有上拉电阻,都会使该引脚成为低电平。
如何保证该总线是高电平
:通过在总线上添加上拉电阻。
51单片机的引脚的高电平很弱,所以需要上拉电阻来保证引脚的高电平。
复位:
//在复位的过程中, 如何检测引脚确实发生如下变化,证明18b20的存在
int t;
while (t <= 24 && (P3 & (1 << 7) != 0)) // 检测引脚是否为高电平
{
Delay10us(1);
t++;
}
if (t > 24)
{
return 0;
}
while (t <= 24 && (P3 & (1 << 7) == 0)) // 检测引脚是否为低电平
{
Delay10us(1);
t++;
}
if (t > 24)
{
return 0;
}
return 1;
cpu和18b20之间的通信
#define DS18B20CLR (P3 &= ~(1 << 7)) //P3_7 = 0
#define DS18B20SET (P3 |= (1 << 7)) //P3_7 = 1;
#define DS18B20TST ((P3 &= (1 << 7)) != 0)
void sendChar(unsigned char n)
{
int i;
for (i = 0; i < 8; ++i)
{
if (n & 0x01 != 0)
{
//根据手册
DS18B20CLR;
Delay10us(1);
DS18B20SET;
Delay10us(3);
}
else
{
DS18B20CLR;
Delay10us(5);
DS18B20SET;
}
}
}
unsigned char readChar(void)
{
unsigned char i, n = 0;
for(i = 0; i < 8; i++)
{
DS18B20CLR;
_nop();
_nop();
DS18B20SET;
_nop();
_nop();
_nop();
_nop();
n |= DS18B20TST << i; // read bit并保存至n
Delay10us(5);
}
return n;
}
ret = t2 << 8 | t1;
return ret * 0.0625;
上位机与上位机的通信
modbus协议框架:
帧:
起始字节 地址码 功能码 数据长度 数据码 数据码 校验码 结束码
0xAA 0x01 03 02 xx xx CRC 0x0D
地址码:modbus并未规定
功能码: 01 读温度
02 读秒数
03 设秒数
举例:
上位机(读温度命令): AA 01 01 00 XX 0D
下位机(回复给上位): AA 81 01 04 XX XX XX XX ** 0D上位机(02):AA 01 02 00 XX 0D
下位机(回复给上位):AA 81 02 XX XX ** 0D
校验:int parse(const unsigned char *buffer, int len)
{
if (buffer[1] != 0x01)
{
return 0;
}
if (buffer[0] != (unsigned char)0xAA || buffer[len-1] != (unsigned char)0x0D)
{
return 0;
}
if (校验条件)
{
return 0;
}
return buffer[2];
}
int main(void)
{
int ret = 0;
ret = parse(recvBuffer, pos);
if (ret != 0)
{
switch(ret)
{
}
}
}