硬件基础4
ds18b20数字温度传感器1.参数指标1量程温度测量范围 -55℃----125℃2精度测量的温度值与实际温度值之间所允许的最大误差 ±0.5℃3分辨率传感器对温度变化的敏感程度9位0.5℃10位0.25℃11位0.125℃12位默认0.0625℃4工作电压3v---5.5v2.ds18b20通信半双工串行异步GPIO One-wireGPIO单总线通信通过一根GPIO信号线来进行通信3.ds18b20芯片内部结构1可以通过内部电源给芯片供电264位ROM和单总线接口3存储器控制逻辑模块协调芯片内部各模块工作4暂存器SCRATCHPAD存放温度配置参数5温度传感器采集温度6高温触发阈值与低温触发阈值可配置78位CRC校验生成器生成CRC校验4.上拉电阻上拉电阻是数字电路中非常基础但极其重要的元件用于确保信号线在空闲时有确定的电平状态在双方都释放总线时保持高电平51和ds18b20都释放总线时总线能够呈现高电平释放总线 需要作为数据的接收方任何一方拉低总线整个总线都变低5.dsl8b20读数16位、符号扩展的二进制补码通过单总线DQ串行发出6.读取数据流程1复位2发送0xCC跳过ROM3发送0x44开启温度转换4延时750ms5复位6发送0xCC跳过ROM7发送0xBE读取温度8读取两个字节的温度数据float get_temp(void) { unsigned char temp_low0; unsigned char temp_high0; short temp0; ds18b20_reset(); write_ds18b20(0xCC); write_ds18b20(0x44); Delay1ms(1000); ds18b20_reset(); write_ds18b20(0xCC); write_ds18b20(0xBE); temp_lowread_ds18b20(); temp_highread_ds18b20(); temptemp_high 8; temp | temp_low; return temp * 0.0625; }DS18B20 返回的温度数据是16位的但单片机一次只能读取8位1个字节所以必须分两次读取。要遵循LSB读取顺序// DS18B20 先发送低字节LSB再发送高字节MSB temp_low read_ds18b20(); // 先读低字节 temp_high read_ds18b20(); // 后读高字节 // 如果顺序错了 // temp_high read_ds18b20(); // ❌ 先读高字节 → 数据错乱 // temp_low read_ds18b20();7.时序逻辑1复位时序1.主机将总线拉低480---960us发送复位脉冲告诉从机准备复位2.主机释放总线交出控制权总线呈现高水平3.ds18b20检测到总线为高水平后等待15---60us4.ds18b20将总线拉低60---240us回复响应脉冲向主机应答5.ds18b20释放总线总线呈现高水平告诉主机执行完毕#includereg51.h #includeds18b20.h #includedelay.h #includeuart.h #define DQ_PIN_LOW (P3 ~(17)) #define DQ_PIN_HIGH (P3 |(17)) #define DQ_PIN_CHECK ((P3 (17))!0) // 检测DQ引脚是否为高电平 int ds18b20_reset(void) { int time0; // 主机向ds18b20发送复位脉冲 DQ_PIN_LOW; Delay10us(70); DQ_PIN_HIGH; Delay10us(5); // 等待低电平到来ds18b20拉低总线 while(DQ_PIN_CHECK time30) { Delay10us(1); time; } if (time 30) { uart_sendstr(wait ds18b20_low timeout!\r\n); return -1; } // 等待高电平到来ds18b20释放总线 time 0; while (!DQ_PIN_CHECK time 30) { Delay10us(1); time; } if (time 30) { uart_sendstr(wait ds18b20_high timeout!\r\n); return -2; } return 1; }2写0时间片与写1时间片写0时序1.主机首先将总线拉低小于15us告诉从机开始写数据然后持续拉低60us驱动 0 的低电平到总线上2.ds18b20在30us---60us内进行采样此时总线如果是低水平则ds18b20读03.主机释放总线呈现高水平写1时序1.主机将总线拉低小于15us告诉从机开始写数据然后释放总线呈现高水平驱动“1”电平到总线上从机此时释放总线2.ds18b20在拉高后45us内进行采样此时总线如果是高水平则ds18b20读1void write_ds18b20(unsigned char dat) { int i0; for(i0;i8;i) { if(dat 1) { DQ_PIN_LOW; _nop_(); _nop_(); DQ_PIN_HIGH; Delay10us(5); } else { DQ_PIN_LOW; Delay10us(6); DQ_PIN_HIGH; } dat 1; } }3读0时间片与读1时间片读0时序1.主机拉低总线持续1us释放总线2.ds18b20在主机释放总线后主动拉低总线表示传输03.主机在15us内进行采样此时总线为低电平主机读到0读1时序1.主机拉低总线持续1us释放总线2..ds18b20释放总线总线由上拉电阻拉为高电平3.主机在15us内采样此时总线为高电平主机读到1unsigned char read_ds18b20(void) { unsigned char dat 0; int i 0; for (i 0; i 8; i) { DQ_PIN_LOW; _nop_(); _nop_(); //主机发起读时序告诉 DS18B20 我要读数据了 DQ_PIN_HIGH; _nop_(); _nop_(); _nop_(); //释放总线让 DS18B20 驱动数据线 DS18B20 会在主机释放总线后 - 在 1-3μs 内驱动数据线 - 发送 0拉低总线低电平 - 发送 1释放总线高电平 if (DQ_PIN_CHECK) // 读到ds18b20发送的1 { dat | (1 i); } Delay10us(6); } return dat; }