请教关于DS18B20温度传感器的温度读取 10
我想用P1口的8个引脚每个引脚挂1个DS18B20传感器,然后从P1.0开始顺序读取温度数值,温度读取的程序我有,请大侠们帮助给些端口轮流读取数据的例程,谢谢。我的程序中...
我想用P1口的8个引脚每个引脚挂1个DS18B20传感器,然后从P1.0开始顺序读取温度数值,温度读取的程序我有,请大侠们帮助给些端口轮流读取数据的例程,谢谢。
我的程序中只有如下定义1个端口,请帮助改写:
sbit DQ=P3^7; //ds18b20 端口 展开
我的程序中只有如下定义1个端口,请帮助改写:
sbit DQ=P3^7; //ds18b20 端口 展开
3个回答
展开全部
我这有个现成的C源程序,你参考一下吧!
三通道18B20温度测量数码管显示。-55-+125℃,用1位数码管显示当前通道号,4位数码管显示18B20当前通道温度值(一位小数),负号位与正温度百位1用同一位数码管显示,该位为0不显示,如:0 27.9、1 123.1、2 -35.6。连接方法:三个18B20均接P3.7,P0口(JP10)接8位数码管段码口(J12)。
#include <reg52.h>
#include <intrins.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit ADDR0 = P2^2;
sbit ADDR1 = P2^3;//定义38译码器地址
sbit ADDR2 = P2^4;
uint8 x,h;//定义通道
uint16 ans,ansb[3],f,g,p; //ans各通道温度值,f符号值,g为小数部分,p为1秒的计数变量
code uint8 number[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x40,0x00,0x80};//0,1,2,3,4,5,6,7,8,9,-,灭,小数点
sbit DQ = P3^7; //温度DQ一线输入口
#define nops(); {_nop_(); _nop_(); _nop_(); _nop_();} //定义空指令
uint8 romid[3][8]={//romid二维数组存放每个芯片ROM编号
{0x28,0xA2,0xb4,0x0A,0x00,0x00,0x00,0x83},//0通道
{0x28,0xA2,0xb4,0x0A,0x03,0x00,0x00,0x83},//1通道
{0x28,0xA2,0xb4,0x0A,0x05,0x00,0x00,0x83},//2通道
};
// 定时器初始化
void T1_init(void)
{
TMOD = 0x10; //定时器1工作在方式1(显示扫描定时)
TH1 = 0xfc;
TL1 = 0x67;//T1定时1ms初值
TR1 = 1;//启动T1
}
void delay(uint16 n)
{
while (n--);
}
// 18B20复位函数
void DS18b20_reset(void)
{
bit flag=1;
while (flag)
{
while (flag)
{
DQ = 1;
delay(1);
DQ = 0;
delay(50); // 550us
DQ = 1; //给18B20发出复位信号
delay(6); // 66us
flag = DQ; //检测18B20发出的存在脉冲"0",判断复位是否成功
}
delay(45); //延时500us
flag = ~DQ; //18B20存在脉冲过后变"1",取反后仍为"0"
}
DQ=1;
}
//18B20写1个字节函数 * 向1-WIRE总线上写一个字节
void write_byte(uint8 val)
{
uint8 i;
for (i=0; i<8; i++)
{
DQ = 1;
_nop_();
DQ = 0;
nops(); //4us,11.0592晶振时每个时钟周期约1us
DQ = val & 0x01; //最低位移出
delay(6); //66us
val >>= 1; //右移一位
}
DQ = 1;
delay(1);
}
//18B20读1个字节函数 * 从1-WIRE总线上读取一个字节
uint8 read_byte(void)
{
uint8 i, value=0;
for (i=0; i<8; i++)
{
DQ=1;
_nop_();
value >>= 1;
DQ = 0;
nops(); //4us
DQ = 1;
nops(); //4us
if (DQ)
value|=0x80;
delay(6); //66us
}
DQ=1;
return(value);
}
// 启动温度转换
void start_temp_sensor(void)
{
DS18b20_reset();
write_byte(0xCC); // 发Skip ROM命令
write_byte(0x44); // 发转换命令
}
// 读出温度,多点多个18B20测温主程序:
void read_temp() //读取通道x的温度值
{
uint8 i,temp_data[2];//读出温度暂放
uint16 temp;
for(x=0;x<3;x++)
{
DS18b20_reset(); //复位
write_byte(0x55); // 发匹配ROM命令
for(i=0;i<8;i++)
write_byte(romid[x][i]);//写8位器件ID(从左到右),如:28 A2 b4 0A 03 00 00 83。
write_byte(0xBE);//读RAM命令,共9个字节,只取前两温度字节
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
temp=temp_data[1];//温度高字节
temp=temp<<8;//移到高8位中
temp+=temp_data[0];//温度低字节
ansb[x]=temp;
}
}
// 刷新5位数码管程序
void refresh()
{
static uint8 j = 0,a;//j为数码管位数,a为临时存放红外数据高或低4位
P0 = 0x00;//防止重影
switch(j)
{
case 0: ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;j++;//最右边一位数码管,一位小数
a=g*625/1000;//只取小数点后一位,*625把16进制换算成对应的10进制
P0 = number[a];break;
case 1: ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;j++;
a = ans%10;//取个位
P0 = number[a];break;
case 2: ADDR0 = 1;ADDR1 = 0;ADDR2 = 1;j++;
a = ans/10%10;//取十位
P0 = number[a];break;
case 3: ADDR0 = 0;ADDR1 = 0;ADDR2 = 1;j++;
a = ans/100%10;//取百位
if (f!=0){a=10;}//若为负显示-号
else if (a!=1){a=11;}//若小于100度该位熄灭
P0 = number[a];break;//为1则正常显示
case 4: ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;j++;
a = 12;//个位显示小数点
P0 = number[a];break;
case 5: ADDR0 = 0;ADDR1 = 1;ADDR2 = 0;j=0; //通道显示
P0 = number[h];break;//显示通道号
default: break;
}
}
main()
{
T1_init();//定时器初始化
while(1)
{
if(TF1==1)
{
TF1 = 0;
TH1 = 0xfc;
TL1 = 0x67;
start_temp_sensor();//启动温度转换
p++;
if(p==1000)// 延时约1秒
{
read_temp();//读各通道温度值
switch(h)
{//切换温度显示通道
case 0: ans=ansb[1];h++;break;//1通道
case 1: ans=ansb[2];h++;break;//2通道
case 2: ans=ansb[0];h=0;break;//0通道
default: break;
}
f=ans&0xF800;//取符号位
g = ans&0x000f;//取小数部分
ans>>=4;//去除小数部分
if (f!=0)
{
ans=~ans+1;
}
p=0;
}
refresh();
}
}
}
三通道18B20温度测量数码管显示。-55-+125℃,用1位数码管显示当前通道号,4位数码管显示18B20当前通道温度值(一位小数),负号位与正温度百位1用同一位数码管显示,该位为0不显示,如:0 27.9、1 123.1、2 -35.6。连接方法:三个18B20均接P3.7,P0口(JP10)接8位数码管段码口(J12)。
#include <reg52.h>
#include <intrins.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit ADDR0 = P2^2;
sbit ADDR1 = P2^3;//定义38译码器地址
sbit ADDR2 = P2^4;
uint8 x,h;//定义通道
uint16 ans,ansb[3],f,g,p; //ans各通道温度值,f符号值,g为小数部分,p为1秒的计数变量
code uint8 number[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x40,0x00,0x80};//0,1,2,3,4,5,6,7,8,9,-,灭,小数点
sbit DQ = P3^7; //温度DQ一线输入口
#define nops(); {_nop_(); _nop_(); _nop_(); _nop_();} //定义空指令
uint8 romid[3][8]={//romid二维数组存放每个芯片ROM编号
{0x28,0xA2,0xb4,0x0A,0x00,0x00,0x00,0x83},//0通道
{0x28,0xA2,0xb4,0x0A,0x03,0x00,0x00,0x83},//1通道
{0x28,0xA2,0xb4,0x0A,0x05,0x00,0x00,0x83},//2通道
};
// 定时器初始化
void T1_init(void)
{
TMOD = 0x10; //定时器1工作在方式1(显示扫描定时)
TH1 = 0xfc;
TL1 = 0x67;//T1定时1ms初值
TR1 = 1;//启动T1
}
void delay(uint16 n)
{
while (n--);
}
// 18B20复位函数
void DS18b20_reset(void)
{
bit flag=1;
while (flag)
{
while (flag)
{
DQ = 1;
delay(1);
DQ = 0;
delay(50); // 550us
DQ = 1; //给18B20发出复位信号
delay(6); // 66us
flag = DQ; //检测18B20发出的存在脉冲"0",判断复位是否成功
}
delay(45); //延时500us
flag = ~DQ; //18B20存在脉冲过后变"1",取反后仍为"0"
}
DQ=1;
}
//18B20写1个字节函数 * 向1-WIRE总线上写一个字节
void write_byte(uint8 val)
{
uint8 i;
for (i=0; i<8; i++)
{
DQ = 1;
_nop_();
DQ = 0;
nops(); //4us,11.0592晶振时每个时钟周期约1us
DQ = val & 0x01; //最低位移出
delay(6); //66us
val >>= 1; //右移一位
}
DQ = 1;
delay(1);
}
//18B20读1个字节函数 * 从1-WIRE总线上读取一个字节
uint8 read_byte(void)
{
uint8 i, value=0;
for (i=0; i<8; i++)
{
DQ=1;
_nop_();
value >>= 1;
DQ = 0;
nops(); //4us
DQ = 1;
nops(); //4us
if (DQ)
value|=0x80;
delay(6); //66us
}
DQ=1;
return(value);
}
// 启动温度转换
void start_temp_sensor(void)
{
DS18b20_reset();
write_byte(0xCC); // 发Skip ROM命令
write_byte(0x44); // 发转换命令
}
// 读出温度,多点多个18B20测温主程序:
void read_temp() //读取通道x的温度值
{
uint8 i,temp_data[2];//读出温度暂放
uint16 temp;
for(x=0;x<3;x++)
{
DS18b20_reset(); //复位
write_byte(0x55); // 发匹配ROM命令
for(i=0;i<8;i++)
write_byte(romid[x][i]);//写8位器件ID(从左到右),如:28 A2 b4 0A 03 00 00 83。
write_byte(0xBE);//读RAM命令,共9个字节,只取前两温度字节
temp_data[0]=read_byte(); //温度低8位
temp_data[1]=read_byte(); //温度高8位
temp=temp_data[1];//温度高字节
temp=temp<<8;//移到高8位中
temp+=temp_data[0];//温度低字节
ansb[x]=temp;
}
}
// 刷新5位数码管程序
void refresh()
{
static uint8 j = 0,a;//j为数码管位数,a为临时存放红外数据高或低4位
P0 = 0x00;//防止重影
switch(j)
{
case 0: ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;j++;//最右边一位数码管,一位小数
a=g*625/1000;//只取小数点后一位,*625把16进制换算成对应的10进制
P0 = number[a];break;
case 1: ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;j++;
a = ans%10;//取个位
P0 = number[a];break;
case 2: ADDR0 = 1;ADDR1 = 0;ADDR2 = 1;j++;
a = ans/10%10;//取十位
P0 = number[a];break;
case 3: ADDR0 = 0;ADDR1 = 0;ADDR2 = 1;j++;
a = ans/100%10;//取百位
if (f!=0){a=10;}//若为负显示-号
else if (a!=1){a=11;}//若小于100度该位熄灭
P0 = number[a];break;//为1则正常显示
case 4: ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;j++;
a = 12;//个位显示小数点
P0 = number[a];break;
case 5: ADDR0 = 0;ADDR1 = 1;ADDR2 = 0;j=0; //通道显示
P0 = number[h];break;//显示通道号
default: break;
}
}
main()
{
T1_init();//定时器初始化
while(1)
{
if(TF1==1)
{
TF1 = 0;
TH1 = 0xfc;
TL1 = 0x67;
start_temp_sensor();//启动温度转换
p++;
if(p==1000)// 延时约1秒
{
read_temp();//读各通道温度值
switch(h)
{//切换温度显示通道
case 0: ans=ansb[1];h++;break;//1通道
case 1: ans=ansb[2];h++;break;//2通道
case 2: ans=ansb[0];h=0;break;//0通道
default: break;
}
f=ans&0xF800;//取符号位
g = ans&0x000f;//取小数部分
ans>>=4;//去除小数部分
if (f!=0)
{
ans=~ans+1;
}
p=0;
}
refresh();
}
}
}
展开全部
就先像流水灯一样啊!你的温度读取的程序应该是单个!有种接法,也可以再,一个io上挂8个就不可以用你的那个程序了!
追问
请把具体程序上传谢谢啦
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
我来帮你做做
追问
QQ18302101
加我聊
追答
好的
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询