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.

[参考译文] CCS/TM4C1290NCPDT:多个计时器问题

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/576341/ccs-tm4c1290ncpdt-multiple-timers-issue

器件型号:TM4C1290NCPDT

工具/软件:Code Composer Studio

大家好、我使用4个计时器 从 PC4 PC5 PC6 PC7引脚以不同的频率(8 9 10和11 KHz)生成4个方波信号、一切正常、因此我尝试使用更多计时器从其他引脚 PH0 PH1 PH2 PH3生成更多方波信号 (8.5 9.5 10.5和11.5 KHz)、因此我尝试使用子计时器、代码如下:

#include 
#include 
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"







#include "driverlib/interrupt.h"#include "driverlib/rom/driverlib/#include"#driverlib/rom/driverlib/#include "driverlib/#driverlib/#include "driverlib/rom.lib"#include"#driverlib/#driver.h"

uint32_t g_ui32SysClock; //系统时钟速率,单位为 Hz。
uint32_t g_ui32FlagsN; //包含 UART 上显示的中断指示符当前值的标志。
uint32_t g_ui32FlagsF; //包含 UART 上显示的中断指示符当前值的标志。
uint32_t g_ui32FlagsP; //包含 UART 上显示的中断指示符当前值的标志。
uint32_t g_ui32FlagsB; //包含 UART 上显示的中断指示符当前值的标志。
uint32_t g_ui32FlagsC; //包含 UART 上显示的中断指示符当前值的标志。
uint32_t g_ui32FlagsH; //包含 UART 上显示的中断指示符当前值的标志。

uint32_t leBandera = 0;
//*********
空 Timer0IntHandler (空) //第一个计时器中断的中断处理程序。
{
ROM_TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsN、0)^= 1; //切换第一个计时器的标志。
HWREGBITW (&g_ui32FlagsC、4)^= 1; //切换第一个计时器的标志。
GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_0、g_ui32FlagsN); //使用标志切换此计时器的 LED
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_4、g_ui32FlagsC); //使用标记来切换此计时器的 LED

}

//*********
空 Timer1 IntHandler (空) //第二个计时器中断的中断处理程序。
{
ROM_TimerIntClear (Timer1_base、timer_TINA_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsN、1)^= 1; //切换第二个计时器的标志。
HWREGBITW (&g_ui32FlagsC、5)^= 1; //切换第一个计时器的标志。

GPIOPinWrite (GPIO_PORTN_BASE、GPIO_PIN_1、g_ui32FlagsN); //使用标志切换此计时器的 LED
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_5、g_ui32FlagsC); //使用标记来切换此计时器的 LED

}
//*********
空 Timer2IntHandler (空) //第二个计时器中断的中断处理程序。
{
ROM_TimerIntClear (TIMER2_base、TIMER_TINA_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsF、4)^= 1; //切换第二个计时器的标志。
HWREGBITW (&g_ui32FlagsC、6)^= 1; //切换第一个计时器的标志。

GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_4、g_ui32FlagsF); //使用标志切换此计时器的 LED
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_6、g_ui32FlagsC); //使用标记来切换此计时器的 LED

}
//*********
空 Timer3IntHandler (空) //第二个计时器中断的中断处理程序。
{
ROM_TimerIntClear (TIMER3_base、TIMER_TINA_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsF、0)^= 1; //切换第二个计时器的标志。
HWREGBITW (&g_ui32FlagsC、7)^= 1; //切换第一个计时器的标志。

GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_0、g_ui32FlagsF); //使用标志切换此计时器的 LED
GPIOPinWrite (GPIO_PORTC_BASE、GPIO_PIN_7、g_ui32FlagsC); //使用标记来切换此计时器的 LED

}
//*********
//
空 Timer0IntHandlerB (空) //第一个计时器中断的中断处理程序。
{
ROM_TimerIntClear (TIMER0_BASE、TIMER_TIMB_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsH、0)^= 1; //切换第一个计时器的标志。
GPIOPinWrite (GPIO_Porth_BASE、GPIO_PIN_0、g_ui32FlagsH); //使用标记来切换此计时器的 LED

}

//*********
空 Timer1 IntHandlerB (空) //第二个计时器中断的中断处理程序。
{
ROM_TimerIntClear (Timer1_base、timer_TIMB_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsH、1)^= 1; //切换第一个计时器的标志。
GPIOPinWrite (GPIO_Porth_BASE、GPIO_PIN_1、g_ui32FlagsH); //使用标记来切换此计时器的 LED

}
//*********
空 Timer2IntHandlerB (空) //第二个计时器中断的中断处理程序。
{
ROM_TimerIntClear (TIMER2_base、TIMER_TIMB_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsH、2)^= 1; //切换第一个计时器的标志。
GPIOPinWrite (GPIO_Porth_BASE、GPIO_PIN_2、g_ui32FlagsH); //使用标记来切换此计时器的 LED

}
//*********
空 Timer3IntHandlerB (空) //第二个计时器中断的中断处理程序。
{
ROM_TimerIntClear (TIMER3_base、TIMER_TIMB_TIMEOUT); //清除计时器中断。
HWREGBITW (&g_ui32FlagsH、3)^= 1; //切换第一个计时器的标志。
GPIOPinWrite (GPIO_Porth_BASE、GPIO_PIN_3、g_ui32FlagsH); //使用标记来切换此计时器的 LED

}
//*********
//
//此示例应用演示了如何使用计时器来生成
//周期性中断。
//
int main (void)
{
G_ui32SysClock = MAP_SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz | //将时钟设置为直接从频率为120MHz 的晶体运行。
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480)、120000000);

ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPION); //启用用于板载 LED 的 GPIO 端口。
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF); //启用用于板载 LED 的 GPIO 端口。
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC); //启用用于板载 LED 的 GPIO 端口。
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOH); //启用用于板载 LED 的 GPIO 端口。


