PIC16f877a 中ds18b20测温所遇到的问题,求高手解疑答惑

631920774 2014-02-18 08:58:04
最近在用PIC16f877a开发板中的ds18b20进行测温,lcd显示,开发板中自带了ds18b20_lcd的程序,拷入单片机后,温度显示及lcd显示正常。
但将手中其他的ds18b20替换下开发板中的ds18b20后,温度显示不正确(未对程序进行改动)。ds18b20都比较新,开发板上的ds18b20是可以方便插拔的,所以插入的ds18b20,接入应该没有错误,难道是这些ds18b20都是坏掉的?所以温度就不能显示了?
请各位高手指点下迷津,不胜感激。
...全文
186 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
631920774 2014-03-04
  • 打赏
  • 举报
回复
是这个原因 但我不明白的是 为什么开发板自带的程序只能使开发板上的那个传感器工作正常,换一个就不正常了,难道不同的传感器对延时的要求不同?
单片机工程师 2014-03-02
  • 打赏
  • 举报
回复
18B20对延时的精确度要求是很高的,是不是这个原因
631920774 2014-02-27
  • 打赏
  • 举报
回复
引用 7 楼 u013785063 的回复:
得执行发现传感器后才可以正常读数据
为啥能发现以前自带的那个传感器,却发现不了替换的呢
631920774 2014-02-27
  • 打赏
  • 举报
回复
为啥能发现板子以前自带的传感器而发现不了替换的呢?
大山无邪 2014-02-26
  • 打赏
  • 举报
回复
得执行发现传感器后才可以正常读数据
631920774 2014-02-22
  • 打赏
  • 举报
回复
温度显示是99.9,如果方便,请你帮我仔细分析下附上的程序,帮我找到原因 不胜感激
y651503148 2014-02-21
  • 打赏
  • 举报
回复
端口方向设置对了吗,IO的第二功能也要注意
lover_blackberry 2014-02-20
  • 打赏
  • 举报
回复
温度显示是多少?
631920774 2014-02-18
  • 打赏
  • 举报
