實(shí)現(xiàn)定時(shí)功能,比較方便的方法是利用單片機(jī)內(nèi)部的定時(shí)器/計(jì)數(shù)器。也可以采用下面的三種方法
1.軟件定時(shí):軟件定時(shí)不占用硬件資源,但是占用了cpu的利用率
2.采用時(shí)基電路定時(shí):列采用555電路,外接必要的元器件(電阻和電容),即可構(gòu)成硬件定時(shí)電路,但在硬件連接好以后,定時(shí)的范圍不能由軟件進(jìn)行控制和修改,即不可編程
3.采用可編程的芯片定時(shí):這種定時(shí)芯片的定時(shí)值及定時(shí)范圍很容易用軟件來確定和修改,此種芯片定功能強(qiáng),使用靈活。在單片機(jī)的定時(shí)/計(jì)數(shù)器不夠用時(shí),可以考慮進(jìn)行擴(kuò)展。
中斷服務(wù)程序的寫法
void 函數(shù)名()interrupt 中斷號 using 工作組
{
中斷服務(wù)程序內(nèi)容
}
在寫單片機(jī)的定時(shí)器程序時(shí),在程序開始處需要對定時(shí)器及中斷寄存器做初始化設(shè)置,通常定時(shí)器初始化過程如下:
?。?)對TMOD賦值,以確定T0和 T1的工作方式。
(2)計(jì)算初值,并將初值寫入TH0、TL0或TH1、TL1。
?。?)中斷方式時(shí),則對IE賦值,開放中斷。
?。?)使TR0和TR1置位,啟動(dòng)定時(shí)器/計(jì)數(shù)器定時(shí)或計(jì)數(shù)。
例:利用定時(shí)器0工作方式1,實(shí)現(xiàn)一個(gè)發(fā)光管以1s亮滅閃爍。
程序代碼如下:
#include《reg52.h》
#define uchar unsigned char
#define uint unsigned int
sbit led1=P1^0;
uchar num;
void main()
{
TMOD=0x01; //設(shè)置定時(shí)器0位工作模式1(M1,M0位0,1)
TH0=(65536-45872)/256; //裝初值11.0592M晶振定時(shí)50ms數(shù)為45872
TL0=(65536-45872)%256;
EA=1; //開總中斷
ET0=1; //開定時(shí)器0中斷
TR0=1; //啟動(dòng)定時(shí)器0
while(1)
{
if(num==20) //如果到了20次,說明1秒時(shí)間
{
led1=~led1; //讓發(fā)光管狀態(tài)取反
num=0;
}
}
}
void T0_time()interrupt 1
{
TH0=(65536-45872)/256; //重新裝載初值
TL0=(65536-45872)%256;
num++;
}
以下為一個(gè)比較簡單易懂的單片機(jī)定時(shí)器中斷程序,只要自行更改端口就可以使用!大家可以參考一下!
#include《reg51.h》
#define uchar unsigned char
#define uint unsigned int
sbit RING1=P3^7; //P3^7接蜂鳴
sbit OPEN=P3^1; //鬧鐘開時(shí)LED亮
uchar idata buffer[8]={0,0,0,0,0,0,10,11};//定義兩段緩沖區(qū),buffer用于過程中時(shí)間BCD碼暫存并初始化
uchar code LED[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X40}; //LED段譯存儲(chǔ)于程序存儲(chǔ)區(qū)
uchar miao=0;fen=58;shi=10; //定義全局變量用于miao,fen,shi用于存儲(chǔ)過程時(shí)間
uchar _20ms;//定義全局變量_20ms用于計(jì)數(shù)中斷個(gè)數(shù),50個(gè)為1秒
uchar hour2,minutes2,second2;//鬧鈴設(shè)置時(shí)間存儲(chǔ)區(qū)
uchar hour1,minutes1,second1;//修改時(shí)間時(shí)暫存區(qū)
bit hour,minutes,second;//修改相應(yīng)時(shí)的位標(biāo)志
bit add,dec;//加減位標(biāo)志
bit openring,cancelring;//鬧鈴開、關(guān)、取消標(biāo)志
bit setring,settime;//鬧鈴設(shè)置、時(shí)間設(shè)置標(biāo)志
bit ok;//確定變量
void delay_1ms(uchar x)//延時(shí)1ms
{
uchar j;
while(x--)
{
for(j=0;j《123;j++){;}
}
}
void inital(void)//定時(shí)器初始化函數(shù)
{ RING1=1; //這里RING等于0時(shí)蜂鳴器響;
TMOD=0x01; //定時(shí)器0工作于方式1,采用12M晶振,定時(shí)20ms
TH0=(65536-20000)/256;
TL0=(65536-20000)%256;
TR0=1; //TR0=1 啟動(dòng)定時(shí)器
EA=1; //開總中斷
ET0=1; //開定時(shí)器中斷
}
void timer0 (void) interrupt 1 using 1 //定時(shí)0中斷函數(shù)
{ TH0=(65536-20000)/256;
TL0=(65536-20000)%256;
_20ms++;
if(50==_20ms) //判斷是否到了一秒
{ miao++; //到了一秒,秒++
_20ms=0;
if(miao==60) //六十秒到了嗎
{ fen++; //到了份++
miao=0;
if(fen==60) //六十分到了嗎
{ shi++; //到了時(shí)++
fen=0;
if(shi==24) //24小時(shí)到了嗎
{ shi=0; //時(shí)清零
fen=0;
miao=0;
}
}
}
}
if(openring==1) //鬧鐘開了嗎
{ if((shi==hour2)&&(fen==minutes2)&&(miao==second2)) //定時(shí)時(shí)間到 鬧鈴響
RING1=0;
if(cancelring==1) //鬧鐘關(guān)
{RING1=1;cancelring=0;}
}
}
void timebcd (uchar m,uchar f,uchar s) //時(shí)間變動(dòng)函數(shù),當(dāng)計(jì)時(shí)到達(dá)1秒時(shí)進(jìn)行時(shí)間變動(dòng)
{
buffer[0]=m%10; //shi、fen、miao轉(zhuǎn)換成BCD碼,主要為了數(shù)碼管的顯示
buffer[1]=m/10;
buffer[2]=f%10;
buffer[3]=f/10;
buffer[4]=s%10;
buffer[5]=s/10;
}
void keyscan(void) //鍵掃描并確定鍵值函數(shù),該部分是時(shí)鐘各種功能實(shí)現(xiàn)的核心
{
uchar scode,recode,value; //定義行列變量
P2=0XF0; // 注意鍵盤與P2的接法,4*4鍵盤
if ((P2 & 0XF0)!=0XF0)
{
delay_1ms(10);
if ((P2&0XF0)!=0XF0)
{
scode=0xfe;
while((scode & 0x10)!=0)
{ P2=scode;
if ((P2&0XF0)!=0XF0)
{recode=(P2 & 0XF0)|0X0f;
value=((~scode)+(~recode));
switch(value)
{ case 0x11: hour=1;minutes=0;second=0;break;//時(shí),按到的鍵是修改時(shí)的功能鍵,hour是修改時(shí)的標(biāo)志位
case 0x21: hour=0;minutes=1;second=0;break;//分,按到的鍵是修改分的功能鍵,minutes是修改分的標(biāo)志位;
case 0x41: hour=0;minutes=0;second=1;break;//秒 與上面類似;
case 0x81: add=1;dec=0;break;// 加
case 0x12: dec=1;add=0;break;//減
case 0x22: setring=1;settime=0;second1=second2;minutes1=minutes2;hour1= hour2;break;//鬧鐘設(shè)置,
case 0x42: settime=1;setring=0;second1=miao;minutes1=fen;hour1=shi;break;//時(shí)間設(shè)置
case 0x82: setring=0;settime=0;break;//返回
case 0x14: ok=1;break;//確定
case 0x24: openring=1;OPEN=0;break;//開鬧鐘
case 0x44: openring=0;OPEN=1;break;//關(guān)鬧鐘
case 0x84:cancelring=1;break;// 取消響鈴
default: break;
}
}
else scode=(scode《《1)|0x01;
}
}
}
}
注意:這里將鍵盤的值進(jìn)行了編碼,12個(gè)鍵盤進(jìn)行了編碼 ,特別注意 鬧鐘設(shè)置和時(shí)間設(shè)置的實(shí)現(xiàn)方法 ,他們共用了函數(shù) resettime,沒什么難的。
void resettime (viod)
{
if(hour==1)
{
if (add==1)
{hour1++;add=0;}
if( hour1==24)
hour1=0;
if (dec==1)
{hour1--;dec=0;}
if (hour1==-1)
hour1=23;
}
if(minutes==1)
{
if (add==1)
{minutes1++;add=0;}
if (minutes1==60)
minutes1=0;
if(dec==1)
{ minutes1--;dec=0;}
if (minutes1==-1)
minutes1=59;
}
if(second==1)
{
if (add==1)
{second1++;add=0;}
if(second1==60)
second1=0;
if (dec==1)
{second1--;dec=0;}
if(second1==-1)
second1=59;
}
}
display (void) //顯示函數(shù)子程序
{
uchar j,n;
for(n=0,j=0XFE;n《8;j=((j《《1)|0X01),n++)
{P1=j; //P1接數(shù)碼管位選
P0=LED[buffer[n]]; //P0接數(shù)碼管段選
delay_1ms(5);
}
}
void main (void)
{
inital(); // 調(diào)用定時(shí)器初始化
for(;;)
{
timebcd(miao,fen,shi);
keyscan();
//調(diào)用鍵掃描,確定功能
if(settime==1) //當(dāng)按下的鍵是時(shí)間設(shè)置時(shí)
{
resettime();
timebcd ( second1, minutes1,hour1);
if(ok==1) //當(dāng)確定被按下時(shí),表明重設(shè)時(shí)間要覆蓋原來的時(shí)間,所以將miao,fen,shi重置,_20ms清零
{ shi=hour1;
fen=minutes1;
miao=second1;
_20ms=0;
}
}
if(setring==1)
{
resettime();
timebcd( second1, minutes1,hour1);
if(ok==1)
{ hour2=hour1;
minutes2=minutes1;
second2=second1;
}
}
display(); //調(diào)用顯示函數(shù)
}
}
單片機(jī)C語言定時(shí)中斷程序
#include《reg51.h》 //包含51單片機(jī)寄存器定義的頭文件
#define x 65536
#define y 256
sbit sound=P2^0; //將sound位定義為P3.7
unsigned int C; //儲(chǔ)存定時(shí)器的定時(shí)常數(shù)
unsigned int code f[]={399,1900,1800,1700,1600,1500,1400,1300,1200,1100,1000,900,0xff};
unsigned char code JP[]={4,1,1,4,1,1,2,2,2,2,2,8};
void delay()
{
unsigned char i,j;
for(i=0;i《250;i++)
for(j=0;j《250;j++)
;
}
void main()
{
unsigned char i,j;
EA=1; //開總中斷
ET0=1;
TMOD=0x01; // 使用定時(shí)器T0的模式1(13位計(jì)數(shù)器)
while(1) //無限循環(huán)
{
while(f[i]!=0xff) //只要沒有讀到結(jié)束標(biāo)志就繼續(xù)播放
{
C=500000/f[i];
TH0=(x-C)/y; //可證明這是13位計(jì)數(shù)器TH0高8位的賦初值方法
TL0=(x-C)%y; //可證明這是13位計(jì)數(shù)器TL0低5位的賦初值方法
TR0=1; //啟動(dòng)定時(shí)器T0
for(j=0;j《JP[i];j++) //控制節(jié)拍數(shù)
delay(); //延時(shí)1個(gè)節(jié)拍單位
TR0=0; //關(guān)閉定時(shí)器T0
i++; //播放下一個(gè)音符
}
}
}
void Tim() interrupt 1
{
sound=!sound; //將P3.7引腳輸出電平取反,形成方波
TH0=(x-C)/y; //可證明這是13位計(jì)數(shù)器TH0高8位的賦初值方法
TL0=(x-C)%y; //可證明這是13位計(jì)數(shù)器TL0低5位的賦初值方法
}
評論
查看更多