#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
/*DS18B20*/
sbit k=P1^4;
void Delay1ms(uint y)
{
uint x;
for(;y>0;y--)
{
for(x=110;x>0;x--);
}
}
uchar Ds18b20Init()
{
uchar i=0;
k=0;
i=70;
while(i--); //642us
k=1;
i=0;
while(k)
{
Delay1ms(1);
i++;
if(i>5)
{
return 0;
}
}
return 1;
}
void Ds18b20WriteByte(uchar dat)
{
uchar i,j;
for(j=0;j<8;j++)
{
k=0;
i++;
k=dat&0x01;
i=6;
while(i--)//68um
k=1;
dat>>=1;//移位
}
}
uchar Bs18b20ReadByte()
{
uint i,j;
uchar bi,byte;
for(j=0;j<8;j--)
{
k=0;
i++;
k=1;
i++;
i++;
bi=k;
byte=(byte>>1)|(bi<<7);
i=4;
while(i--);
}
return byte;
}
void Ds18b20changeTemp()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc) ;
Ds18b20WriteByte(0x44);//溫度轉換
}
void Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc) ;
Ds18b20WriteByte(0xbe);
}
int Ds18b20ReadTemp()
{
int temp=0;
uchar th,tl;
Ds18b20changeTemp();
Ds18b20ReadTempCom();
tl=Bs18b20ReadByte();
th=Bs18b20ReadByte();
temp=th;
temp<<=8;
temp|=tl;
return temp;
}
/*數碼管*/
uchar code SMGduan[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//顯示0~9
uchar DisplayDate[8];
void datepros(int temp)
{
float tp;
if(temp<0)
{
DisplayDate[0]=0x40;
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*10+0.5;
}
else
{
DisplayDate[0]=0x00;
tp=temp;
temp=tp*0.0625*10+0.5;
}
DisplayDate[1]=SMGduan[temp/100];
DisplayDate[2]=SMGduan[temp%100/10]|0x80;
DisplayDate[3]=SMGduan[temp%100%10];
}
sbit fuhao=P1^0;
sbit shi=P1^1;
sbit ge=P1^2;
sbit xiaoshu=P1^3;
void delay(uint i)
{
while(i--);
}
void DigDisplay()
{
uint i;
for(i=0;i<4;i++)
{
if(i==0) {fuhao=0;shi=1;ge=1;xiaoshu=1; }
if(i==1) {fuhao=1;shi=0;ge=1;xiaoshu=1;}
if(i==2) {fuhao=1;shi=1;ge=0;xiaoshu=1;}
if(i==3) {fuhao=1;shi=1;ge=1;xiaoshu=0; }
}
P2=DisplayDate[i];//發送段碼
delay(100);//間隔一段時間掃描
P2=0x00;//消隱
}
void main()
{
while(1)
{
datepros(Ds18b20ReadTemp());
DigDisplay();
}
}


uj5u.com熱心網友回復:
先把datepros(Ds18b20ReadTemp());注釋掉再把
DisplayDate[1]=1;
DisplayDate[1]=2;
DisplayDate[2]=3;
DisplayDate[3]=4;
運行測驗數碼管顯示程式
uj5u.com熱心網友回復:
數碼管沒有問題,用別的程式都可以顯示數字,那可以請你幫我看下這個程式嗎?我在CSDN下載的,但是不懂dula和wela什么意思,按照我的電路圖怎么改麻煩幫我看下好嗎/*
該段代碼實作了DS18B20的溫度測量,晶振11.0592M,難點在于延時程式。
該程式前面的寫位、寫位元組,讀位、讀位元組代碼可以作為單總線通信的標準代碼,本身也是借用的標準代碼
*/
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
sbit wela=P2^7;
sbit DQ=P2^2;
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 Init_Com(void) //串口初始化,該程式中并未用到串口
{
TMOD = 0x20;
PCON = 0x00;
SCON = 0x50;
TH1 = 0xFd;
TL1 = 0xFd;
TR1 = 1;
}
*/
void delay(int cnt) //延時
{
int i;
for(i=0;i<cnt;i++);
}
unsigned char reset(void) //復位信號
{
unsigned char presence;
DQ=0; //將 DQ 信號線拉低
delay(29); //使 DQ 信號線的低電平狀態持續480us
DQ=1; //釋放總線,使之回傳到高電平狀態
delay(3); //等待從設備拉低總線
presence=DQ; //保存當前總線狀態
delay(25); //等待總線初始化結束
return presence; //回傳是否有從設備將總線拉低
}
void write_bit(char BitValue) //寫位
{
DQ=0; //拉低 DQ 信號,啟動寫時隙
if(BitValue=https://bbs.csdn.net/topics/=1)
{
delay(5);
DQ=1; //如果寫的時隙是1,則 DQ 為高電平
}
else
{
delay(5);
}
delay(50); //等待寫時隙結束
DQ=1;
}
void write_byte(WriteByteValue) //寫位元組
{
unsigned char i;
unsigned char WriteTemp;
for(i=0;i<8;i++) //連續寫 8 個資料位
{
WriteTemp = WriteByteValue >> i; //將要寫的資料 按位元組 右移 i 位
WriteTemp = WriteTemp & 0x01; //取出資料的位元組的第 i 位
write_bit(WriteTemp); //向總線寫一個資料位
}
delay(50); //等待時隙結束
}
unsigned char read_bit(void) //讀位
{
unsigned char i;
DQ=0; //拉低 DQ 信號線,啟動讀時隙
DQ=1; //釋放 DQ 信號線,等待從機回傳資料位
for(i=0;i<3;i++); //產生 15us 延時,準備采樣總線信號
return DQ; //回傳總線狀態
}
unsigned char read_byte(void) //讀位元組
{ unsigned char i;
unsigned char ReadByteValue=https://bbs.csdn.net/topics/0; //將回傳值初始化為 0
for(i=0;i<8;i++) //連續讀取 8 個資料位
{
if(read_bit()) //如果當前讀取的資料位是 1
{
ReadByteValue = ReadByteValue | (0x01<<i); //將回傳位元組對應的資料位置 1
}
}
delay(6); //等待時隙結束
return ReadByteValue;
}
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; //個位
P0=0x7e; //經發現,必須先置P0,然后打開位選通,否則的話其余沒選通的數碼管會
wela=1; //有微光,因為先位選通的話,P0因為一瞬間尚未賦值,所以其余數碼管會有極短
wela=0; //的導通時間
dula=1;
P0=table[A1]; //顯示百位
dula=0;
delay(40);
P0=0x7d;
wela=1;
wela=0;
dula=1;
P0=table1[A2]; //顯示十位
dula=0;
delay(40);
P0=0x7b;
wela=1;
wela=0;
dula=1;
P0=table[A3]; //顯示個位
dula=0;
delay(40);
}
/* //這一段代碼跟上面一段代碼實作的功能一模一樣
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=0x7e;
wela=1;
wela=0;
delay(1); //delay()函式另外撰寫的,不是本程式的delay()
dula=0;
P0=table1[A2]; //顯示十位
dula=1;
dula=0;
wela=0;
P0=0x7d;
wela=1;
wela=0;
delay(1);
P0=table[A3]; //顯示個位
dula=1;
dula=0;
P0=0x7b;
wela=1;
wela=0;
delay(1);
}
*/
uint tmp() //讀取并求溫度值,該值不帶小數點,小數點由顯示的時候在編碼上加工,比如temp值為295
{ //實際溫度則為29.5,所以應該在十位顯示碼上加上小數點來編碼
float tt;
uchar a,b;
uint temp;
reset();
delay(100);
write_byte(0xcc);
write_byte(0xbe);
a=read_byte(); //低8位
b=read_byte(); //高8位
temp=b;
temp<<=8; //two byte compose a int variable
temp=temp|a;
tt=temp*0.0625; //溫度值的計算公式,這里并沒有考慮溫度為負數的情況
//temp=tt*10+0.5;
temp=tt;
return temp;
}
void tmpchange(void) //DS18B20 開始轉換
{
reset(); //實際沒有用到回傳值
delay(100);
write_byte(0xcc); // address all drivers on bus
write_byte(0x44); // initiates a single temperature conversion
}
void main()
{
uchar a;
// Init_Com();
tmpchange();
a=tmp();
while(1) //數碼管要在while大回圈中點亮,不然的話最后的結果三個數碼管亮度不一
display(a); //前兩個很暗,最后一個很亮
}
uj5u.com熱心網友回復:
你這是病急亂投醫,我有自己寫的1820也有別人讓修改的,能運行的代碼,很早自己寫的,現在也懶得去修改,運行一下正常.


uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
這里代碼是接2個溫度傳感器的,你和單個溫度傳感器,代碼自己去修改.uj5u.com熱心網友回復:
不好意思我剛剛學單片機不是很懂,我改了一下但是為什么不行呢,顯示出來是0088uj5u.com熱心網友回復:
#include<reg52.h>
#include <intrins.h>
sbit DS=P1^4;
#define GPIO_SMG P2
int t;
void YanShi(unsigned int j)
{
while(--j);
}
bit ChuShiHua_DS18B20()
{
bit i;
DS=1;
_nop_();
DS=0;
YanShi(75);
DS=1;
YanShi(4);
i=DS;
YanShi(20);
DS=1;
_nop_();
return i;
}
void DS18B20_Xie_ZiJie(unsigned int ZiJie)
{
unsigned char i=8;
do
{
DS=0;
_nop_();
DS=ZiJie&0x01;
YanShi(10);
DS=1;
_nop_();
ZiJie>>=1;
}while(--i);
}
unsigned int DS18B20_Du_ZiJie()
{
unsigned char i=8,j;
unsigned int ZiJie;
do
{
DS=0;
_nop_();
j=DS;
YanShi(10);
DS=1;
_nop_();
ZiJie=(j<<7)|(ZiJie>>1);
}while(--i);
return(ZiJie);
}
void DS18B20_Xie(bit X)
{
ChuShiHua_DS18B20();
DS18B20_Xie_ZiJie(0xcc);
DS18B20_Xie_ZiJie(X?0xbe:0x44);
}
unsigned int DS18B20_WenDu()
{
unsigned int L,M,i;
DS18B20_Xie(0);
DS18B20_Xie(1);
L=DS18B20_Du_ZiJie();
M=DS18B20_Du_ZiJie();
i=M;
i<<=8;
i|=L;
if(i>2048)
{
i=~i;++i;
i=i*0.0625*100+0.5;
t=0;
}
else
{
i=i*0.0625*100+0.5;
t=1;
}
return i;
}
sbit A1=P1^0;
sbit B1=P1^1;
sbit C1=P1^2;
sbit D1=P1^3;
unsigned char shu[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char shu1[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
void delay(unsigned int i)
{
while(i--);
}
void display(unsigned int temp)
{
if(t==0)
{
A1=0;B1=1;C1=1;D1=1;
GPIO_SMG=0x40;
delay(100);
}
else
{
A1=0;B1=1;C1=1;D1=1;
GPIO_SMG=shu[temp/10000];
delay(100);
}
A1=1;B1=0;C1=1;D1=1;
GPIO_SMG=shu[temp%10000/1000];delay(100);
A1=1;B1=1;C1=0;D1=1;
GPIO_SMG=shu1[temp%10000%1000/100];delay(100);
A1=1;B1=1;C1=1;D1=0;
GPIO_SMG=shu[temp%10000%1000%100];delay(100);
}
int main()
{
while(1)
{
display(DS18B20_WenDu());
}
}
uj5u.com熱心網友回復:
你先display(1234);運行拍照來看uj5u.com熱心網友回復:
很好的學習態度,我看了一下你發的電路圖數碼管驅動三極管那樣連接,就算測溫程式是好的,也很可能因數碼管電路使得蛋騙雞運行出問題而無法正常作業,因此,你先把4位數碼管除錯好。假如4位數碼管無法正常顯示4位數字如1234的話,那就要修改驅動數碼管的電路圖中的三極管的接法了,有2種方案可行,1更換三極管的極性,2使用復合管即達林頓管加大基極到IO口的電阻值。uj5u.com熱心網友回復:
ds18b20時序圖按你的電路寫的數碼管

void main()
{
Xz=0;DS18B20_Xie_ZhiJie(31); /*設定第二個18B20*/
W0=4321;
while(1)
{
Shu_Ma_Xian_Shi(0, W0%10, 43, 1, 1, 222);
Shu_Ma_Xian_Shi(1, W0/10%10, 43, 1, 1, 222);
Shu_Ma_Xian_Shi(2, W0/100%10, 28, 1, 1, 222);
Shu_Ma_Xian_Shi(3, W0/1000%10, 43, 1, 1, 222);
// W0=DS18B20_WenDu();
}
}
按你的埠做的仿真
uj5u.com熱心網友回復:
ds18b20是靠時間隙的長度來分辨0/1的,因此時間間歇準確要求比較高,建議使用一個單片機的定時器做延時,以符合規范的要求uj5u.com熱心網友回復:
按照這個還是顯示8888
uj5u.com熱心網友回復:
我用同樣的測溫代碼,新設計符合你定義的IO口的電路,這都有截圖的.uj5u.com熱心網友回復:
我現在也找不出來有什么問題,主要是我不懂。謝謝你啦!uj5u.com熱心網友回復:
測溫讀取每秒一次,使用中斷.uj5u.com熱心網友回復:
這個截圖就是中斷每秒去讀取的運行結果uj5u.com熱心網友回復:
我買了一個報警器送了代碼我刪了一部分就只有顯示溫度了可以用,但是沒有用中段也可以,不知道為什么可以一直重繪溫度。void main() //主函式
{
while(temp==850);
{ //呼叫讀溫度函式,這里是一個判斷,因為溫度傳感器,第一次讀資料會出來一個850,不是溫度資料,所以濾掉這一個資料
temp=Temper();
}
//因為DS18B20上電之后會讀出來850,但不是溫度值,所以等待讀出溫度值
delay(1000);
display(); //短延時穩定資料,也可不要
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/62798.html
標籤:單片機/工控