回复
追问: (1)另外一块PIC16f877a开发板上所带的ds18b20_lcd测温显示程序,直接下载入单片机,程序运作正常。但重新编译后,下载,lcd显示正常但温度显示不正常。是由于编译器不同造成的吗?原来是PICCv9.60PL0,现在是PICCv9.81. (2)想将上述问题中提到的程序,改写后,烧入这片单片机,温度依然显示不正常。只对帖子中提到的程序中的ds18b20端口部分进行了改动,LCD程序保留的是追问中提到的这块板子自带的,感觉没有错误,可温度显示就是不正常。 #include <pic.h> __CONFIG(0x3B31); #define uchar unsigned char #define uint unsigned int #define rs RD5 //命令/数据选择 #define rw RD4 //读写口 #define e RD3 //锁存控制 #define Dataport PORTB //数据口定义 unsigned char temp1; unsigned char temp2; //转换后的温度值小数点部分查表 const unsigned char table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9}; uchar dis0[16]={'T','h','e',' ','t','e','m','p',' ','n','o','w',' ','i','s',':',};//LCD第1行 uchar dis[10]={' ',' ',' ',' ',0x00,0x00,'.',0x00,0xeb,'C'}; //LCD第2行 //*********************************************************************************** //延时 //*********************************************************************************** void delay1(uint time) { uint i,j; for(i = 0;i < time; i++) { for(j = 0;j < 30; j++); } } //************************************************************************************************** //向LCD写一命令 //************************************************************************************************** wcode(uchar t) { rs=0; // 写的是命令 rw=0; // 写状态 e=1; //使能 Dataport=t; //写入命令 delay1(20); //等待写入,如果时间太短,会导致液晶无法显示 e=0; //数据的锁定 } //************************************************************************************************** //向LCD写一数据 //************************************************************************************************** wdata(uchar t) { rs=1; // 写的是数据 rw=0; // 写状态 e=1; //使能 Dataport=t; //写入数据 delay1(20); //等待写入,如果时间太短,会导致液晶无法显示 e=0; //数据的锁定 } //************************************************************************************************** //LCD显示 //************************************************************************************************** show() { uchar i; wcode(0x80); //设置第一行显示地址 for(i=0;i<16;i++) //循环16次,写完1行 { wdata(dis0[i]); //写入该行数据 } wcode(0xc6); //设置第一行显示地址 for(i=0;i<10;i++) //循环16次,写完1行 { wdata(dis[i]); //写入该行数据 } } //************************************************************************************************** //LCD 初始化 //************************************************************************************************** InitLCD() { wcode(0x01); //清屏 wcode(0x06); //输入方式控制,增量光标不移位 wcode(0x0e); //显示开关控制 wcode(0x38); //功能设定:设置16x2显示,5x7显示,8位数据接口 } //--------------------------------------- //名称:复位DS18B20函数 //--------------------------------------- unsigned char Reset(void) { unsigned int i; unsigned char k; TRISD7=0; //设置RA4位输出口 RD7=0; //拉低DQ总线开始复位 i=67; //保持DQ低大约870uS,符合不低于480US的要求 while(i>0) //保持DQ低大约870uS,符合不低于480US的要求 i--; //保持DQ低大约870uS,符合不低于480US的要求 TRISD7=1; //设置RA4为输入口,以释放总线等电阻拉高总线 i=6; //大约78uS后,判断是否复位成功 while(i>0) //大约78uS后,判断是否复位成功 i--; //大约78uS后,判断是否复位成功 if(RD7==0) //读出数据并保存 k=0; else k=1; i=31; //维持约400US,符合总读时隙不低于480US的要求 while(i>0) //维持约400US,符合总读时隙不低于480US的要求 i--; //维持约400US,符合总读时隙不低于480US的要求 return k; //k=0为复位成功,k=1为复位失败 } //--------------------------------------- //名称:写字节函数 //--------------------------------------- void WriteByte(unsigned char dat) { unsigned int i; unsigned char j; for(j=0;j<8;j++) { if(dat&0x01) //如果写1 { TRISD7=0; //设置RA4位输出口 RD7=0; //拉低 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 TRISD7=1; //设置RA4为输入口,以释放总线等电阻拉高总线 i=14; //维持约63US,符合不低于60US的要求 while(i>0) //维持约63US,符合不低于60US的要求 i--; //维持约63US,符合不低于60US的要求 } else //如果写0 { TRISD7=0; //设置RA4位输出口 RD7=0; //拉低 i=14; //维持约63US,符合不低于60US的要求 while(i>0) //维持约63US,符合不低于60US的要求 i--; //维持约63US,符合不低于60US的要求 TRISD7=1; //设置RA4为输入口,以释放总线等电阻拉高总线 NOP(); //维持2US,符合大于1US的规范 NOP(); //维持2US,符合大于1US的规范 } dat=dat>>1; //写入字节右移1位 } } //--------------------------------------- //名称:读字节函数 //--------------------------------------- unsigned char ReadByte(void) { unsigned int i; unsigned char j,buf=0; for(j=1;j<=8;j++) //接收8次还原一个字节数据 { buf=buf>>1; //接收前,先将接收缓冲区右移 TRISD7=0; //设置RA4位输出口 RD7=0; //拉低 NOP(); //维持2US,符合大于1US小于15US的规范 NOP(); //维持2US,符合大于1US小于15US的规范 TRISD7=1; //设置RA4为输入口,以释放总线等电阻拉高总线 准备读 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 if(RD7==1) buf|=0x80; //读出1位数据保存于buf中最高位 i=4; //维持约52US,符合总读时隙不低于60US的要求 while(i>0) //维持约52US,符合总读时隙不低于60US的要求 i--; //维持约52US,符合总读时隙不低于60US的要求 } return buf; //退出的同时将接收缓冲区参数返回 } //--------------------------------------- //名称:启动读温度函数 //--------------------------------------- unsigned char Convert(void) { unsigned int i; if(Reset()==0) //如果复位成功 { i=77; //延时约1000US while(i>0) //延时约1000US i--; //延时约1000US WriteByte(0xCC); // 跳过多器件识别 WriteByte(0x44); // 启动温度转换 return 1; } else { return 0; } } //--------------------------------------- //名称:读温度函数 //--------------------------------------- void ReadFlash(void) { unsigned int i; unsigned char Lsb,Msb; if(Reset()==0) { i=77; //延时约1000US while(i>0) //延时约1000US i--; //延时约1000US WriteByte(0xCC); // 跳过多器件识别 WriteByte(0xBE); // 读暂存器 Lsb=ReadByte(); // 低字节 Msb=ReadByte(); // 高字节 temp2=Lsb&0x0f; //LSB的低4位为小数部分 temp1=(Lsb>>4)|(Msb<<4);//LSB的高4位和MSB拼成整数部分 } else { temp1=0; temp2=0; } } //************************************************************************************************** //主函数 //************************************************************************************************** main() { TRISB=0x00; //RB设置为输出 PORTB=0xff; //初始化为高 TRISD=0x80; PORTD=0x00; InitLCD(); //液晶初始化 while(1) { if(Convert()==1) //启动转换 { ReadFlash(); //读取温度 if(temp1>99) temp1=99; if(temp2>15) temp2=0; dis[4]=temp1/10+0x30; dis[5]=temp1%10+0x30; dis[7]=table[temp2&0x0f]+0x30; } show(); //显示温度值 delay1(500); //延时 } }
631920774 2014-02-18
  • 打赏
  • 举报
