开始引脚为输出状态,引脚置“0”时间>1us,然后置“1”时间大于1us,改引脚方向为输入状态,等待器件反映获取引脚电平,如果是0,mask按位取反相与,如果是1就相或,mask左移一位,data的值就是8次变换的值,再返回给函数。
子函数调用流程:
1、初始化DS18B20
2、延时500ms等待稳定
3、写ROM指令(跳过ROM) 4、写ROM指令,启动温度转换 5、延时500ms等待稳定 6、初始化DS18B20
7、写ROM指令(跳过ROM) 8、写ROM指令(读暂存器) 9、延时500ms等待稳定 10、调用读DS18B20函数
DS18B20的暂存中的温度值是16个位,高5位是符号位,12位为数据位,其中12位中的低4位是小数位。网上大多数资料都是一次读8个位,分两次读出来,然后拼合数据。该程序为了简化后面的处理,一次性读完16个位。如果是正温度值,高5位全部为0;如果是负数温度值,高5位全部为1。
例如读到的数据为二进制1111 1110 1001 0100? ,高位是1,说明该值就是一个负数,printf函数按补码形式来处理,最高位符号位保持不变,其余位取反加1,得到十进制为-364,再乘0.0625等于-22.75度,所以用printf函数输出不需要考虑任何问题,从传感器里面读到什么数直接输出来就行了。
匹配ROM函数:
int MatchingRom(unsigned char com) {
unsigned char r; if(!DS18B20init()) {
DS18B20init(); //初始化DS18B20
delay(100); //延时500毫秒等待稳定
DS18B20Write(0xCC); //写ROM指令(跳过ROM) DS18B20Write(0x44); //写ROM指令,启动温度转换
delay(100); //延时500毫秒等待稳定 DS18B20init(); //初始化DS18B20 delay(100);
DS18B20Write(0x55); //写ROM指令(匹配ROM) switch(com) {
case 1: for(r=0;r<8;r++)DS18B20Write(DS18B20Rom1[r]),LCDwrite(0x80,0);break;
case 2: for(r=0;r<8;r++)DS18B20Write(DS18B20Rom2[r]),LCDwrite(0x90,0);break; case 3: for(r=0;r<8;r++)DS18B20Write(DS18B20Rom3[r]),LCDwrite(0x88,0);break; default: break; }
DS18B20Write(0xBE); //写ROM指令(读暂存器)
tp=DS18B20Read(); //读取DS18B20函数一次性取回所有的16个位 } return tp; }
事先要获取每个器件的ROM系列号,采集温度时一一对应即可,如果ROM系列吨不匹配,温度采集就不成功,缺点是一旦ROM系列号在程序中被固定,器件就不可以更换了,如果需要更换器件,需要在程序中重新录入新器件的ROM系列号。
温度值输出程序:
f1=WriteDataTo12864(1);
if(f1==65535) //如果器件检测失败,得到的值都是1,所以这里判断65535 {
if(fg1==1)LCDwrite(0x01,0),fg1=0;//检测失败刷新一次显示器 printf(\传感器检测失败!\ } else {
if(fg1==0)LCDwrite(0x01,0),fg1=1;//检测失败转到正常刷新一次显示屏 printf(\温度A:\ f1=(f1&0x07FF)>>4;
if((f1>40) && (a1==1)) //+或-40度蜂鸣器报警,a1是控制蜂鸣器开启标记,避免BEEP寄存器被重复赋值造成声音不正常。 {
BEEP_CSR=(0x20|0x23),a1=0; //蜂鸣器输出约3.2KHz信号
printf(\ //如果该传感器报警在后显示一个感叹号。 }
if((f1<40)&&(a1==0)) {
BEEP_CSR=0x00; //低于温度阈值时关闭蜂鸣器 printf(\ \ //清除感叹号 a1=1; } }
先获取器件1温度值赋给f1,f1是一个无符号的整型变量,获取的值都做正数处理。一般情况 ,如果器件检测不成功,获取的16个位的值都是为“1”,即65535,这样程序认为器件连接不正常,就执行第一个判断语句,否则执行else中的语句。如果温度值大于40度开启蜂鸣器报警,并在后温度值后面打印一个“感叹号”显示该器件报警中。第二个判断是将f1的值高5位清零,处理成正数,再右移4移去掉小数位,得到一个正整数温度值,此时无论温度值是负值大于40度还是正值大于40度都会开启蜂鸣器,如果温度值低于40
度时执行第三个判断,关闭蜂鸣器并打印几个空格清除感叹号。该程序必须要在while(1)里面循环执行。
实验效果截图: 本人为了能够得到负温度值,检验程序的正确性,将DS18B20传感器放在水杯里,加适量的水,再放进冰箱冻24个小时结冰后再来测量,真是功夫不负有心人,总算得到一个-8度左右。
第一个测量点“温度A”23度保留两位小数,第二个测量点“温度B”22.7500度,保留四位小数,第三个测量点“温度C”-8.81度,保留二位小数,测试符合实验要求。
拔掉其中一个传感器时,显示“传感器检测失败!”(虽然在冰里面,温度C升起来也很快,10分钟不到升到0.38度,冰并没有完全融化。)
再拔掉第二个传感器,两个都显示“传感器检测失败!”
当三个都拔掉时,显示“无任何器件!”。
插上去第一个后又可以正常显示。
温度B:74.9375度超出40度阈值,报警显示“感叹号”,蜂鸣器鸣叫。
本程序总共3个文件:main.c、12864.c、DS18B20.c
Main.c
#include \
#include \ //标准输入输出库,没有它printf不能用 #include \ //定义布尔类型头文件 //以下是12864外部文件函数声明区 extern void delay(unsigned int count); extern void init();
extern void LCDwrite(unsigned char dat,unsigned char type);