标题:
单片机数码管显示ds18b20温度值不正常
[打印本页]
作者:
心灵的尘埃
时间:
2019-3-20 08:31
标题:
单片机数码管显示ds18b20温度值不正常
本帖最后由 心灵的尘埃 于 2019-3-20 08:34 编辑
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit du26=P2^6;//数码管段选
sbit we27=P2^7;//数码管位选
sbit DS=P2^2;//温度传感器
uchar sum;//将温度值送到数码管显示
uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9数码管段表
uchar code smgwei[]={0xfe,0xfd,0xfb}; //1~3数码管位表
void we(uchar z) //位选
{
P0=z;
we27=1;
we27=0;
}
void du(uchar z) //段选
{
P0=z;
du26=1;
du26=0;
}
void display(uchar z) //三个数码管显示
{
static uchar wei;
switch(wei)
{
case 0:we(smgwei[wei]);du(led[z/100]);break;
case 1:we(smgwei[wei]);du(led[z%100/10]|0x80);break;
case 2:we(smgwei[wei]);du(led[z%10]);break;
}
wei++;
if(wei==3)
wei=0;
}
void timer0int() interrupt 1 //定时器,定时5ms
{
TH0=(65535-5000)/256;
TL0=(65535-5000)%256;
display(sum);
}
void delay_us(uchar us) //延时函数
{
while(us--);
}
//单总线初始化时序
bit ds_init()
{
bit i;
DS=1;
_nop_();
DS=0;
delay_us(75);//拉低总线499.45us,总线上的温度传感器将会被全部复位
DS=1;//释放总线
delay_us(4);//延时37.95us,等待温度传感器发回存在信号
i=DS;
delay_us(20);//延时141.95us,读取温度传感器存在的时间
DS=1;
_nop_();
return (i);
}
//写一个字节
void write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS=0;
_nop_(); //产生写时序
DS=dat&0x01;
delay_us(10);//延时76.95us
DS=1;//释放总线准备下一次数据的写入
_nop_();
dat>>=1;
}
}
//读一个字节
uchar read_byte()
{
uchar i,j,dat;
for(i=0;i<8;i++)
{
DS=0;
_nop_();//产生读时序
DS=1;
_nop_();//释放总线
j=DS;
delay_us(10);//76.95us
DS=1;
_nop_();
dat=(j<<7)|(dat>>1);
}
return (dat);
}
void main()
{
uint i;
uchar L,M;
EA=1;
ET0=1;
TR0=1;
TMOD=0X01;
TH0=(65535-5000)/256;
TL0=(65535-5000)%256;
while(1)
{
ds_init();//初始化温度传感器
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0x44);//发送温度转换指令
ds_init();//初始化温度传感器
write_byte(0xcc);//发送跳跃ROM指令
write_byte(0xbe);//读取温度传感器暂存器的值
L=read_byte();
M=read_byte();
i=M;
i<<=8;
i|=L; //将读出来的数据合并存到i中
i=i*0.625*10+0.5;
i=sum;
}
求问题出在哪里,谢谢!!!
}
作者:
zzyix123
时间:
2019-3-20 09:50
没的图纸 怎么帮?
作者:
gj2000
时间:
2019-3-20 13:48
ds18b20是单总线通信,它对时序要求非常高,你可能需要检查你的延迟
作者:
HC6800-ES-V2.0
时间:
2019-3-20 14:38
试试我的程序:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2;
uint temp;
uchar flag1;
sbit dula=P2^6;
sbit wela=P2^7;
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef};
void delay(uint count)
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void dsreset(void)
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void)
{
uint i;
bit dat;
DS=0;i++;
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void)
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1);
}
return(dat);
}
void tmpwritebyte(uchar dat)
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb)
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0;
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void)
{
dsreset();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0x44);
}
uint tmp()
{
float tt;
uchar a,b;
dsreset();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp<<=8;
temp=temp|a;
tt=temp*0.0625;
temp=tt*10+0.5;
return temp;
}
void readrom()
{
uchar sn1,sn2;
dsreset();
delay(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void delay10ms()
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}
void display(uint temp)
{
uchar A1,A2,A2t,A3,ser;
ser=temp/10;
SBUF=ser;
A1=temp/100;
A2t=temp%100;
A2=A2t/10;
A3=A2t%10;
dula=0;
P0=table[A1];
dula=1;
dula=0;
wela=0;
P0=0xfe;
wela=1;
wela=0;
delay(1);
dula=0;
P0=table1[A2];
dula=1;
dula=0;
wela=0;
P0=0xfd;
wela=1;
wela=0;
delay(1);
P0=table[A3];
dula=1;
dula=0;
P0=0xfb;
wela=1;
wela=0;
delay(1);
}
void main()
{
uchar a;
do
{
tmpchange();
for(a=100;a>0;a--)
{ display(tmp());
}
} while(1);
}
作者:
hhh402
时间:
2019-3-20 21:24
数码管显示语句有问题:
case 0:we(smgwei[wei]);du(led[z/100]);break;
case 1:we(smgwei[wei]);du(led[z%100/10]|0x80);break;
case 2:we(smgwei[wei]);du(led[z%10]);break;
作者:
wulin
时间:
2019-3-20 21:49
改为6位数码管显示-55~128度,保留2位小数。
无标题.jpg
(255.81 KB, 下载次数: 27)
下载附件
2019-3-20 21:47 上传
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/************定义端口*************/
sbit du26=P2^6;//数码管段选
sbit we27=P2^7;//数码管位选
sbit DS=P2^2;//温度传感器
/************定义全局变量*************/
uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9数码管段表
uchar code smgwei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //1~6数码管位表
uchar TempData[6]; //存储显示值的全局变量
bit ReadTempFlag; //读时间标志
/*------------------------------------------------
函数声明
------------------------------------------------*/
void WriteOneChar(uchar dat); //写入DS18B20一个字节
uchar ReadOneChar(void); //读取DS18B20一个字节
uint ReadTemperature(void); //读取DS18B20温度值
bit Init_DS18B20(void); //初始化DS18B20
void Display(void); //数码管显示函数
void Init_Timer0(void); //定时器初始化
void DelayUs2x(uchar t); //uS延时函数
void DelayMs(uchar t); //mS延时函数
void we(uchar z); //位选
void du(uchar z); //段选
/*------------------------------------------------
主函数
------------------------------------------------*/
void main()
{
uint temp;
long tempM;
bit negative;//负数标志
uchar TempH,TempL,TempK;
Init_Timer0();
TempData[5]=0x39; //显示C
while(1) //主循环
{
if(ReadTempFlag==1)//定时标志
{
ReadTempFlag=0;
temp=ReadTemperature();//读取温度
if(temp&0x8000)
{
negative=1; //负号标志
temp=~temp; //取反加1
temp +=1;
}
else negative=0; //正数
tempM=temp*0.0625*100; //换算为10进制温度值再放大100倍
TempH=tempM/100; //分解出整数值
TempL=tempM%100; //分解出小数值
TempL=(TempL+TempK)/2+0.5;//小数取两次平均值加四舍五入
TempK=TempL;
if(negative==1)
TempData[0]=0x40;//显示负号
else if(TempH/100==0)//小于100
TempData[0]=0; //百位消隐
else
TempData[0]=led[TempH/100]; //显示百位温度
if((TempH/100==0)&&((TempH%100)/10==0))
TempData[1]=0; //十位消隐
else
TempData[1]=led[(TempH%100)/10]; //显示十位温度
TempData[2]=led[(TempH%100)%10]|0x80;//显示个位温度,带小数点
TempData[3]=led[TempL/10]; //显示温度小数1位
TempData[4]=led[TempL%10]; //显示温度小数2位
}
}
}
void we(uchar z) //位选
{
P0=z;
we27=1;
we27=0;
}
void du(uchar z) //段选
{
P0=z;
du26=1;
du26=0;
}
/*------------------------------------------------
6位动态数码管显示函数
------------------------------------------------*/
void Display() //6个数码管显示
{
static uchar wei;
switch(wei)
{
case 0:we(smgwei[wei]);du(TempData[wei]);break;
case 1:we(smgwei[wei]);du(TempData[wei]);break;
case 2:we(smgwei[wei]);du(TempData[wei]);break;
case 3:we(smgwei[wei]);du(TempData[wei]);break;
case 4:we(smgwei[wei]);du(TempData[wei]);break;
case 5:we(smgwei[wei]);du(TempData[wei]);break;
}
wei++;
wei%=6;
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01;
TH0=(65536-2000)/256; //给定初值
TL0=(65536-2000)%256;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
static uint num;
TH0=(65536-2000)/256; //重新赋值 2ms
TL0=(65536-2000)%256;
Display(); // 调用数码管扫描
num++;
if(num>=250) //500ms
{
num=0;
ReadTempFlag=1; //读标志位置1
}
}
/*------------------------------------------------
2uS延时函数
------------------------------------------------*/
void DelayUs2x(uchar t)
{
while(--t);
}
/*------------------------------------------------
1mS延时函数
------------------------------------------------*/
void DelayMs(uchar t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
18b20初始化
------------------------------------------------*/
bit Init_DS18B20(void)
{
bit dat=0;
DS = 1; //DS复位
DelayUs2x(5); //稍做延时
DS = 0; //单片机将DS拉低
DelayUs2x(200); //精确延时 大于 480us 小于960us
DelayUs2x(200);
DS = 1; //拉高总线
DelayUs2x(50); //15~60us 后 接收60-240us的存在脉冲
dat=DS; //如果x=0则初始化成功, x=1则初始化失败
DelayUs2x(25); //稍作延时返回
return dat;
}
/*------------------------------------------------
读取一个字节
------------------------------------------------*/
uchar ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DS = 0; // 给脉冲信号
dat>>=1;
DS = 1; // 给脉冲信号
if(DS)
dat|=0x80;
DelayUs2x(25);
}
return(dat);
}
/*------------------------------------------------
写入一个字节
------------------------------------------------*/
void WriteOneChar(uchar dat)
{
uchar i=0;
for(i=8; i>0; i--)
{
DS = 0;
DS = dat&0x01;
DelayUs2x(25);
DS = 1;
dat>>=1;
}
DelayUs2x(25);
}
/*------------------------------------------------
读取温度
------------------------------------------------*/
uint ReadTemperature(void)
{
uchar a=0;
uint b=0;
uint t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
DelayMs(10);
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar(); //低位
b=ReadOneChar(); //高位
b<<=8;
t=a+b;
return(t);
}
复制代码
作者:
采蘑菇的小宋
时间:
2019-3-21 13:53
如果是实际电路的话,DS18B20温度转换最少要93.57ms(9位),最多要750ms(12位),之后才能读取到正确的数据,protues仿真就不需要
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1