ROM_GPIOPinTypeGPIOOutput (GPIO_PORTN_BASE、GPIO_PIN_0 | GPIO_PIN_1); //为 LED (PN0和 PN1)启用 GPIO 引脚。
ROM_GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_0 | GPIO_PIN_4);//为 LED 启用 GPIO 引脚(PF4)。
ROM_GPIOPinTypeGPIOOutput (GPIO_PORTC_BASE、GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
ROM_GPIOPinTypeGPIOOutput (GPIO_Porth_BASE、GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);


ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0); //启用此示例使用的外设。
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_Timer1);
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER2);
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_TIMER3);
// ROM_IntMasterEnable (); //启用处理器中断。

TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICASE); //配置两个32位周期定时器。
TimerConfigure (Timer1_base、timer_CFG_PERIODICRACRACASE);
TimerConfigure (TIMER2_base、TIMER_CFG_PERIODICRACASE);
TimerConfigure (TIMER3_base、TIMER_CFG_PERIODICASE);


ROM_TimerLoadSet (TIMER0_BASE、TIMER_A、2*(g_ui32SysClock/8000));
ROM_TimerLoadSet (Timer1_base、timer_A、2*(g_ui32SysClock/9000));
ROM_TimerLoadSet (TIMER2_base、TIMER_A、2*(g_ui32SysClock/10000));
ROM_TimerLoadSet (TIMER3_base、TIMER_A、2*(g_ui32SysClock/11000));

ROM_TimerLoadSet (TIMER0_BASE、TIMER_B、2*(g_ui32SysClock/8500));
ROM_TimerLoadSet (Timer1_base、timer_B、2*(g_ui32SysClock/9500));
ROM_TimerLoadSet (TIMER2_base、TIMER_B、2*(g_ui32SysClock/10500));
ROM_TimerLoadSet (TIMER3_base、TIMER_B、2*(g_ui32SysClock/11500));


ROM_IntEnable (INT_TIMER0A); //设置计时器超时的中断。
ROM_IntEnable (INT_TIMER1A);
ROM_IntEnable (INT_TIMER2A);
ROM_IntEnable (INT_TIMER3A);

ROM_IntEnable (INT_TIMER0B);
ROM_IntEnable (INT_TIMER1B);
ROM_IntEnable (INT_TIMER2B);
ROM_IntEnable (INT_TIMER3B);


ROM_TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT);
ROM_TimerIntEnable (Timer1_base、timer_TINA_TIMEOUT);
ROM_TimerIntEnable (TIMER2_base、TIMER_TINA_TIMEOUT);
ROM_TimerIntEnable (TIMER3_base、TIMER_TINA_TIMEOUT);

ROM_TimerIntEnable (TIMER0_BASE、TIMER_TIMB_TIMEOUT);
ROM_TimerIntEnable (Timer1_base、TIMER_TIMB_TIMEOUT);
ROM_TimerIntEnable (TIMER2_base、TIMER_TIMB_TIMEOUT);
ROM_TimerIntEnable (TIMER3_base、TIMER_TIMB_TIMEOUT);



ROM_TimerEnable (TIMER0_BASE、TIMER_A); //启用计时器。
ROM_TimerEnable (Timer1_base、timer_A);
ROM_TimerEnable (TIMER2_base、TIMER_A);
ROM_TimerEnable (TIMER3_base、TIMER_A);

ROM_TimerEnable (TIMER0_BASE、TIMER_B);
ROM_TimerEnable (Timer1_base、Timer_B);
ROM_TimerEnable (TIMER2_base、TIMER_B);
ROM_TimerEnable (TIMER3_base、TIMER_B);

IntMasterEnable();

while (1)
{
//在计时器运行时永久循环
。}
}

当我运行此代码时,引脚 PC4 PC5 PC6和 PC7的输出频率会降低(到2000 KHz Aprox), 使用调试器、我看到 Timer0IntHandlerB、Timer1IntHandlerB、Timer2IntHandlerB、Timer3IntHandlerB 的中断永远不会发生、我不知道这为什么不起作用、我的目的是在频率为偶数时生成8平方信号... 问题出在哪??、
更新了启动文件以支持8个计时器的中断。

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

    使用子计时器时、您需要使用参数 TIMER_CFG_SPLIT_PAIR 来配置计时器

    请参阅示例

    D:\ti\TivaWare_C_Series-2.1.3.156\examples\peripherals\timer\period_16bit.c
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢 Amit
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Sergio 和读者、

    答复中 Amit 的补充内容:

    我以前见过这种怀疑。 务必了解每个计时器(如 Timer0、Timer1...) 由一个寄存器块控制。 "子定时器"-与 TimerA 和 TimerB 一样-驻留在同一寄存器组内。 Tivaware Timer API 函数使用传递的参数访问寄存器、对于大多数参数、如果您在 TimerA 完成配置后"意外"调用 TimerB 配置、则实际上会覆盖第一个调用。

    换言之、在以后设置 TimerB 时、您会取消配置 TimerA。 这就是 TIMER_CFG_SPLIT_PAIR 的作用。 为了完全理解它、用户可以打开 timers.c 文件并查看 Tivaware 实际上在那里做了什么、并将其与数据表上的寄存器文档进行比较。

    顺便说一下、这是不对的、但您也可以使用 PWM 来生成您的方形信号、它们实际上更方便。

    此致

    布鲁诺