TIVA 123GXL的边沿计数模式测量低频PWM

TM4C123GXL频率计第二弹

上篇文章讲到了使用Edge Timer模式来测量频率较高的PWM信号的方法,这次写了个用另一种原理来测量频率的方法,那就是采用Edge Count(边沿计数模式)的方法来较好地测量低频(50Hz左右)PWM信号频率。

一. 实验简介

  • 用函数信号发生器产生50Hz(或类似低频)PWM信号,用开发板测量频率
  • 每1s更新一次Frequency的值

二. 思路

上篇文章提到,Timer的边沿捕获有两种模式,一种是Edge Timer,也就是上篇文章测频率的方法,还有一种就是Edge Count,我们就采用边沿计数模式来测量。

  • 每1s更新一次Frequency:这个就需要采用定时器设置为超时模式,来使程序每1s进入一次超时中断函数,在这个函数里完成数据的更新和打印。
  • 边沿计数模式:相比于Edge Timer,我们只需要改一下TimerConfigure和设置下适当的装载值即可。

三. 库函数编程方法

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_timer.h"
#include "inc/hw_ints.h"
#include "inc/hw_gpio.h"
#include "inc/hw_i2c.h"
#include "inc/hw_sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/i2c.h"
#include "driverlib/udma.h"
#include "driverlib/fpu.h"
#include "driverlib/rom.h"
#include "uc1701.h"

unsigned long count = 0;
unsigned long tmp = 0;
unsigned long cur = 0, pre = 0;
unsigned short i = 0;
float freq = 0;

void Timer0AIntHandler(void);
void Time_1s_IntHandler(void);

void Calc_Freq(void)
{
   
   TimerIntClear(TIMER0_BASE, TIMER_CAPA_MATCH);
   tmp = cur - pre;
   //频率的获取,MatchSet()设置的10最后结果当然要乘以10
   freq = tmp * 10}

void Timer0AIntHandler(void)
{
   
   TimerIntClear(TIMER0_BASE, TIMER_CAPA_MATCH);
   count++;//当前计数值
}

void Time_1s_IntHandler(void)//保证
{
   
   // Clear the timer interrupt
   TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
   pre = cur;//这里用到了前后指针,
   cur = count;//记录前后计数模式的寄存器的值,防止再像上篇文章持续进入中断函数
   Calc_Freq();
}

void Time_1s_Init()
{
   
   uint32_t ui32Period;
   SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
   TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
   ui32Period = (SysCtlClockGet() / 1);//这里,除以x,就是2xHz的频率进入超时中断函数,我写的实际上使每0.5s进入中断函数处理数据得到Frequency ORZ。。。
   TimerLoadSet(TIMER1_BASE, TIMER_A, ui32Period -1);//上句装载值装入
   TimerIntRegister(TIMER1_BASE, TIMER_A, Time_1s_IntHandler);
   IntEnable(INT_TIMER1A);
   TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);//配置Timer1为超时中断
   TimerEnable(TIMER1_BASE, TIMER_A);
}

void Timer0Init()
{
   
   SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
   SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
   GPIOPinConfigure(GPIO_PB6_T0CCP0);
   GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_6);
   GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
   TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_COUNT_UP);
   TimerControlEvent(TIMER0_BASE, TIMER_A, TIMER_EVENT_NEG_EDGE);
   TimerMatchSet(TIMER0_BASE, TIMER_A, 10-1);//匹配的使10个计数到来后进入中断
   TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0AIntHandler);
   TimerIntEnable(TIMER0_BASE, TIMER_CAPA_MATCH);
   IntEnable(INT_TIMER0A);
   TimerEnable(TIMER0_BASE, TIMER_A);
}

void main()
{
   
   SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
   Time_1s_Init();
   Timer0Init();
   InitUC1701();
   UC1701CharDispaly(0, 4, "Freq Meter");
   UC1701CharDispaly(1, 9, "Hz");
   IntMasterEnable();
   while(1)    UC1701DisplayN(1, 2, freq);
}

这个链接里可以找到完整项目代码

四. 结果

  • 别忘了把GND&PB6接到函数发生器上
  • 别忘了确认输入的PWM波的高电平为3.3V,低电平为0V

这个我忘拍照片了,不过和上一个用Edge Timer的差不多,这个能较好地测量低频信号,放个上次的图吧…

参考链接
[1]: Help with Frequency Meter(Google)
[2]: https://github.com/WadeGao/TIVA
[3]: https://blog.csdn.net/weixin_44587168/article/details/102529152

全部评论

相关推荐

点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务