做网站有一个火箭回顶部,企业网站系统cms,如何建设网站哪个济南兴田德润简介,如何写开发信wordpress我要成为嵌入式高手之4月9日51单片机第四天#xff01;#xff01; ————————————————————————————
DS18B20温度传感器
单总线数字温度计
异步的半双工的串行通信
测量范围从-55℃ ~ 125℃#xff0c;增量值为0.5℃
要用DS18B20采集温度 ————————————————————————————
DS18B20温度传感器
单总线数字温度计
异步的半双工的串行通信
测量范围从-55℃ ~ 125℃增量值为0.5℃
要用DS18B20采集温度就要实现与单片机之间的通信因此有两个问题 Bus master active low主机执行低电平
DS1820 active lowDS18B20执行低电平
Both bus master and DS1820 active low全都释放低电平
Resistor pull-up电阻拉高
1、如何向DS18B20发送数据
sendChar(发送单字节的数据) 主机单片机向DS18B20写入发送0 空闲时总线上呈现高电平如果要发送0就把总线电平拉低至少(MIN)拉低15微秒典型(TYP)拉低30微秒最多(MAX)拉低60微秒。这样一段时间就表示单片机向DS18B20写入一个0由于是异步传输故0 和 1只能靠控制时间长短来表示
主机单片机向DS18B20写入发送1 空闲时总线上呈现高电平如果要发送1就把总线电平拉低拉低时间大于1微秒后立刻又将电平拉高拉高时间为至少(MIN)拉高15微秒典型(TYP)拉高30微秒最多(MAX)拉高60微秒。
2、如何从DS18B20读取数据
readChar() MASTER SAMPLES主机采样读引脚电平
主机单片机从DS18B20读取接收0 空闲时总线上呈现高电平DS18B20会将电平拉低在拉低后的15微秒以内单片机进行采样若为低电平说明收到的是0
主机单片机从DS18B20读取接收1 空闲时总线上呈现高电平DS18B20会将电平拉低在拉低后1微秒之后且15微秒以内单片机进行采样若为高电平说明收到的是1
以上两图即为DS18B20数据收发原理
——————————————————————————————————————————— DS18B20采集流程
复位
1、单片机向DS18B20发送0xCC
2、单片机向DS18B20发送0x44启动温度变换
3、延时将温度模拟转换为数字需要时间大约为700ms
复位
4、单片机向DS18B20发送0xCC
5、单片机向DS18B20发送0xBE读取温度
6、单片机连续从DS18B20读取两个字节
如何将读取到的字节转换为浮点型float
读出的两个字节是一个补码需要 * 0.06252 ^ -4得到温度 涉及到的问题 单片机P37和DS18B20总线连接起来要是P37要拉低电平总线要拉高电平那到底是高电平还是低电平 答一定是低电平因为有任一方拉低相当于该总线接地那么就是低电平。 那么如何保证该总线一定是高电平呢 答在该总线上外接一个上拉电阻4.7k ~ 10k因为51的内部构造导致51的上拉电平非常弱因此需要这个电阻来添一把力保证它是高电平这样在单片机和DS18B20同时拉高时该总线一定是高电平。 这俩表现出一种特性线与特性
拉高总线的操作称为释放总线
拉低总线的操作称为占有总线 初始化过程复位和存在脉冲
黑色线表示单片机拉低此时DS18B20释放总线最少480最多960微秒然后单片机释放总线在60~240微秒之内DS18B20要拉低总线这样就能检测到低电平在240微秒之后DS18B20再次释放总线此时总线上必然会检测到高电平这样就表示该信号存在可以被使用 延时10us函数
//延时10us
void delay10us(unsigned int n) //12.000MHz
{unsigned char data i;while (n--){i 2;while (--i);}
}
初始化
#include ds18b20.h#define DS18B20CLR (P3 ~(1 7))
#define DS18B20SET (P3 | (1 7))
#define DS18B20TST ((P3 (1 7)) ! 0)//判断总线是否为高电平1为高电平0为低电平void delay10us(unsigned int n) //12.000MHz
{unsigned char data i;while (n--){i 2;while (--i);}
}int rest18b20(void)
{int t 0;DS18B20CLR;//单片机拉低delay10us(70);//延时DS18B20SET;//释放总线while (t 24 DS18B20TST)//240us之内DS18B20为高电平{delay10us(1);t; }if (t 24)//超过240us{return 0;//说明初始化有问题}t 0;while (t 24 !DS18B20TST)//240us之内DS18B20为低电平{delay10us(1);}if (t 24){return 0;//一直为低电平跳不上高电平初始化有问题} return 1;//在240us之内出现低电平初始化正确返回1
} 向18b20发送数据
/********************向18b20发送数据*一次发送一个char*先发低位******************/
void sendChar(unsigned char n)//LSB先行先发低位
{int i 0;for (i 0; i 8; i){if ((n 0x01) ! 0)//判断要发的位不为0此时应该找1的时序图{DS18B20CLR;_nop_();_nop_();DS18B20SET;delay10us(3); }else{DS18B20CLR;delay10us(5);DS18B20SET;}n 1;}
}
从18b20接收数据
/*********************从18b20接收数据*一次发送一个char*从低位开始接收*返回接收到的数据********************/
unsigned char readChar(void)//接收18b20的数据每次接收一个字符
{unsigned char ret 0;int i 0;for (i 0; i 8; i){DS18B20CLR;//拉低总线_nop_();//空指令但是消耗了一个指令周期1us_nop_();DS18B20SET;//释放总线_nop_();_nop_();_nop_();//采样DS18B20TST表示P37是(1)否(0)为高电平若接收到1左移或运算可以将指定位置1(第i位为1其余位为0)ret | DS18B20TST i;delay10us(5);}return ret;
}
获取温度按照流程
float getTemerature(void)
{unsigned char t1, t2; int ret 0;
//接收温度的总流程rest18b20();sendChar(0xCC);sendChar(0x44);delay10us(60000);rest18b20();sendChar(0xCC);sendChar(0xBE);t1 readChar();//低位t2 readChar();//高位//将字符型转换为浮点型ret t2 8 | t1;return ret * 0.0625;
//
} main.c
如何查看获取到的温度的数据呢
这里采用串口调试查看uart-send_buffer
#include ds18b20.h
#include uart.hint main(void)
{float f;char s[16]; uart_init(); while (1){f getTemerature();sprintf(s, %f, f);send_buffer(s, strlen(s));}return 0;
}
MODBUS协议框架
帧
起始字节地址码功能码数据长度数据码数据码校验码 结束码0xAA0x01 01读温度02读秒数03设置秒数 02xxxxxx 0x0D
例如
读温度
上位机发出AA 01 01 00 ** 0D 下位机回复AA 81 01 04 xx xx xx xx ** 0D 0000 0001 1000 0001 第一位0代表上位机发给下位机第一位1代表下位机发给上位机
读秒数
上位机发出AA 01 02 00 ** 0D 下位机回复AA 81 02 xx xx ** 0D 两个字节的数值大端发送