在运用STC单片机测频率最常用的办法是在必定时刻内核算脉冲个数,这种办法一般需求一个计数器和一个定时器合作,并且对低频信号也不太精确,下面咱们能够用到timer2的捕获形式经过丈量两个下降沿的时刻,来核算频率,这样做仅运用timer2就好了,并且对低频信号丈量精确,经实践测验,在100Hz一下时,精度可达0.05Hz。
下面先介绍一下STC51 timer2的捕获形式:
在捕获形式中,经过T2CON中的EXEN2设置两个选项,假如EXEN2=0,定时器作为一个16位的定时器或计数器,溢出时置位TF2。该位可用于发生中止(ET2=1)。假如EXEN2=1,就增加了一个特性,即外部输入T2EX(P11)有下降沿时,将timer2中的TH2和TL2当时值各自捕获到RCAP2L和RCAP2H。别的,T2EX的负跳变使T2CON中的EXF2置位,EXF2也想TF2相同来发生中止(其向量与timer2溢出中止相同,timer2的中止服务经过查询TF2和EXF2来确认引起的中止事情),若是T2EX中止,进来后TH2和TL2不会从头装载值,会持续以当时计数往上计数,除非你的确想改动TH2和TL2的值,如需求从头计数。
下面介绍下程序:
由于外部跳变和溢出均能够进入中止,咱们能够使用这一特性来做对两个脉冲之间的时刻丈量,初始时设置TH2和TL2值为0,假如发生溢出中止,咱们的计时变量就自加65536,假如进入外部跳变中止,则咱们读取RCAP2L和RCAP2H的值并与前面的计时变量相加即可得到这个跳变与上一跳变的时刻,留意丈量完毕后要清空计时变量以及H2和TL2,便利下一次的从头计数。
初始化程序如下:
//定时器2设置为捕获形式,用户核算速度void Timer2Init(){char i;EXEN2 = 1;//timer2 outside enableCP_RL2 = 1;//enable capture modeTH2 = TL2 = 0;RCAP2H = RCAP2L = 0;TR2 = 1;//enable timer2ET2=1; //enable timer2 interrupt//将计时器存储区设置的很大,也便是频率先挨近0 for(i=0;i<5;i++){plus_length[i] = 6553600;}}
中止服务程序如下,在这里keil对long型的数据核算有点问题,需求分外留意:
/** 函 数 名 :Timer2Int* 函数功用 :定时器2中止函数 , 捕获形式* 输 入 :无* 输 出 :无 */void Timer2Int() interrupt 5{static volatile long plus_length_temp=0;static char index=0;if(TF2 == 1)//overflow int{TF2 = 0;TH2 = 0;TL2 = 0;RCAP2H = 0;RCAP2L = 0;plus_length_temp = plus_length_temp + 65536;if(plus_length_temp > 6553600) {plus_length[index] = plus_length_temp;//对最近5个求平均值index++;if(index == 5) index = 0;plus_length_temp = 0;}}if(EXF2 == 1)//capture int{long temp;TH2 = 0;TL2 = 0;//WTF!!! clear TH2 and TL2,not TH0 and TH1EXF2 = 0;temp = ((long)(RCAP2H<<8) + RCAP2L) & 0xffff; //古怪的问题,假如不加0xffff,temp高位会全为ff,然后发生负数RCAP2H = 0;RCAP2L = 0;temp = plus_length_temp + temp;//在对long核算时要当心,一步一来plus_length_temp = temp;plus_length[index] = plus_length_temp;//对最近5个求平均值index++;if(index == 5) index = 0;plus_length_temp = 0;//read calc next plus}}
最终便是主函数部分内容,每隔500ms求平均值并打印一次当时频率:
calc_plength = 0;Delayms(500);for(count = 0;count<5;count++){calc_plength += plus_length[count];}calc_plength = calc_plength/5;freq = (float)3990000/calc_plength;//read real frequenceprintf("freq=%f\r\n",freq);
这种办法对低频情况下比较有用,但频率较高时如达到上k的频率,夺冠比较大,有显着的偏高,至于原因,还等候进一步研讨。