你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

#C51中断计数功能(简单频率测量)

2021/12/30 3:29:30

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 系列文章目录
  • 前言
  • 一、场景
  • 二、编程实现
    • 设计思路
    • 代码设计
    • 调试验证
  • 总结


前言

T0/T1中断计数功能使用,及简单频率测量


提示:以下是本篇文章正文内容,下面案例可供参考

一、场景

  1. 方案1:单位时间计数,如1s计数,即为频率。有误差,频率约高误差逐步减小,适用于精度要求不高的测量
  2. 方案2:测周法:外部中断下降沿触发,第1个负跳变时打开定时器开始计数,第2个负跳变时关闭计数,TH0 && TL0取出,即为周期。倒数即为频率。

二、编程实现

设计思路

T1计数,T0定时。
T0中断服务函数中定时1s,关闭T1计数,并计算TH1/TL1

代码设计

void Timer1Init(void)		//@11.0592MHz 
{
	TMOD &= 0x0F;		//设置计数模式	GATE C/T^ M1 M0  // 0 1 0 1
	TMOD |= 0x50;		//设置计数模式 T1 方式1 16位定时器
	TL1 = 0;	//初值	
	TH1 = 0;		
	TF1 = 0;			//清除TF1标志
	ET1 = 1;//打开定时器T1
	TR1 = 1;			//定时器1开始计时
}
void Timer0_ISR() interrupt 1
{
	UI vFreqCnt;
	vFreqCnt++;
	if(vFreqCnt > 1000)
	{
		vFreqCnt = 0;
		TR1 = 0;	//关闭T1计数
		FreqCnt = TH1 * 256  + TL1;
		TH1 = 0;	
		TL1 = 0;
		TR1 = 1;	//打开T1计数,继续下一轮
	}
}

显示处理:

NumDisSpare(FreqCnt);
void NumDisSpare(unsigned int vDisNum)
{
	if(vDisNum >= 1000)
	{
		SEG_DisBuf[0]  = vDisNum / 1000;
	}
	else
	{
		SEG_DisBuf[0] = 23;
	}
	if(vDisNum >= 100)
	{
		SEG_DisBuf[1]  = vDisNum / 100 % 10;
	}
	else 
	{
		SEG_DisBuf[1] = 23;
	}
	if(vDisNum >= 10)
	{
		SEG_DisBuf[2]  = vDisNum / 10 % 10;
	}
	else
	{
		SEG_DisBuf[2] = 23;
	}
	SEG_DisBuf[3]  = vDisNum % 10;
}

调试验证

时钟发生器20Hz
在这里插入图片描述

以上验证ok


总结

1.单位时间计数求频率的方式存在误差。来源于中断定时内代码时延,频率越高误差越小。T1目前最高65536Hz,若是要更高频率,需要分频处理