返回信息流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;} //负温度是最高为显示“-“
}
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #8626同步于 2010/5/23
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖
单片机测4路ds18b20的程序,有错误,求指导
challenge14
2010/5/23镜像同步2 回复
订阅后,新回复会通过你的通知中心匿名送达。
2 条回复
建议:
不要玩4P,一个一个来。反正ROM够大,不怕代码啰嗦四遍。
1-Wire的读写时间较短,把ReadByte和WriteByte写好点,里面不要再套DS18B20_Write_0、DS18B20_ReadDQ、Delay_1us(1)这些的了。
有空练练1-Wire的寻址吧,光SkipROM不显牛叉。
【 在 mc34 的大作中提到: 】
: 建议:
: 不要玩4P,一个一个来。反正ROM够大,不怕代码啰嗦四遍。
: 1-Wire的读写时间较短,把ReadByte和WriteByte写好点,里面不要再套DS18B20_Write_0、DS18B20_ReadDQ、Delay_1us(1)这些的了。
: ...................
谢了