【微控制器】時鐘及溫度的顯示
阿新 • • 發佈:2019-01-01
回頭看我所寫的文章,基本都是軟體方面的,是個典型的“欺軟怕硬”的人。然而,在最開始的時候,我學習的是硬體。在前面文章《我的2013–一起從心開始》一文中寫道,我在大一暑假的時候開始了微控制器的學習,在大二、大三期間做過些小東西。剛進入程式設計師的領域的時候,顯然是微控制器帶我入了門。下面我將寫寫用微控制器做過的一些東西,權當紀念。
本文介紹我大一暑假學完微控制器後,在大二上學期為參加學校星火盃而完成的作品(最終沒有參加比賽)。這個電子製作是關於用微控制器顯示時間的作品,其功能就用微控制器控制LCD、LED來顯示時間和溫度。
功能描述
- 顯示精確度為0.1攝氏度的溫度(低於0攝氏度和高於100攝氏度響鈴)
- 液晶時鐘,斷電後仍然繼續走動,每月誤差不到一分鐘,無電源可工作10年左右,區分平年和閏年;
- 指標式時鐘(黃燈為時針,紅色為分針,最小誤差5分鐘,整點報時)與考試計時器(計時2兩小時)
電子元器件
- 2個微控制器最小系統 (微控制器型號為STC89C52)
- 雙色發光二級管
- 液晶顯示屏
- 按鍵
- DS12C887時鐘晶片
- DS18b20溫度感測器
- 蜂鳴器(整點報時)
- LED數碼管(顯示溫度)
作品展示圖
- 由於所有電路都是由杜邦線連線,所以存在接觸不良,導致有時不能正常顯示,於是就沒有參賽,下圖為雙色二極體的顯示。
- 下圖為用1602液晶顯示日期和時間
- 下圖為用數碼管來顯示溫度
- 下圖為作品的佈線,簡直是亂成一團,要是用PCB就好了。
附錄:程式碼實現
對於硬體來說,給程式碼不給管腳圖沒啥意義,不過由於年代久遠,我已經找不到當初設計的電路圖了。但仍然給出程式碼圖,希望能起到一點點的參考作用。
//--------------------------------溫度顯示程式 第一個晶片------------------------------------------------------------------//
#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbit ds=P2^2;
unsigned int te;
unsigned char code tabledu[]=
{
0x3f0x060x5b0x4f
0x660x6d0x7d0x07
0x7f0x6f0x770x7c
0x390x5e0x790x71
};
unsigned char code tabledu1[]=
{
0xbf0x860xdb0xcf
0xe60xed0xfd0x87
0xff0xef0xf70xfc
0x390x5e0x790x71
};
unsigned char code tablewe[]=
{
0xfe0xfd0xfb0xf70xef0xdf
};
void delayxms(unsigned int x)
{
unsigned int ij;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
void delayx2us(unsigned char t)
{
while(--t);
}
void dsreset() // 復位
{
ds=1;
_nop_();
ds=0;
delayx2us(200);//注意時間
ds=1;
delayx2us(20);
}
void writetemp(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
ds = 0;
ds = dat&0x01;
delayx2us(25);
ds = 1;
dat>>=1;
}
delayx2us(25);
}
unsigned char readtemp(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
ds = 0; // 給脈衝訊號
dat>>=1;
ds = 1; // 給脈衝訊號
if(ds)
dat|=0x80;
delayx2us(25);
}
return(dat);
}
uint temp()
{
uint ab;
dsreset();
delayxms(1);
writetemp(0xcc);
writetemp(0x44);
delayxms(1);
dsreset();
delayxms(1);
writetemp(0xcc);
writetemp(0xbe);
delayx2us(50);
a=readtemp();
b=readtemp();
a=a*10;
te=b*160+a/16;
return te;
}
void disp(long int num)
{
uchar cde;
c=num/100;
d=num%100/10;
e=num%10;
P0=tabledu[c];
P1=0xfe;
delayxms(6);
P0=tabledu1[d];
P1=0xfd;
delayxms(6);
P0=tabledu[e];
P1=0xfb;
delayxms(6);
P0=0xcc;
P1=0xf7;
delayxms(2);
}
void main()
{
while(1)
{
disp(temp());
if((temp()>=1000)||(temp()<=0))
beep=0;
else
beep=1;
}
//--------------------------------時鐘顯示程式 第二個晶片------------------------------------------------------------------//
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
//流水燈鎖存器
sbit wela1=P2^0;//1
sbit wela2=P2^1;//2
sbit wela3=P2^2;//1
sbit wela4=P2^3;//2
//蜂鳴器
sbit beep=P2^4;
//按鍵
sbit key1=P2^5;//功能選擇鍵
sbit key2=P2^6;//+(時間、日期加)
sbit key3=P2^7;//-(時間、日期減)
sbit key4=P3^7;//模式鍵(平時或考試)
//液晶介面
sbit lcden=P3^4;
sbit lcdrs=P3^5;
sbit lcdwr=P3^6;
//ds12c887介面
sbit dscs=P1^6;
sbit dsas=P1^7;
sbit dsrw=P3^0;
sbit dsds=P3^1;
sbit dsirq=P3^3;
//定義變數
uchar hour minseccountriweekyuenianj;
//uchar counthcountmcountycountkloop1;
uchar code table1[]=" - - ";
uchar code table2[]=" : : ";
uchar code table3[]="SUNMONTUEWEDTHUFRISAT";
//延遲函式
void delayxms(unsigned int x)
{
unsigned int ij;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
//--------------------1602液晶函式----------------------------------
//液晶寫命令
void write_com(unsigned char com)
{
lcdrs=0;
P0=com;
delayxms(5);
lcden=1;
delayxms(5);
lcden=0;
}
//液晶寫資料
void write_data(unsigned char date)
{
lcdrs=1;
P0=date;
delayxms(5);
lcden=1;
delayxms(5);
lcden=0;
}
//液晶初始化
void lcdinit()
{
lcdwr=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
// 液晶顯示
void disp()
{
uchar i;
write_com(0x80);
for(i=0;i<15;i++)
{
write_data(table1[i]);
delayxms(5);
}
write_com(0x80+0x40);
for(i=0;i<12;i++)
{
write_data(table2[i]);
delayxms(5);
}
}
//寫時間
void write_sfm(uchar addressuchar shu)
{
uchar shige;
shi=shu/10;
ge=shu%10;
write_com(0x80+0x40+address);
write_data(0x30+shi);
write_data(0x30+ge);
}
//寫日曆
void write_calendar(uchar addressuchar shu)
{
uchar shige;
shi=shu/10;
ge=shu%10;
write_com(0x80+address);
write_data(0x30+shi);
write_data(0x30+ge);
}
//-------------------------DS12C887程式----------------------------
//寫時鐘
void write_ds(uchar adduchar date)
{
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsrw=0;
P0=date;
dsrw=1;
dsas=1;
dscs=1;
}
//讀時鐘
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
ds_date=P0;
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}
//寫星期
void write_week(uchar date)
{
write_com(0x80+12);
write_data(table3[3*date]);
write_data(table3[3*date+1]);
write_data(table3[3*date+2]);
}
//鍵盤檢測
void keyscan() //鍵盤檢測 key1 為功能鍵 key2為加 key3為減 :時間與日期的改變
{
if(key1==0)
{
delayxms(10);
if(key1==0)
{
while(!key1);
count++;
if(count==1)
{
write_com(0x80+0x40+11);
write_com(0x0f);
}
if(count==2)
{
write_com(0x80+0x40+8);
write_com(0x0f);
}
if(count==3)
{
write_com(0x80+0x40+5);
write_com(0x0f);
}
if(count==4)
{
write_com(0x80+13);
write_com(0x0f);
}
if(count==7)
{
write_com(0x80+10);
write_com(0x0f);
}
if(count==6)
{
write_com(0x80+7);
write_com(0x0f);
}
if(count==5)
{
write_com(0x80+4);
write_com(0x0f);
}
if(count==8)
{
count=0;
write_com(0x0c);
write_ds(0sec);
write_ds(2min);
write_ds(4hour);
}
}
}
if(key2==0)
{
delayxms(10);
if(key2==0)
{
while(!key2);
if(count==1)
{
sec++;
if(sec==60)
sec=0;
write_ds(0sec);
write_sfm(10sec);
write_com(0x80+0x40+11);
}
if(count==2)
{
min++;
if(min==60)
min=0;
write_ds(2min);
write_sfm(7min);
write_com(0x80+0x40+8);
}
if(count==3)
{
hour++;
if(hour==24)
hour=0;
write_ds(4hour);
write_sfm(4hour);
write_com(0x80+0x40+5);
}
if(count==4)
{
week++;
if(week==7)
week=0;
write_week(week);
write_ds(6week);
}
if(count==5)
{
nian++;
if(nian==100)
nian=0;
write_ds(9nian);
write_calendar(3nian);
write_com(0x80+4);
}
if(count==6)
{
yue++;
if(yue==13)
yue=1;
write_ds(8yue);
write_calendar(6yue);
write_com(0x80+7);
}
if(count==7) // 判斷閏年
{
ri++;
week++;
if(nian%4==0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==31)
ri=1;
}
else if(yue==2)
{
if(ri==30)
ri=1;
}
else
{
if(ri==32)
ri=1;
}
}
if(nian%4!=0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==31)
ri=1;
}
else if(yue==2)
{
if(ri>=29)
ri=1;
}
else
{
if(ri==32)
ri=1;
}
}
write_ds(7ri);
write_calendar(9ri);
write_com(0x80+10);
delayxms(2);
if(week==7)
week=0;
write_week(week);
write_ds(6week);
}
}
}
if(key3==0)
{
delayxms(10);
if(key3==0)
{
while(!key3);
if(count==1)
{
if(sec==0)
sec=59;
else
sec--;
write_ds(0sec);
write_sfm(10sec);
write_com(0x80+0x40+11);
}
if(count==2)
{
if(min==0)
min=59;
else
min--;
write_ds(2min);
write_sfm(7min);
write_com(0x80+0x40+8);
}
if(count==3)
{
if(hour==0)
hour=23;
else
hour--;
write_ds(4hour);
write_sfm(4hour);
write_com(0x80+0x40+5);
}
if(count==5)
{
if(nian==0)
nian=99;
else
nian--;
write_ds(9nian);
write_calendar(3nian);
write_com(0x80+4);
}
if(count==6)
{
if(yue==1)
yue=12;
else
yue--;
write_ds(8yue);
write_calendar(6yue);
write_com(0x80+7);
}
if(count==7) // 判斷閏年
{
ri--;
week--;
if(nian%4==0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==0)
ri=30;
}
else if(yue==2)
{
if(ri==0)
ri=29;
}
else
{
if(ri==0)
ri=31;
}
}
if(nian%4!=0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==0)
ri=30;
}
else if(yue==2)
{
if(ri==0)
ri=28;
}
else
{
if(ri==0)
ri=31;
}
}
write_ds(7ri);
write_calendar(9ri);
write_com(0x80+10);
delayxms(2);
if(week==-1)
week=7;
write_week(week);
write_ds(6week);
}
}
}
}
//----------------初始化---------------------------------//
void init()
{
lcdinit();
disp();
week=0;
nian=11;
yue=9;
ri=1;
}
//---------------------------流水燈-----------------------------------//
void lampinit()
{
P1=0xff;
wela1=1;
wela2=1;
wela3=1;
wela3=1;
wela1=0;
wela2=0;
wela3=0;
wela4=0;
}
//----------------時鐘用黃燈顯示程式-------------------------------//
void clock()
{
if((hour==1)&&(hour==13))
{
P1=0xfd;
wela3=1;
wela3=0;
}
if((hour==2)&&(hour==14))
{
P1=0xfb;
wela3=1;
wela3=0;
}
if((hour==3)&&(hour==15))
{
P1=0xf7;
wela3=1;
wela3=0;
}
if((hour==4)&&(hour==16))
{
P1=0xef;
wela3=1;
wela3=0;
}
if((hour==5)&&(hour==17))
{
P1=0xdf;
wela3=1;
wela3=0;
}
if((hour==6)&&(hour==18))
{
P1=0xfe;
wela4=1;
wela4=0;
}
if((hour==7)&&(hour==19))
{
P1=0xfd;
wela4=1;
wela4=0;
}
if((hour==8)&&(hour==20))
{
P1=0xfb;
wela4=1;
wela4=0;
}
if((hour==9)&&(hour=21))
{
P1=0xf7;
wela4=1;
wela4=0;
}
if((hour==10)&&(hour==22))
{
P1=0xef;
wela4=1;
wela4=0;
}
if((hour==11)&&(hour==23))
{
P1=0xdf;
wela4=1;
wela4=0;
}
if((hour==12)&&(hour==0))
{
P1=0xfe;
wela3=1;
wela3=0;
}
if(min<5)
{
if((hour!=12)&&(hour!=24))
{
P1=0xfe;
wela1=1;
wela1=0;
}
}
//----------------分鐘用紅燈顯示------------------------//
if((min>=5)&&(min<10))
{
if((hour!=13)&&(hour!=1))
{
P1=0xfd;
wela1=1;
wela1=0;
}
}
if((min>=10)&&(min<15))
{
if((hour!=14)&&(hour!=2))
{
P1=0xfb;
wela1=1;
wela1=0;
}
}
if((min>=15)&&(min<20))
{
if((hour!=15)&&(hour!=3))
{
P1=0xf7;
wela1=1;
wela1=0;
}
}
if((min>=20)&&(min<25))
{
if((hour!=16)&&(hour!=4))
{
P1=0xef;
wela1=1;
wela1=0;
}
}
if((min>=25)&&(min<30))
{
if((hour!=17)&&(hour!=5))
{
P1=0xdf;
wela1=1;
wela1=0;
}
}
if((min>=30)&&(min<35))
{
if((hour!=18)&&(hour!=6))
{
P1=0xfe;
wela2=1;
wela2=0;
}
}
if((min>=35)&&(min<40))
{
if((hour!=19)&&(hour!=7))
{
P1=0xfd;
wela2=1;
wela2=0;
}
}
if((min>=40)&&(min<45))
{
if((hour!=20)&&(hour!=8))
{
P1=0xfb;
wela2=1;
wela2=0;
}
}
if((min>=45)&&(min<50))
{
if((hour!=21)&&(hour!=9))
{
P1=0xf7;
wela2=1;
wela2=0;
}
}
if((min>=50)&&(min<55))
{
if((hour!=22)&&(hour!=10))
{
P1=0xef;
wela2=1;
wela2=0;
}
}
if(min>=55)
{
if((hour!=23)&&(hour!=11))
{
P1=0xdf;
wela2=1;
wela2=0;
}
}
}
//---------------考試倒計時模式-----------------------//
void test()
{
uchar hour1min1min2shi;
hour1=hour+2;
if(hour==24)
hour1=0;
if(hour==25)
hour1=1;
min1=min+20;
if(min1>=60)
{
min1=min1-60;
hour1=hour1+1;
if(hour1==24)
hour1=0;
}
shi=min1/10;
min1=shi*10;
if((min==min1)&&(sec==0))
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfe;
wela3=1;
wela3=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfc;
wela1=1;
wela1=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf8;
wela1=1;
wela1=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf0;
wela1=1;
wela1=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xe0;
wela1=1;
wela1=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xc0;
wela1=1;
wela1=0;
}
//-------------------------------------------------//
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfe;
wela2=1;
wela2=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfc;
wela2=1;
wela2=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf8;
wela2=1;
wela2=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf0;
wela2=1;
wela2=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xe0;
wela2=1;
wela2=0;
}
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xc0;
wela2=1;
wela2=0;
}
//----------------------時間到後開始響鈴------------------------------------------//
if(min==min2)
{
P1=0;
wela1=1;
wela1=0;
beep=0;
delayxms(1000);
beep=1;
delayxms(1000);
beep=0;
delayxms(1000);
beep=1;
beep=0;
delayxms(1000);
beep=1;
delayxms(1000);
beep=0;
delayxms(6000);
delayxms(6000);
beep=1;
lampinit();
}
}
//-----------------主函式--------------------------------------//
void main()
{
init();
while(1)
{
keyscan();
if(count==0)
{
sec=read_ds(0);
min=read_ds(2);
hour=read_ds(4);
week=read_ds(6);
nian=read_ds(9);
yue=read_ds(8);
ri=read_ds(7);
write_sfm(10sec);
write_sfm(7min);
write_sfm(4hour);
write_week(week);
write_calendar(3nian);
write_calendar(6yue);
write_calendar(9ri);
write_calendar(120);
}
}
}