BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #8626同步于 2010/5/23
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖

单片机测4路ds18b20的程序,有错误,求指导

challenge14
2010/5/23镜像同步2 回复
51单片机 P1.0-P1.4接按键开关,未按下时使各口接地,按下时各口接VCC 4个ds18b20接在P3.4-P3.7各口 P0接4个LED发光管 P2.0-P2.3选择LED 要求按下指定的按键,显示代表的传感器的温度 为了避免多个ds18b20接在一根线上复杂的程序,我选择了把它们并行接在各接口上,然后对p3口整体赋值,进行初始化、测温、读数据等, 整个程序编到现在了没什么进展,求指导。 # include "reg51.h" # include "intrins.h" # define disdata P0 # define discan P2 # define uchar unsigned char # define uint unsigned int uint B20_Error; sbit DIN = P0^7;//led小数点控制 uint h; uchar code ditab[16]= {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09}; uchar code dis_7[12]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf}; uchar code scan_con[4]={0xf7,0xfB,0xFD,0xFE};//列扫描控制字 uchar data temp_data[2]={0x00, 0x00,}; //读出温度暂存 uchar data display[5]={0x00,0x00,0x00,0x00,0x00}; //显示单元数据,共4个数据,1个运算暂存用 /******1us_delay******************************************************/ void Delay_1us(uint t) { for(;t>0;t--); } /******************************显示扫描函数******************************/ scan() { char k; for(k=0;k<4;k++) //4位LED扫描控制 { disdata=dis_7[display[k]]; if(k==1){DIN=0;} //当K=1时,P0^7为低电平显示小数点 discan=scan_con[k]; //列扫描 Delay_1us(30); discan=0xFF; } } void DS18B20_Write_1(void) //总线写1时序控制函数: { P3 = 0x00; //8个DQ 线全部设置为低电平 Delay_1us(10); //延时10us左右 P3 = 0xff; //8个DQ线全部输出高电平 Delay_1us(30); //延时30us左右 } //总线写0时序控制函数: void DS18B20_Write_0(void) { P3 = 0x00; //8个DQ 线全部设置为低电平 Delay_1us(40); //延时 P3 = 0xff; //端口恢复高电平 Delay_1us(1); } unsigned char DS18B20_ReadDQ(void) //总线读取一个数据位时序控制函 { unsigned char DQ_S=0; P3 = 0x00; //8个DQ 线全部设置为低电平 Delay_1us(10); P3 = 0xff; //端口置1,准备读取 Delay_1us(1); //延时待总线准备好数据 DQ_S = P3; //一次性读取8条DQ线的数据状态 P1 = 0xff; //恢复端口电平 Delay_1us(30); //延时 return DQ_S; //返回读取的值 } void DS18B20_Reset(void) //总线复位时序控制函数: { unsigned char Error_Counter=0; P3 = 0x00; //8个DQ 线全部设置为低电平 Delay_1us(500); //保持总线低电平500us P3 = 0xff; Delay_1us(100); if(P3!=0x00) B20_Error = P3; //如检测到DS18B20总线响应了回 复信号,则读取当前8条总线的状态 Delay_1us(50); P3 = 0xff; for(Error_Counter=0;Error_Counter<200;Error_Counter++) { if((P3&(~B20_Error))==(~B20_Error)) break; //如检测到总线的回复信号结 束,则退出循环 Delay_1us(1); } P3 = 0xff; //恢复端口电平 Delay_1us(200); //延时 200us~~~ } //写字节操作函数: void DS18B20_WriteByte(unsigned char Com) { unsigned char i; for(i=0;i<8;i++) { if(Com&0x01) DS18B20_Write_1(); else DS18B20_Write_0(); Com = Com>>1; } } //调用DS18B20_WriteByte函数,连在8个I/O口上的一线制总线上的8个DS18B20器件,将都会接收到同样的一个字节的数据:Com。 unsigned char Read_buf_8ch[16]; //读数据操作函数: //buffer of Read DS18B20 void DS18B20_Read2Byte(void) { unsigned int i; for(i=0;i<16;i++) { Read_buf_8ch[i] = DS18B20_ReadDQ(); } } /*******************************主函数**********************************************************/ main () { disdata=0xff;// 初始化端口 discan=0xff; for(h=0;h<4;h++) //开机显示“8888”scan( {display[h]=8;} for(h=0;h<500;h++)//开机显示“8888 {scan();} } void DS18B20_Conver(void) //启动温度转换控制函数: { DS18B20_Reset(); DS18B20_WriteByte(0xcc); //Skip ROM DS18B20_WriteByte(0x44); //启动测温 } void DS18B20_ReadTemp(void) //读取温度值函数: { DS18B20_Reset(); DS18B20_WriteByte(0xcc); //Skip ROM DS18B20_WriteByte(0xbe); //送入读取数据命令 DS18B20_Read2Byte(); } //调用读取温度值函数后,8个DS18B20器件的测温数据将保存在数组Read_buf_8ch的16个字节单元当中,还有待进行下一步的处理,方可得到对应每个DS18B20器件的测温值。下面介绍简单的处理代码片断: char i,j; unsigned int uiData[8]; unsigned char Mask; //OS the resoult of Temperature for(i=15;i>=0;i--) { Mask = 0x01; for(j=0;j<8;j++) { uiData[j] = uiData[j]<<1; if(Read_buf_8ch&Mask) uiData[j]++; Mask = Mask<<1; } } unsigned f; f=P1; switch(f) { case0:{ temp_data[1]=uiData[0]<<8; temp_data[0]=uiData[0]>>8; work_temp(); scan(); }break; case2:{ temp_data[1]=uiData[1]<<8; temp_data[0]=uiData[1]>>8; work_temp(); scan(); }break; case4:{ temp_data[1]=uiData[2]<<8; temp_data[0]=uiData[2]>>8; work_temp(); scan(); }break; case16:{ temp_data[1]=uiData[3]<<8; temp_data[0]=uiData[3]>>8; work_temp(); scan(); }break; default:{ }break; } } /********************************计算温度子函数**********************************************/ work_temp() { uchar n=0; if(temp_data[1]>127) {temp_data[1]=(255-temp_data[1]);temp_data[0]=(255-temp_data[0]);n=1;} //负温度求补码 display[4]=temp_data[0]&0x0f;display[0]=ditab[display[4]]; display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4) ; display[3]=display[4]/100; display[1]=display[4]%100; display[2]=display[1]/10; display[1]=display[1]%10; if(!display[3]){display[3]=0x0a; if(!display[2]){display[2]=0x0a;}} //最高位为0时不显示 if(n){display[3]=0x0b;} //负温度是最高为显示“-“ }
订阅后,新回复会通过你的通知中心匿名送达。
2 条回复
mc34机器人#1 · 2010/5/23
建议: 不要玩4P,一个一个来。反正ROM够大,不怕代码啰嗦四遍。 1-Wire的读写时间较短,把ReadByte和WriteByte写好点,里面不要再套DS18B20_Write_0、DS18B20_ReadDQ、Delay_1us(1)这些的了。 有空练练1-Wire的寻址吧,光SkipROM不显牛叉。
challenge14机器人#2 · 2010/5/23
【 在 mc34 的大作中提到: 】 : 建议: : 不要玩4P,一个一个来。反正ROM够大,不怕代码啰嗦四遍。 : 1-Wire的读写时间较短,把ReadByte和WriteByte写好点,里面不要再套DS18B20_Write_0、DS18B20_ReadDQ、Delay_1us(1)这些的了。 : ................... 谢了