使用单片机 DS18B20 温度传感器 C 语言程序(参考) 1) / DS18B20 测温程序 硬件A T89S52 1单线 ds18b20 接 P2.2 二七段数码管接 P0 口 3使用外部电源给 ds18b20 供电,寄生电源未使用 软件Kei uVision 3 * */ include “reg52.h“ include “intrins.h“ define uchar unsigned char define uint unsigned int sbit dsP22; sbit dulaP26; sbit welaP27; uchar flag ; uint temp; 参数 temp 必须声明为 int 型 uchar code table0 x3f,0 x06,0 x5b,0 x4f,0 x66,0 x6d,0 x7d, 0 x07,0 x7f,0 x6f,0 x77,0 x7c,0 x39,0 x5e,0 x79,0 x71; 不带小数点数字编码 uchar code table10 xbf,0 x86,0 xdb,0 xcf,0 xe6,0 xed,0 xfd, 0 x87,0 xff,0 xef; 小数点数字编码 /*延时函数*/ void TempDelay uchar us whileus; void delayuint count 延时子函数 uint i; whilecount i200; whilei0 i; count; /*串口初始化,波特率 9600,方式 1 */ void init_com TMOD0 x20; 设置定时器 1 为模式 2 TH10 xfd; 波特率设置为安装初值 TL10 xfd; TR11; 启动定时器 SM00; 设置串口通信模式 SM11; REN1; 串口允许接收数据 PCON0; 波特率不倍频 SMOD0; 波特率不倍频 EA1; 开总中断 ES1; 开串行中断 /*显示数字管 */ void displayuint temp uchar bai,shi,ge; baitemp/100; shitemp100/10; getemp10010; dula0; P0tablebai; 显示百位 dula1; 从 0 到 一、有上升沿,解锁,显示相应段 dula0; 从 1 到 0 再次锁存 wela0; P00 xfe; wela1; wela0; delay1; 延时约 2ms P0table1shi; 显示十位 dula1; dula0; P00 xfd; wela1; wela0; delay1; P0tablege; 显示个位 dula1; dula0; P00 xfb; wela1; wela0; delay1; /* 时序初始化,读时序,写时序。 所有时间序列都以主机单片机为主设备,单总 从设备中使用线设备。 所有时间序列都以主机单片机为主设备,单总 从设备中使用线路设备。每个命令和数据传输 从主机主动启动写时序开始,如果要求单总 编写命令后,主机需要启动线设备返回数据 读时序完成数据接收。数据和命令的传输都很低 位在先。 初始时序复位脉冲 存在脉冲 读;1 或 0 时序 写;1 或 0 时序 只有脉冲信号的存在 18b20(从机)发出的,其 它的信号都是由主机发出的。 脉冲让主机(总线)知道从机(18)b20)已 准备好了。 / /* 初始检测总线控制器发出的复位脉冲 和 ds18b20 任何通信都应该从初始化开始 初始化序列包括由总线控制器发出的复位脉冲 以及随后从机发出的存在脉冲。 脉冲存在初始化复位脉冲 具体操作 发出总线控制器(TX)复位脉冲 (一个至少保持 480s 低电平信号) ,然后释放总 线, 进入接收状态(RX) 。单线总线由 5K 上拉电阻拉到高电平。探测到 I/O 上升沿后引脚 DS1820 等待 1560s,然后发出存在脉冲(一个脉冲) 60240s 低电平信号) 。 具体看 18b20 单线复位脉冲时序和 1-wire presence detect “的时序图 -*/ void ds_resetvoid ds1; _nop_; 1us ds0; TempDelay80; 当总线停留在低电平以上时 480us,所以装置会在总线上复位,这里延 时约 530us 总 线路停留在低电平以上 480s,总线上的所有器件都将被复位。 _nop_; ds1; 产生复位脉冲后,微处理器释放总线,使总线空闲 18b20 中文资料 TempDelay5; 释放总线后,从机 18b20 通过降低总线来指示它是否在线, 有时间检测高电平 1560us, 所以延时 44us, 进行 1-wire presence detect (单 线存检测) _nop_; _nop_; _nop_; ifds0 flag1; detect 18b20 success else flag0; detect 18b20 fail TempDelay20; 低电平时间6024us,所以延时约 140us _nop_; _nop_; ds1; 再次拉高总线,使总线处于空闲状态 控制器对原理解释 18B20 操作流程 1 , 复位 首先,我们必须正确 DS18B20 芯片复位 , 由控制器复位 ( 单片机 ) 给 DS18B20 单总线至少 480uS 低电平信号 。 当 18B20 收到此复位信号后,它将会 在 1560uS 后回发一个芯片的存在脉冲。 当 18B20 收到此复位信号后,它将会 在 1560uS 芯片存在脉冲后回发。 2 , 存在脉冲 复位电平结束后 , 控制器应该拉高数据单总线 , 以便于 在 1560uS 接收存在脉冲后,存在脉冲为一个 60240uS 低电平信号。到目前为止,双方已经通信了 达成基本协议后,控制器和 18B20 间数据通信 。 /* 读写时间间隙 DS1820 数据读写是通过时间间隙处理的 确认信息交换的位置和命令字。 */ bit ds_read_bitvoid 读一位 bit dat; ds0; 单片机(微处理器)将总线拉低 _nop_; 读取间隙从微处理器开始,至少拉下总线 1us ds1; 拉低总线后,释放总线,让从机 18b20 接管总线,输出有效数据 _nop_; _nop_; 小延时,读取 18b20 上的数据 ,因为从 ds18b20 上输出的数据 读时间间隙的下降沿出现 15us 内有效 datds; 主机读从机 18b20 输出的数据在读时间隙的下降边缘出现15us 内 有效 TempDelay10; 所有读时间间隙都必须必须 60120us,这里 77us returndat; 返回有效数据 原理图 8 读时间间隙控制时采样时间应更准确 , 阅读时间间隙也必须先由主 机产生至少 1uS 低电平表示阅读时间的开始。然后在总线释放后 15uS 中 DS18B20 如果发现总线为高电平,将发送内部数据位 “ 1 ” , 如果总线为低电平,则表示读取数据 “ 0 ” 。然后在总线释放后 15uS 中 DS18B20 如果发现总线为高电平,将发送内部数据位 “ 1 ” , 如果总线为低电平,则表示读取数据 “ 0 ” 。在读取每个人之前,由控制器添加一个 起始信号。注意如图 8 所示,必须从阅读间隙开始 15uS 内读数据位 确保正确的通信。 以通信为准 8 位 “ 0 ” 或 “ 1 ” 为一个字节 , 字节的读写始于高位 , 即 A7 到 A0. 字节的读写顺序也如图所示 2 自上而下。 uchar ds_read_bytevoid 读一字节 uchar value,i,j; value0; 别忘了给初值 fori0;i1; 这一步的解释是一个 word 文档里面 returnvalue; 返回字节数据 void ds_write_byteuchar dat 写一个字节 uchar i; bit onebit; 不要忘记,onebit 是一位 fori1;i1; 从低到高传输数据 ifonebit 写 1 ds0; _nop_; _nop_; 看时序图,至少延时 1us,写时间间隙才产生 ds1; 写时间间隙开始后 15s 允许数据线拉到高电平 TempDelay5; 所有的写作时间必须至少持续 60us else 写 0 ds0; TempDelay8; 主机生成一个写作 0 时间间隙必须将数据线拉到低电平,保持至少 60s,这里 64us ds1; _nop_; _nop_; /* 控制主机(单片机) 18B20 完成温度转换需要三个步骤 每次读写前都要 18B20 复位后发送 一条 ROM 最后发送指令 RAM 指令,这样才能正确 DS18b20 进行 预定操作。 复位要求主 CPU 下拉数据线 500us,然后释放,当 ds18B20 接收信号后等待 1660us,后发出 60240us 低脉冲存在, 主 CPU 收到此信号表示复位成功 / /* 温度转换 先初始化 然后跳过 ROM跳过 64 位 ROM 地址,直接向 ds18B20 温度转换命令适用于单片工作 发送温度转换命令 */ void tem_change ds_reset; delay1; 约 2ms ds_write_byte0 xcc;单线情况下,跳跃 ROM 指令 ds_write_byte0 x44.温度转换指令 /* 获得温度 */ uint get_temperature float wendu; uchar a,b; ds_reset; delay1; 约 2ms ds_write_byte0 xcc; ds_write_byte0 xbe;发送阅读温度命令 ads_read_byte;读出温度低 8 位 bds_read_byte;读书温度高 8 位 tempb; temp0;a display get_temperature;