51单片机定时器测量脉冲信号的频率并使用数码管显示。
附件提供完整可行的源码。
- #include "reg52.h"
- #define uint unsigned int
- #define SMG_A_DP_PORT P0 // 使用宏定义数码管段码口
- unsigned long int fre; //存储频率计算结果
- unsigned char time; //存储计时时间
- unsigned int count; //计数器0中断计数
- typedef unsigned int u16; // 对系统默认数据类型进行重定义
- typedef unsigned char u8;
- //共阴极数码管,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;
- //定义按键状态
- #define KEY1_PRESS 1
- #define KEY2_PRESS 2
- #define KEY3_PRESS 3
- #define KEY4_PRESS 4
- #define KEY_UNPRESS 0
- #endif
- /*******************************************************************************
- * 函 数 声明
- *******************************************************************************/
- u8 key_scan(u8 mode);
- void timer_init(void);
- void smg_display(u8 dat[],u8 pos);
- void delay_10us(u16 ten_us);
- /*******************************************************************************
- * 函 数 名 : delay_10us
- * 函数功能 : 延迟ten_us*10微秒
- * 输 入 : ten_us
- * 输 出 : 无
- *******************************************************************************/
- void delay_10us(u16 ten_us)
- {
- while(ten_us--);
- }
- /*******************************************************************************
- * 函 数 名 : key_scan
- * 函数功能 : 按键扫描并消抖
- * 输 入 : mode 按键操作
- * 输 出 : key 按键值
- *******************************************************************************/
- u8 key_scan(u8 mode)
- {
- static u8 key=1;
- if(mode)
- {
- key=1;
- }//模式为1时,重置按键状态
- 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;
- }
- /*******************************************************************************
- * 函 数 名 : timer_init
- * 函数功能 : 定时器0,1,2中断配置函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- 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的自动重装载值,用于产生62.5ms的定时
- RCAP2L=(65536-62500)%256; //TH2和TL2将会在中断产生时自动使TH2=RCAP2H,TL2=RCAP2L。
-
- TH2=RCAP2H; //定时器2的定时
- TL2=RCAP2L;
-
- ET2=1; //使能定时器2中断
- TR2=1; //定时器2开始计时
- EA=1; //使能全局中断
- }
- /*******************************************************************************
- * 函 数 名 : smg_display
- * 函数功能 : 动态数码管显示
- * 输 入 : dat:要显示的数据
- pos: 从数码管左边第pos位开始显示
- * 输 出 : 无
- *******************************************************************************/
- void smg_display(u8 dat[],u8 pos) //数码管显示
- {
-
- 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];//传送段选数据
- delay_10us(100);//延时一段时间,等待显示稳定
- SMG_A_DP_PORT=0x00;//消隐
- }
-
- }
- /*******************************************************************************
- * 函 数 名 : main
- * 函数功能 : 主函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void main() //主函数
- {
- 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);//显示
-
- }
- }
- /*******************************************************************************
- 函数功能:定时器2中断函数
- 中断条件:定时器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(单个中断的频率计数)×count(频率数)+TL0(不满一次中断的频率计数)
- fre=fre/1.084; //机器周期修正
- flag= 1;
-
- TL0=0; //清零计数器0计数
- TH0=0;
-
- TL1=0;
- TH1=0;
-
- count=0; //清零计数器0计数
-
- EA=1; //开中断
-
- }
- }
- /*******************************************************************************
- 函数功能:定时器0中断函数
- 中断条件: 8位计数器0溢出=》256个外部脉冲
- *******************************************************************************/
- void timer0(void) interrupt 1
- {
- count++;
- }
复制代码
|