首先申明,這篇博客是用作記錄本人實訓內容的,代碼我個人一字一字碼的,就上網查了下數字溫度傳感器DS18B20的處理方法,基本都是個人完成的,
在這里吐槽下,本人辛辛苦苦碼的代碼,最后實訓分數還沒那些抄的人高,吐槽下老師- -,好了接下來說正事
萬年歷
- 一、實驗內容
- 二、電路仿真圖
- 三、代碼
- 四、效果圖
- 1.開始
- 2.日期
- 3.溫度
- 四、最后
一、實驗內容
設計定時器每50ms中斷一次,在中斷服務程式中,對中斷次數進行計數,50ms計數20次,就是1秒,然后再對秒計數得到分的值,對分計數得到小時的值,分別將各值送到相應的段地址埠和位地址埠,通過數碼管顯示結果,達到電子時鐘的計數效果,在計數的基礎上,程式增加了按鍵程式,對電子時鐘進行可調(對秒/分/時進行加1,此功能的增加使電子時鐘功能更強、更實用,同理對日期也可以日/月/年進行加1,
a. 用AT89S51單片機的定時/計數器T0產生一秒的定時時間,作為秒計數時間,
b. 當一秒產生時,秒計數加1,
c. 開機時,顯示00-00-00,并開始連續計時,計時滿23-59-59時,回傳00-00-00重新開始計時,
在以上設計基礎上,在單片機的P1.0-P1.3口分別接入4個按鍵:
d. P1.0控制“秒”的調整,每按一次加1秒
e. P1.1控制“分”的調整,每按一次加1分
f. P1.2控制“時”的調整,每按一次加1時
g. P1.3用作功能選擇鍵,在程式運行程序中如果按下功能選擇鍵,則在年月日、時分秒和顯示溫度之間進行功能切換,
用AT89C52控制DS18B20,讀取資料,并對DS18B20轉換后的資料進行處理,最后在數碼管上顯示DS18B20測出的溫度,
a.使用6位數碼管顯示測得的溫度
b.最高位為符號位,如果溫度值為正,不顯示,如果溫度為負,則顯示負號
c.第2—4位顯示溫度值的整數部分,并在第4位資料上顯示小數點
d.第5位顯示小數部分
e.6,7位顯示攝氏度符號“C”,
二、電路仿真圖
這里我用的是ISIS Professional仿真,寫代碼用到是keil4


這是圖中所用到的元器件
三、代碼
#include <reg51.h> //頭檔案
unsigned char bitcode[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; //選擇LED位碼
unsigned char code
pcode[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; //無小數點0~9
ncode[] = {0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef}; //有小數點0~9
unsigned char riqi[] = {2, 0, 2, 1, 0, 2, 0, 8};//在這里改日期
unsigned int key1=1,key2=1,key3=1,key4=1,year=0,month=0,day=0,d;
unsigned int bitcnt;
unsigned int flag = 0;
unsigned int s = 0,m = 0,h = 0;
unsigned int n = 0;
unsigned int bitcnt;
unsigned char Tools[] = {0x63, 0x39,0x40};
sbit p10 = P1 ^ 0;
sbit p11 = P1 ^ 1;
sbit p12 = P1 ^ 2;
sbit p13 = P1 ^ 3;
sbit DQ = P2 ^ 4;
void DATE(); //宣告函式
void changed();
void runnian();
void delay();
void delay2(int z);
void time_init();
void button();
void jishu();
void delay3(unsigned int j);
void Init_DS18B20(void);
char ReadOneChar(void);
void WriteOneChar(unsigned char dat);
int ReadTemperature(void);
void display_tempmain(unsigned int i);
void delay()
{
int i, j;
for (i = 0; i <= 10; i++)
for (j = 0; j <= 20; j++);
}
void DATE() //日期
{
for (bitcnt = 0; bitcnt < 8; bitcnt++)
{
P3 = bitcode[bitcnt];
if (bitcnt == 3 || bitcnt == 5)
P0 = ncode[riqi[bitcnt]];
else
P0 = pcode[riqi[bitcnt]];
delay();
runnian();
if(p10==0) //判斷天數按鍵是否按下
key1=0;
if (p10==1&&key1==0)
{
riqi[7]+=1;
key1=1;
if (riqi[7]==10)
{
riqi[7]=0;
riqi[6]+=1;
}
if(day==d)
{
riqi[6]=0;
riqi[7]=1;
riqi[5]+=1;
}
if(month==12&&day==31)
{
riqi[5]=1;
riqi[4]=0;
riqi[3]+=1;
}
}
if(p11==0) //判斷月份按鍵是否按下
key2=0;
if(p11==1&&key2==0)
{
riqi[5]+=1;
key3=1;
if(riqi[5]==10)
{riqi[4]+=1;
riqi[5]=0;}
if(month==12)
{
riqi[5]=1;
riqi[4]=0;
riqi[3]+=1;
}
key2=1;
}
if(p12==0) //判斷年份按鍵是否按下
key3=0;
if(p12==1&&key3==0)
{
riqi[3]+=1;
key3=1;
if(riqi[3]==10)
{
riqi[3]=0;
riqi[2]+=1;
}
}
}
}
void runnian(void) //判斷是否為閏年
{
year=riqi[0]*1000+riqi[1]*100+riqi[2]*10+riqi[3];
month=riqi[4]*10+riqi[5];
day=riqi[6]*10+riqi[7];
if ((year%4==0)&&(year%100!=0)||(year%400==0))
{
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==10)||(month==12))
{d=31;}
if((month==4)||(month==6)||(month==9)||(month==11))
{d=30;}
if(month==2)
{d=28;}
}
else
{
if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==10)||(month==12))
{d=31;}
if((month==4)||(month==6)||(month==9)||(month==11))
{d=30;}
if(month==2)
{d=29;}
}
}
void delay2(int z)
{
int x, y;
for (x = z; x > 0; x--)
for (y = 50; y > 0; y--)
;
}
void time_init() //定時器初始化
{
TMOD = 0x01;
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
EA = 1;
TR0 = 1;
ET0 = 1;
}
void button()
{
if (p10==0) //判斷s按鍵是否按下
key1=0;
if (p10==1&&key1==0)
{
s++;
key1=1;
}
if (p11==0) //判斷m按鍵是否按下
key2=0;
if (p11==1&&key2==0)
{
m++;
key2=1;
}
if (p12==0) //判斷h按鍵是否按下
key3=0;
if (p12==1&&key3==0)
{h++;
key3=1;}
}
void jishu()
{
for (bitcnt = 0; bitcnt < 8; bitcnt++)
{
P3 = bitcode[bitcnt];
button();
if(P3==0xfe)
P0=pcode[h/10]; //取小時的十位
else if(P3==0xfd)
P0=pcode[h%10]; //取小時的個位
else if(P3==0xfb)
P0=0x40; //取段碼顯示為-
else if(P3==0xf7) //取分的十位
P0=pcode[m/10];
else if(P3==0xef) //取分的個位
P0=pcode[m%10];
else if(P3==0xdf)
P0=0x40; //取段碼顯示為-
else if(P3==0xbf) //取秒的十位
P0=pcode[s/10] ;
else if(P3==0x7f) //取秒的個位
P0=pcode[s%10];
delay();
}
}
void delay3(unsigned int j)
{
while (j--)
;
}
void Init_DS18B20(void)
{
unsigned char x = 0;
DQ = 1;
delay3(8);
DQ = 0;
delay3(80);
DQ = 1;
delay3(14);
x = DQ;
delay3(20);
}
char ReadOneChar(void)
{
unsigned char i = 0;
unsigned char dat = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if (DQ)
dat |= 0x80;
delay3(4);
}
return (dat);
}
void WriteOneChar(unsigned char dat)
{
unsigned char i = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
DQ = dat & 0x01;
delay3(5);
DQ = 1;
dat >>= 1;
}
delay3(4);
}
int ReadTemperature(void) //讀取溫度
{
unsigned char a = 0;
unsigned char b = 0;
unsigned int t = 0;
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0x44);
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0xBE);
a = ReadOneChar();
b = ReadOneChar();
t = b << 8;
t = t | a;
return (t);
}
void display_tempmain(unsigned int i) //顯示溫度
{
float temp;
unsigned char xiaoshu;
unsigned int zhengshu;
if ((0xf000 & i) == 0xf000)
{
i = ~i + 1;
P0 = 0x00;
if((zhengshu % 100 / 10)==0)
{
P0 = Tools[2];
P3 = 0xfb;
}
else
{
P0 = Tools[2];
P3 = 0xfd;
}
delay3(500);
}
temp = (0x000f & i) * 10.0 * 0.0625;
xiaoshu = temp;
zhengshu = i >> 4;
P0 = 0x00;
if((zhengshu / 100)==0) //溫度百位
{
delay3(500);
P3 = 0xff;
}
else
{
P0 = pcode[zhengshu / 100];
P3 = 0xfd;
}
if((zhengshu / 100)==0&&(zhengshu % 100 / 10)==0) //溫度十位
{
delay3(500);
P3 = 0xff;
}
else
{
P0 = pcode[zhengshu % 100 / 10];
P3 = 0xfb;
}
delay3(500);
P0 = 0x00;
P0 = pcode[zhengshu % 100 % 10] | ~0x7f; //溫度個位
P3 = 0xf7;
delay3(500);
P0 = 0x00;
P0 = pcode[xiaoshu]; //小數
P3 = 0xef;
delay3(500);
P0 = 0x00;
P0 = Tools[0]; //度
P3 = 0xdf;
delay3(500);
P0 = 0x00;
P0 = Tools[1]; //攝氏度C
P3 = 0xbf;
delay3(500);
P3 = 0xff;
}
void changed() //判斷按鍵是否按下
{
if (flag == 0)
{
while (flag == 0)
{
jishu();
if (p13 == 0) //判斷轉換鍵是否按下
key4=0;
if (p13==1&&key4==0)
{
flag++;
key4=1;
}
}
}
else if (flag == 1)
while (flag == 1)
{
DATE();
if (p13 == 0) //判斷轉換鍵是否按下
key4=0;
if (p13==1&&key4==0)
{
flag++;
key4=1;
}
}
else if (flag == 2)
{
unsigned int temp;
while (flag == 2) //涓誨驚鐜?
{
temp = ReadTemperature();
display_tempmain(temp);
if (p13 == 0) //判斷轉換鍵是否按下
key4=0;
if (p13==1&&key4==0)
{
flag=0;
key4=1;
}
}
}
}
void main(void)
{
time_init();
while (1)
{
changed();
}
}
void timer() interrupt 1 //1s中斷
{
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
n++;
if (n == 20)
{
n = 0;
s++;
if (s == 60)//
{
s = 0;
m++;
}
if (m == 60)
{
m = 0;
h++;
}
if (h == 24)
{
h = 0;
}
}
}
四、效果圖
如果你圖畫對,代碼沒問題,hex檔案也沒問題,程式運行應該如下圖所示:
1.開始
從00-00-00開始計時,充當計時器


這是按鍵的功能,比如在剛開始的計時器狀態,第一個(從上到下)就+1s,第二個+1m,第三個+1h,第四個就是切換led顯示狀態,按下就切換到日期,再按下就切換到溫度,在按下就又切換到顯示計時器的狀態,簡單的說就是(計時-日期-溫度)回圈.
注意:按下切換功能按鍵后計時不會停止,而是在后臺繼續計時,
2.日期

注意:這里日期是代碼里改的固定的,不會隨系統日期的,同樣按左邊的按鍵可以實作+天,+月,+年
3.溫度

注意:溫度是讀取DS18B20的資料來顯示的,也就是改變DS18B20的溫度,就可以改變顯示的溫度,所以左邊的按鍵對這個是無效的,只有第四個切換功能的按鍵有用,按一下就切換到計時的去了
如下圖改成4攝氏度(按那兩個紅色按鈕調溫度):

四、最后
希望能對你有用!!
當然還有最重要的事,麻煩各位大佬給個三連,畢竟碼字不容易,
如果三連不行就點個贊吧(卑微),

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/258090.html
標籤:其他