回复
追问:(1)还有一块PIC16f877A的开发板,其上自带的ds18b20_lcd测温显示程序,直接下载拷入单片机,程序工作正常,一旦重新编译下后,再拷入单片机,程序工作便不正常。是PICC编译器不同的原因么?开发板自带的是用PICC9.60PL0版本编译的,我安装的MAPLAB v8.66,PICC v9.81。 (2)我想将上面问题中提到的程序,只对与端口相关的设置进行对应的改动,复位,读字节,写字节等函数都未改动,对其中的IO口部分进行相应改动。结果还是不出现测温显示结果。至今原因不明,特别费解。 #include <pic.h> __CONFIG(0x3B31); #define uchar unsigned char #define uint unsigned int #define rs RD5 //命令/数据选择 #define rw RD4 //读写口 #define e RD3 //锁存控制 #define Dataport PORTB //数据口定义 unsigned char temp1; unsigned char temp2; //转换后的温度值小数点部分查表 const unsigned char table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9}; uchar dis0[16]={'T','h','e',' ','t','e','m','p',' ','n','o','w',' ','i','s',':',};//LCD第1行 uchar dis[10]={' ',' ',' ',' ',0x00,0x00,'.',0x00,0xeb,'C'}; //LCD第2行 //*********************************************************************************** //延时 //*********************************************************************************** void delay1(uint time) { uint i,j; for(i = 0;i < time; i++) { for(j = 0;j < 30; j++); } } //************************************************************************************************** //向LCD写一命令 //************************************************************************************************** wcode(uchar t) { rs=0; // 写的是命令 rw=0; // 写状态 e=1; //使能 Dataport=t; //写入命令 delay1(20); //等待写入,如果时间太短,会导致液晶无法显示 e=0; //数据的锁定 } //************************************************************************************************** //向LCD写一数据 //************************************************************************************************** wdata(uchar t) { rs=1; // 写的是数据 rw=0; // 写状态 e=1; //使能 Dataport=t; //写入数据 delay1(20); //等待写入,如果时间太短,会导致液晶无法显示 e=0; //数据的锁定 } //************************************************************************************************** //LCD显示 //************************************************************************************************** show() { uchar i; wcode(0x80); //设置第一行显示地址 for(i=0;i<16;i++) //循环16次,写完1行 { wdata(dis0[i]); //写入该行数据 } wcode(0xc6); //设置第一行显示地址 for(i=0;i<10;i++) //循环16次,写完1行 { wdata(dis[i]); //写入该行数据 } } //************************************************************************************************** //LCD 初始化 //************************************************************************************************** InitLCD() { wcode(0x01); //清屏 wcode(0x06); //输入方式控制,增量光标不移位 wcode(0x0e); //显示开关控制 wcode(0x38); //功能设定:设置16x2显示,5x7显示,8位数据接口 } //--------------------------------------- //名称:复位DS18B20函数 //--------------------------------------- unsigned char Reset(void) { unsigned int i; unsigned char k; TRISD7=0; //设置输出口 RD7=0; //拉低DQ总线开始复位 i=67; //保持DQ低大约870uS,符合不低于480US的要求 while(i>0) //保持DQ低大约870uS,符合不低于480US的要求 i--; //保持DQ低大约870uS,符合不低于480US的要求 TRISD7=1; //设置为输入口,以释放总线等电阻拉高总线 i=6; //大约78uS后,判断是否复位成功 while(i>0) //大约78uS后,判断是否复位成功 i--; //大约78uS后,判断是否复位成功 if(RD7==0) //读出数据并保存 k=0; else k=1; i=31; //维持约400US,符合总读时隙不低于480US的要求 while(i>0) //维持约400US,符合总读时隙不低于480US的要求 i--; //维持约400US,符合总读时隙不低于480US的要求 return k; //k=0为复位成功,k=1为复位失败 } //--------------------------------------- //名称:写字节函数 //--------------------------------------- void WriteByte(unsigned char dat) { unsigned int i; unsigned char j; for(j=0;j<8;j++) { if(dat&0x01) //如果写1 { TRISD7=0; //设置RA4位输出口 RD7=0; //拉低 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 TRISD7=1; //设置RA4为输入口,以释放总线等电阻拉高总线 i=14; //维持约63US,符合不低于60US的要求 while(i>0) //维持约63US,符合不低于60US的要求 i--; //维持约63US,符合不低于60US的要求 } else //如果写0 { TRISD7=0; //设置R位输出口 RD7=0; //拉低 i=14; //维持约63US,符合不低于60US的要求 while(i>0) //维持约63US,符合不低于60US的要求 i--; //维持约63US,符合不低于60US的要求 TRISD7=1; //设置为输入口,以释放总线等电阻拉高总线 NOP(); //维持2US,符合大于1US的规范 NOP(); //维持2US,符合大于1US的规范 } dat=dat>>1; //写入字节右移1位 } } //--------------------------------------- //名称:读字节函数 //--------------------------------------- unsigned char ReadByte(void) { unsigned int i; unsigned char j,buf=0; for(j=1;j<=8;j++) //接收8次还原一个字节数据 { buf=buf>>1; //接收前,先将接收缓冲区右移 TRISD7=0; //设置位输出口 RD7=0; //拉低 NOP(); //维持2US,符合大于1US小于15US的规范 NOP(); //维持2US,符合大于1US小于15US的规范 TRISD7=1; //设置为输入口,以释放总线等电阻拉高总线 准备读 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 NOP(); //维持6US,符合大于1US小于15US的规范 if(RD7==1) buf|=0x80; //读出1位数据保存于buf中最高位 i=4; //维持约52US,符合总读时隙不低于60US的要求 while(i>0) //维持约52US,符合总读时隙不低于60US的要求 i--; //维持约52US,符合总读时隙不低于60US的要求 } return buf; //退出的同时将接收缓冲区参数返回 } //--------------------------------------- //名称:启动读温度函数 //--------------------------------------- unsigned char Convert(void) { unsigned int i; if(Reset()==0) //如果复位成功 { i=77; //延时约1000US while(i>0) //延时约1000US i--; //延时约1000US WriteByte(0xCC); // 跳过多器件识别 WriteByte(0x44); // 启动温度转换 return 1; } else { return 0; } } //--------------------------------------- //名称:读温度函数 //--------------------------------------- void ReadFlash(void) { unsigned int i; unsigned char Lsb,Msb; if(Reset()==0) { i=77; //延时约1000US while(i>0) //延时约1000US i--; //延时约1000US WriteByte(0xCC); // 跳过多器件识别 WriteByte(0xBE); // 读暂存器 Lsb=ReadByte(); // 低字节 Msb=ReadByte(); // 高字节 temp2=Lsb&0x0f; //LSB的低4位为小数部分 temp1=(Lsb>>4)|(Msb<<4);//LSB的高4位和MSB拼成整数部分 } else { temp1=0; temp2=0; } } //************************************************************************************************** //主函数 //************************************************************************************************** main() { TRISB=0x00; //RB设置为输出 PORTB=0xff; //初始化为高 TRISD=0x80; PORTD=0x80; InitLCD(); //液晶初始化 while(1) { if(Convert()==1) //启动转换 { ReadFlash(); //读取温度 if(temp1>99) temp1=99; if(temp2>15) temp2=0; dis[4]=temp1/10+0x30; dis[5]=temp1%10+0x30; dis[7]=table[temp2&0x0f]+0x30; } show(); //显示温度值 delay1(500); //延时 } }

27,370

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