系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
T0/T1中断计数功能使用,及简单频率测量
提示:以下是本篇文章正文内容,下面案例可供参考
一、场景
- 方案1:单位时间计数,如1s计数,即为频率。有误差,频率约高误差逐步减小,适用于精度要求不高的测量
- 方案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,若是要更高频率,需要分频处理