This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] SW-DK-TM4C123G:使用定时器0A 的上升沿捕捉进行 PWM 周期测量

Guru**** 661510 points
Other Parts Discussed in Thread: EK-TM4C1294XL
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/951583/sw-dk-tm4c123g-pwm-period-measure-using-rising-edge-capture-with-timer-0a

器件型号:SW-DK-TM4C123G
Thread 中讨论的其他器件:EK-TM4C1294XLTM4C123

大家好、

  我很难让简单的 PWM 周期测量程序正常工作、需要一些帮助。

  我正在为端口 PL0提供320Hz PWM、我想使用捕捉事件来测量两个上升沿之间的时间。

  我以16MHz 的时钟频率运行系统、因此我假设计时器脱离系统时钟运行。 因此、我希望测量2个上升沿之间的50000个计数/周期。

  1个周期@ 16MHz = 0.0000000625秒、因此、50000计数为0.003125s = 320Hz。 我的输入非常稳定。 我已经在范围上检查过它。

  我将代码放在下面(计时器初始化代码和中断服务例程以捕获周期)、运行时为我提供34464和50000的替代输出、而不是一致的50000。 我出了什么问题?

  最后、我计划测量2Hz 到20Hz 之间的波形的周期。 如何减慢计时器时钟的速度? 我尝试使用 TivaWare 库中的 TimerPrescale 函数、但该函数不起作用。

空 InitTimer (空)

UARTprintf ("初始化 Timer0 a\n");
//启用和配置 Timer0外设。
SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);

while (!SysCtlPeripheralReady (SYSCTL_Periph_TIMER0))

//配置定时器读取的引脚(PL0)
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOL);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOL))

//配置定时器读取的引脚(PL0)
GPIOPinConfigure (GPIO_PL0_T0CCP0);
GPIOPinTypeTimer (GPIO_PORTL_BASE、GPIO_PIN_0);

TimerDisable (TIMER0_BASE、TIMER_A);//配置定时器前将其禁用
TimerConfigure (TIMER0_BASE,(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP));//初始化计时器 A 以在边沿计时模式中递增计数
TimerClockSourceSet (TIMER0_BASE、TIMER_CLOCK 系统);//系统设置为16MHz
// TimerPrescaleSet (TIMER0_BASE、TIMER_A、0x20);//目前不确定这是如何工作的
TimerControlEvent (TIMER0_BASE、TIMER_A、TIMER_EVENT_POS_EDGE);// Timer A 记录位置边沿时间
TimerLoadSet (TIMER0_BASE、TIMER_A、0xFFFF);// LoadSet 指定定时器计数的最大值

//将引脚设置为使用内部上拉电阻。 从示例项目复制

MAP_GPIOPadConfigSet (GPIO_PORTL_base、GPIO_PIN_0、
GPIO_Strength _2mA、GPIO_PIN_TYPE_STD_WPU);

//注册一个在计时器 A 遇到上升沿事件时调用的中断函数
TimerIntRegister (TIMER0_BASE、TIMER_A、Timer0CCP0IntHandler);

TimerIntClear (TIMER0_BASE、TIMER_CAP_EVENT);  //确保清除中断
IntEnable (INT_TIMER0A);  //在中断控制器中启用指定的中断。
TimerIntEnable (TIMER0_BASE、TIMER_CAP_EVENT); //启用指示的定时器中断源。

//当到达正边沿时,记录这些值并找到差异,输出到 Putty
空 Timer0CCP0IntHandler (空)

TimerIntClear (TIMER0_BASE、TIMER_CAP_EVENT);
如果(gFLAG = 0)

gEnd = TimerValueGet (TIMER0_BASE、TIMER_A);
gLength = gEnd - gStart;
UARTprintf ("\ngEnd =%d\n"、gEnd);
UARTprintf ("\nLENGTH =%d\n"、gLength);
gFLAG = 1;

否则{
gStart = gEnd;
gEnd = TimerValueGet (TIMER0_BASE、TIMER_A);
gLength = gEnd - gStart;
UARTprintf ("\ngEnd =%d "、gEnd);
UARTprintf ("length =%d\n"、gLength);

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     请注意、Timer0A 是一个16位计时器。 因此、假设您的系统时钟为16MHz、Timer0A 将以最大244Hz 的频率超时。 您未发布有关如何配置系统时钟的代码。 如果您的输入低于244Hz,则需要使用 TimerPrescaleSet() API 更改 Timer0的时基,否则计时器计数器将在检测到下一个边沿之前溢出。 如果预分频2、则可以测量高达244/2 = 122Hz 输入的输入。 如果您的输入较慢、您将预分频更多。 如果您将来要测量2Hz 至20Hz、此信息适合您。  

     如果您测量的是320Hz 信号、则16位计时器应执行此操作。 有一个演示定时器边沿捕获的 TivaWare 示例。  可在 C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\timer_edge_capture 中找到它。 请注意、此示例适用于 tm4c129、但您应该能够适应 TM4C123。 该示例的另一个注意事项是、它使用两个具有两个计时器的引脚来测量两个不同边沿之间的极快转换、但如果上升速度不快、则可以使用一个计时器。   

     我还建议您在 ISR 中删除 UARTprintf()。 UARTPrintf 是一个阻塞函数。 如果 UARTPrintf 向终端发送长字符串、则可能会错过下一个上升沿中断。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Charles、

      系统时钟确实为16MHz。

      您关于从 ISR 中获取 UARTprintf()的建议是正确的。 首先、我将 UARTprintf 更改为仅打印周期字符串(尽量减少发送到终端的字符串长度)、这样可以获得一致的结果。 验证后、我将其从 ISR 中移出。  非常感谢!

       使用 TimerPrescaleSet()命令时预分频器不工作仍然是一个问题。 因此、我使用寄存器模型对初始化代码进行了重新编程、它按预期工作、测量频率低至2Hz 的波的占空比和周期。

       再次感谢!