51單片機定時器測量脈沖信號的頻率并使用數(shù)碼管顯示。
附件提供完整可行的源碼。
- #include "reg52.h"
- #define uint unsigned int
- #define SMG_A_DP_PORT P0 // 使用宏定義數(shù)碼管段碼口
- unsigned long int fre; //存儲頻率計算結果
- unsigned char time; //存儲計時時間
- unsigned int count; //計數(shù)器0中斷計數(shù)
- typedef unsigned int u16; // 對系統(tǒng)默認數(shù)據(jù)類型進行重定義
- typedef unsigned char u8;
- //共陰極數(shù)碼管,0-9段碼表
- unsigned char code Duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
- //定義鎖存器控制位
- sbit LSC=P2^4;
- sbit LSB=P2^3;
- sbit LSA=P2^2;
- unsigned char flag=0; //標志位,用于控制計時器
- u16 dangwei=1; //定時器的分檔位,初始為1
- #ifndef _key_H
- #define _key_H
- //定義獨立按鍵控制腳
- sbit KEY1=P3^1;
- sbit KEY2=P3^0;
- sbit KEY3=P3^2;
- sbit KEY4=P3^3;
- //定義按鍵狀態(tài)
- #define KEY1_PRESS 1
- #define KEY2_PRESS 2
- #define KEY3_PRESS 3
- #define KEY4_PRESS 4
- #define KEY_UNPRESS 0
- #endif
- /*******************************************************************************
- * 函 數(shù) 聲明
- *******************************************************************************/
- u8 key_scan(u8 mode);
- void timer_init(void);
- void smg_display(u8 dat[],u8 pos);
- void delay_10us(u16 ten_us);
- /*******************************************************************************
- * 函 數(shù) 名 : delay_10us
- * 函數(shù)功能 : 延遲ten_us*10微秒
- * 輸 入 : ten_us
- * 輸 出 : 無
- *******************************************************************************/
- void delay_10us(u16 ten_us)
- {
- while(ten_us--);
- }
- /*******************************************************************************
- * 函 數(shù) 名 : key_scan
- * 函數(shù)功能 : 按鍵掃描并消抖
- * 輸 入 : mode 按鍵操作
- * 輸 出 : key 按鍵值
- *******************************************************************************/
- u8 key_scan(u8 mode)
- {
- static u8 key=1;
- if(mode)
- {
- key=1;
- }//模式為1時,重置按鍵狀態(tài)
- if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按鍵按下
- {
- delay_10us(1000);//消抖
- key=0;
- if(KEY1==0)
- return KEY1_PRESS;
- else if(KEY2==0)
- return KEY2_PRESS;
- else if(KEY3==0)
- return KEY3_PRESS;
- else if(KEY4==0)
- return KEY4_PRESS;
- }
- else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1) //無按鍵按下
- {
- key=1;
- }
- return KEY_UNPRESS;
- }
- /*******************************************************************************
- * 函 數(shù) 名 : timer_init
- * 函數(shù)功能 : 定時器0,1,2中斷配置函數(shù)
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- void timer_init(void) //定時器初始化
- {
- TMOD=0xEE; //定時器0和定時器1工作模式方式2,自動重裝載
- TH0=0; //定時器0重裝載值高位
- TL0=0;
- TR0=1; //啟動定時器0
- ET0=1; //使能定時器0中斷,
-
- TH1=0; //定時器1重裝載值高位
- TL1=0;
- TR1=1; //啟動定時器1
- ET1=1; //使能定時器1中斷
-
- RCAP2H=(65536-62500)/256; //定時器2的自動重裝載值,用于產(chǎn)生62.5ms的定時
- RCAP2L=(65536-62500)%256; //TH2和TL2將會在中斷產(chǎn)生時自動使TH2=RCAP2H,TL2=RCAP2L。
-
- TH2=RCAP2H; //定時器2的定時
- TL2=RCAP2L;
-
- ET2=1; //使能定時器2中斷
- TR2=1; //定時器2開始計時
- EA=1; //使能全局中斷
- }
- /*******************************************************************************
- * 函 數(shù) 名 : smg_display
- * 函數(shù)功能 : 動態(tài)數(shù)碼管顯示
- * 輸 入 : dat:要顯示的數(shù)據(jù)
- pos: 從數(shù)碼管左邊第pos位開始顯示
- * 輸 出 : 無
- *******************************************************************************/
- void smg_display(u8 dat[],u8 pos) //數(shù)碼管顯示
- {
-
- u8 i=0;
- u8 pos_temp=pos-1;
- for(i=pos_temp;i<8;i++)
- {
- switch(i)//位選
- {
- case 0: LSC=1;LSB=1;LSA=1;break;
- case 1: LSC=1;LSB=1;LSA=0;break;
- case 2: LSC=1;LSB=0;LSA=1;break;
- case 3: LSC=1;LSB=0;LSA=0;break;
- case 4: LSC=0;LSB=1;LSA=1;break;
- case 5: LSC=0;LSB=1;LSA=0;break;
- case 6: LSC=0;LSB=0;LSA=1;break;
- case 7: LSC=0;LSB=0;LSA=0;break;
- }
- SMG_A_DP_PORT=dat[i-pos_temp];//傳送段選數(shù)據(jù)
- delay_10us(100);//延時一段時間,等待顯示穩(wěn)定
- SMG_A_DP_PORT=0x00;//消隱
- }
-
- }
- /*******************************************************************************
- * 函 數(shù) 名 : main
- * 函數(shù)功能 : 主函數(shù)
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- void main() //主函數(shù)
- {
- u8 key=0;
- u8 time_buf[8];
- fre=0;
-
- timer_init(); //定時器初始化
- while(1)
- {
- key=key_scan(0); //掃描按鍵
- if(key==KEY1_PRESS)//開始和停止計時
- {
- dangwei=1;
- timer_init();
- }
- else if(key==KEY2_PRESS)//清除計時
- {
- dangwei=2;
- timer_init();
-
- }
- else if(key==KEY3_PRESS)//清除計時
- {
- dangwei=5;
- timer_init();
- }
- time_buf[0]=Duan[dangwei];
- time_buf[1]=Duan[fre/1000000%10];
- time_buf[2]=Duan[fre/100000%10];
- time_buf[3]=Duan[fre/10000%10];
- time_buf[4]=Duan[fre/1000%10];
- time_buf[5]=Duan[fre/100%10];
- time_buf[6]=Duan[fre/10%10];
- time_buf[7]=Duan[fre%10];
- smg_display(time_buf,1);//顯示
-
- }
- }
- /*******************************************************************************
- 函數(shù)功能:定時器2中斷函數(shù)
- 中斷條件:定時器2溢出=》定時器2定時62.5ms
- *******************************************************************************/
- void timer2(void) interrupt 5 //定時器2中斷(62.5ms)
- {
- time++;
- TF2=0; //定時器2的中斷標志位TF2不能夠由硬件清零,所以要在中斷服務程序中將其清零
-
- if (time==16*dangwei) //定時時間到
- {
- time=0; //計時清0
- EA=0; //關中斷
- flag = 0;
- fre = ((long)count*256+TL0)/dangwei ; //計算頻率=256(單個中斷的頻率計數(shù))×count(頻率數(shù))+TL0(不滿一次中斷的頻率計數(shù))
- fre=fre/1.084; //機器周期修正
- flag= 1;
-
- TL0=0; //清零計數(shù)器0計數(shù)
- TH0=0;
-
- TL1=0;
- TH1=0;
-
- count=0; //清零計數(shù)器0計數(shù)
-
- EA=1; //開中斷
-
- }
- }
- /*******************************************************************************
- 函數(shù)功能:定時器0中斷函數(shù)
- 中斷條件: 8位計數(shù)器0溢出=》256個外部脈沖
- *******************************************************************************/
- void timer0(void) interrupt 1
- {
- count++;
- }
復制代碼
|