标题:
51单片机测量频率-带修正测量精度
[打印本页]
作者:
llzfry
时间:
2025-1-16 16:35
标题:
51单片机测量频率-带修正测量精度
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++;
}
复制代码
作者:
raymondau
时间:
2025-1-19 00:45
楼主有做实物测试过吗?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1