定時/計數器實現功能:
(1)定時功能:
定時/計數器說明(最高單次計時時間是71毫秒=65535*1.085us,1.085us是機器周期):
使用51定時/計數器步驟:
定時/計算器控制寄存器:
設置定時寄存器的工作模式:
將想計時的時間(這個時間意思是想讓定時/計數器經過多長時間溢出,溢出后就說明達到了你設定的時間)轉化為微秒級(50毫秒=50000微妙)再用轉化后的數除以1.085(機器周期時間)得到的數就是要加的次數 ,定時/計數器總共加65535次就會溢出,提前有一個初始值就可減少達到溢出的的次數。
例子:想50毫秒后定時/計數器溢出,50毫秒=50000微妙
(第一種方式)50000除以1.085得到46082(次),然后就可以將高八位TH0=46082/256(意思是有多少個256放入高八位中),低八位TL0=46082%256(意思是將剩余的256放到低八位中)。
(第二種方式)也可以用65535減46082得到初值,再將十進制初值轉化為十六進制,將前兩位給TH0后兩位給TL0
計時器代碼示例
#include<reg52.h>
#include<intrins.h>#define uint unsigned int
#define uchar unsigned charsbit beep=P2^3;
sbit DUAN =P2^6;//數碼管段選
sbit WEI=P2^7; //數碼管位選
uchar temp;
//共陰極數碼管段選表0——9,code表示數組中的數據在程序執行過程中不能被修改
//加code存放的是ROM區不加code存放的是RAM區
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(void) //誤差 -0.000000000001us
{unsigned char a,b;for(b=15;b>0;b--)for(a=152;a>0;a--);
} void display(uint i)
{ uint bai,shi,ge;bai=i/100;shi=i%100/10;ge=i%10;P0=0xff;//清除斷碼WEI=1;//打開位選鎖存器P0 = 0xfe;//1111 1110 給第一個數碼管接地,讓它工作WEI =0;//關閉位選鎖存器,進行段選(顯示數字)DUAN=1;//打開段選鎖存器P0 =table[bai];DUAN =0;//鎖存段選鎖存器delay();P0=0xff;//清除斷碼WEI=1;P0 = 0xfd;WEI =0;DUAN=1;P0 = table[shi];DUAN =0;delay();P0=0xff;//清除斷碼WEI=1;P0 = 0xfb;WEI =0;DUAN=1;P0 = table[ge];DUAN =0; delay();
}
//定時器0初始化
void timeInit()
{TR0=1;//啟動定時器0TMOD=0x01;//定時器工作模式一,16位定時計時模式//TH0=0x4b;//TL0=0xfd;//定時50毫秒;TH0=(65535-46082)/256;TL0=(65535-46082)%256;//定時50毫秒;
}void main()
{uchar msec,sec;//聲明毫秒和秒儲存變量timeInit();while(1){if(TF0==1){TF0=0;//軟件清0溢出標志位TH0=0x4b;TL0=0xfd;//重放初值msec++;//50毫秒到if(msec==20){msec=0;sec++;//一秒時間到if(sec>100)sec=0;//計時到100秒從1開始 } }display(sec); //數碼管顯示時間}
}
(2)計數功能:
#include<reg52.h>
#include<intrins.h>#define uint unsigned int
#define uchar unsigned charsbit DUAN =P2^6;//數碼管段選
sbit WEI=P2^7; //數碼管位選
sbit LED1=P1^0;
uchar temp;
//共陰極數碼管段選表0——9,code表示數組中的數據在程序執行過程中不能被修改
//加code存放的是ROM區不加code存放的是RAM區
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(void) //誤差 -0.000000000001us
{unsigned char a,b;for(b=15;b>0;b--)for(a=152;a>0;a--);
} void display(uint i)
{ uint bai,shi,ge;bai=i/100;shi=i%100/10;ge=i%10;P0=0xff;//清除斷碼WEI=1;//打開位選鎖存器P0 = 0xfe;//1111 1110 給第一個數碼管接地,讓它工作WEI =0;//關閉位選鎖存器,進行段選(顯示數字)DUAN=1;//打開段選鎖存器P0 =table[bai];DUAN =0;//鎖存段選鎖存器delay();P0=0xff;//清除斷碼WEI=1;P0 = 0xfd;WEI =0;DUAN=1;P0 = table[shi];DUAN =0;delay();P0=0xff;//清除斷碼WEI=1;P0 = 0xfb;WEI =0;DUAN=1;P0 = table[ge];DUAN =0; delay();
}
//計數器0初始化
void jishuInit()
{TR0=1;//啟動計數器0TMOD|=0x05;//定時器工作模式一,16位計數模式TH0=0;TL0=0;
}
//定時器1初始化
void timeInit()
{TR1= 1;//啟動定時器1TMOD|=0x10;//定時器工作模式一,16位定時模式TH1=0x4b;TL1=0xfd;
}void main()
{uchar msec;//聲明毫秒和秒儲存變量jishuInit();//計數器0初始化timeInit();//定時器1初始化while(1){if(TF1==1){TF1=0;//軟件清0溢出標志位TH1=0x4b;TL1=0xfd;//重放初值msec++;//50毫秒到if(msec==10)//定時500毫秒到{msec=0;LED1=~LED1;//產生方波}}display(TL0); //數碼管顯示時間}
}
定時器中斷
中斷情況下TF由硬件清0,若無中斷則有軟件清0。
代碼示例:
#include<reg52.h>
#include<intrins.h>#define uint unsigned int
#define uchar unsigned charsbit beep=P2^3;
sbit DUAN =P2^6;//數碼管段選
sbit WEI=P2^7; //數碼管位選uchar temp;
uchar msec,sec;//聲明毫秒和秒儲存變量
//共陰極數碼管段選表0——9,code表示數組中的數據在程序執行過程中不能被修改
//加code存放的是ROM區不加code存放的是RAM區
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(void) //誤差 -0.000000000001us
{unsigned char a,b;for(b=15;b>0;b--)for(a=152;a>0;a--);
} void display(uint i)
{ uint bai,shi,ge;bai=i/100;shi=i%100/10;ge=i%10;P0=0xff;//清除斷碼WEI=1;//打開位選鎖存器P0 = 0xfe;//1111 1110 給第一個數碼管接地,讓它工作WEI =0;//關閉位選鎖存器,進行段選(顯示數字)DUAN=1;//打開段選鎖存器P0 =table[bai];DUAN =0;//鎖存段選鎖存器delay();P0=0xff;//清除斷碼WEI=1;P0 = 0xfd;WEI =0;DUAN=1;P0 = table[shi];DUAN =0;delay();P0=0xff;//清除斷碼WEI=1;P0 = 0xfb;WEI =0;DUAN=1;P0 = table[ge];DUAN =0; delay();
}
//定時器0初始化
void timeInit()
{EA=1;//打開總中斷ET0=1;//打開中斷允許位TR0=1;//啟動定時器0TMOD=0x01;//定時器工作模式一,16位定時計時模式//TH0=0x4b;//TL0=0xfd;//定時50毫秒;TH0=(65535-46082)/256;TL0=(65535-46082)%256;//定時50毫秒;
}void time0() interrupt 1//中斷函數
{TH0=0x4b;TL0=0xfd;//重放初值msec++;//50毫秒到if(msec==20)//1s時間到{msec=0;sec++;//一秒時間到if(sec>100)sec=0;//計時到100秒從1開始 } }void main()
{timeInit();while(1){display(sec); //數碼管顯示時間}
}
定時器中斷進行數碼管動態掃描:
#include <reg52.h>
#include <intrins.h>#define uint unsigned int
#define uchar unsigned charsbit DU = P2^6;//數碼管段選
sbit WE = P2^7;//數碼管位選
sbit key_s2 = P3^0;//獨立按鍵S2
sbit key_s3 = P3^1;//獨立按鍵S3
uchar num;//數碼管顯示的值//共陰數碼管段選表
uchar code SMGduan[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
//數碼管位選碼
uchar code SMGwei[] = {0xfe, 0xfd, 0xfb};
//毫秒級延時函數定義
void delay(uint z)
{uint x,y;for(x = z; x > 0; x--)for(y = 114; y > 0 ; y--);
} void display(uchar i)
{static uchar wei; P0 = 0XFF;//清除斷碼WE = 1;//打開位選寄存器P0 = SMGwei[wei];WE = 0;//鎖存位選寄存器switch(wei){case 0: DU = 1; P0 = SMGduan[i / 100]; DU = 0; break;case 1: DU = 1; P0 = SMGduan[i % 100 / 10]; DU = 0; break; case 2: DU = 1; P0 = SMGduan[i % 10]; DU = 0; break; }wei++;if(wei == 3)wei = 0;
}
//定時器0初始化
void timer0Init()
{EA = 1; //打開總中斷ET0 = 1;//打開定時器0中斷TR0 = 1; //啟動定時器0TMOD = 0X01; //定時器工作模式,16位定時模式TH0 = 0xED;TL0 = 0xFF; //定時5ms
}void main()//main函數自身會循環
{ timer0Init();//?¨ê±?÷03?ê??ˉwhile(1){if(key_s2 == 0)//判斷S2是否被按下{delay(20);//按鍵消抖if(key_s2 == 0){if(num != 120)num++;while(!key_s2);//松手檢測} }if(key_s3 == 0)//判斷S3是否被按下{delay(20);//按鍵消抖if(key_s3 == 0){if(num > 0)num--;while(!key_s3);//松手檢測} }}
} //定時器中斷函數
void timer0() interrupt 1
{TH0 = 0xED;TL0 = 0xFF; //定時5msdisplay(num); //數碼管顯示函數
}