標(biāo)題:
單片機數(shù)碼管顯示ds18b20溫度值不正常
[打印本頁]
作者:
心靈的塵埃
時間:
2019-3-20 08:31
標(biāo)題:
單片機數(shù)碼管顯示ds18b20溫度值不正常
本帖最后由 心靈的塵埃 于 2019-3-20 08:34 編輯
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit du26=P2^6;//數(shù)碼管段選
sbit we27=P2^7;//數(shù)碼管位選
sbit DS=P2^2;//溫度傳感器
uchar sum;//將溫度值送到數(shù)碼管顯示
uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9數(shù)碼管段表
uchar code smgwei[]={0xfe,0xfd,0xfb}; //1~3數(shù)碼管位表
void we(uchar z) //位選
{
P0=z;
we27=1;
we27=0;
}
void du(uchar z) //段選
{
P0=z;
du26=1;
du26=0;
}
void display(uchar z) //三個數(shù)碼管顯示
{
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) //延時函數(shù)
{
while(us--);
}
//單總線初始化時序
bit ds_init()
{
bit i;
DS=1;
_nop_();
DS=0;
delay_us(75);//拉低總線499.45us,總線上的溫度傳感器將會被全部復(fù)位
DS=1;//釋放總線
delay_us(4);//延時37.95us,等待溫度傳感器發(fā)回存在信號
i=DS;
delay_us(20);//延時141.95us,讀取溫度傳感器存在的時間
DS=1;
_nop_();
return (i);
}
//寫一個字節(jié)
void write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS=0;
_nop_(); //產(chǎn)生寫時序
DS=dat&0x01;
delay_us(10);//延時76.95us
DS=1;//釋放總線準(zhǔn)備下一次數(shù)據(jù)的寫入
_nop_();
dat>>=1;
}
}
//讀一個字節(jié)
uchar read_byte()
{
uchar i,j,dat;
for(i=0;i<8;i++)
{
DS=0;
_nop_();//產(chǎn)生讀時序
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);//發(fā)送跳躍ROM指令
write_byte(0x44);//發(fā)送溫度轉(zhuǎn)換指令
ds_init();//初始化溫度傳感器
write_byte(0xcc);//發(fā)送跳躍ROM指令
write_byte(0xbe);//讀取溫度傳感器暫存器的值
L=read_byte();
M=read_byte();
i=M;
i<<=8;
i|=L; //將讀出來的數(shù)據(jù)合并存到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
數(shù)碼管顯示語句有問題:
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位數(shù)碼管顯示-55~128度,保留2位小數(shù)。
無標(biāo)題.jpg
(255.81 KB, 下載次數(shù): 27)
下載附件
2019-3-20 21:47 上傳
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/************定義端口*************/
sbit du26=P2^6;//數(shù)碼管段選
sbit we27=P2^7;//數(shù)碼管位選
sbit DS=P2^2;//溫度傳感器
/************定義全局變量*************/
uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9數(shù)碼管段表
uchar code smgwei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //1~6數(shù)碼管位表
uchar TempData[6]; //存儲顯示值的全局變量
bit ReadTempFlag; //讀時間標(biāo)志
/*------------------------------------------------
函數(shù)聲明
------------------------------------------------*/
void WriteOneChar(uchar dat); //寫入DS18B20一個字節(jié)
uchar ReadOneChar(void); //讀取DS18B20一個字節(jié)
uint ReadTemperature(void); //讀取DS18B20溫度值
bit Init_DS18B20(void); //初始化DS18B20
void Display(void); //數(shù)碼管顯示函數(shù)
void Init_Timer0(void); //定時器初始化
void DelayUs2x(uchar t); //uS延時函數(shù)
void DelayMs(uchar t); //mS延時函數(shù)
void we(uchar z); //位選
void du(uchar z); //段選
/*------------------------------------------------
主函數(shù)
------------------------------------------------*/
void main()
{
uint temp;
long tempM;
bit negative;//負(fù)數(shù)標(biāo)志
uchar TempH,TempL,TempK;
Init_Timer0();
TempData[5]=0x39; //顯示C
while(1) //主循環(huán)
{
if(ReadTempFlag==1)//定時標(biāo)志
{
ReadTempFlag=0;
temp=ReadTemperature();//讀取溫度
if(temp&0x8000)
{
negative=1; //負(fù)號標(biāo)志
temp=~temp; //取反加1
temp +=1;
}
else negative=0; //正數(shù)
tempM=temp*0.0625*100; //換算為10進(jìn)制溫度值再放大100倍
TempH=tempM/100; //分解出整數(shù)值
TempL=tempM%100; //分解出小數(shù)值
TempL=(TempL+TempK)/2+0.5;//小數(shù)取兩次平均值加四舍五入
TempK=TempL;
if(negative==1)
TempData[0]=0x40;//顯示負(fù)號
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;//顯示個位溫度,帶小數(shù)點
TempData[3]=led[TempL/10]; //顯示溫度小數(shù)1位
TempData[4]=led[TempL%10]; //顯示溫度小數(shù)2位
}
}
}
void we(uchar z) //位選
{
P0=z;
we27=1;
we27=0;
}
void du(uchar z) //段選
{
P0=z;
du26=1;
du26=0;
}
/*------------------------------------------------
6位動態(tài)數(shù)碼管顯示函數(shù)
------------------------------------------------*/
void Display() //6個數(shù)碼管顯示
{
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; //定時器開關(guān)打開
}
/*------------------------------------------------
定時器中斷子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
static uint num;
TH0=(65536-2000)/256; //重新賦值 2ms
TL0=(65536-2000)%256;
Display(); // 調(diào)用數(shù)碼管掃描
num++;
if(num>=250) //500ms
{
num=0;
ReadTempFlag=1; //讀標(biāo)志位置1
}
}
/*------------------------------------------------
2uS延時函數(shù)
------------------------------------------------*/
void DelayUs2x(uchar t)
{
while(--t);
}
/*------------------------------------------------
1mS延時函數(shù)
------------------------------------------------*/
void DelayMs(uchar t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
18b20初始化
------------------------------------------------*/
bit Init_DS18B20(void)
{
bit dat=0;
DS = 1; //DS復(fù)位
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;
}
/*------------------------------------------------
讀取一個字節(jié)
------------------------------------------------*/
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);
}
/*------------------------------------------------
寫入一個字節(jié)
------------------------------------------------*/
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); // 啟動溫度轉(zhuǎn)換
DelayMs(10);
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度
a=ReadOneChar(); //低位
b=ReadOneChar(); //高位
b<<=8;
t=a+b;
return(t);
}
復(fù)制代碼
作者:
采蘑菇的小宋
時間:
2019-3-21 13:53
如果是實際電路的話,DS18B20溫度轉(zhuǎn)換最少要93.57ms(9位),最多要750ms(12位),之后才能讀取到正確的數(shù)據(jù),protues仿真就不需要
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1