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.

[参考译文] TM4C1294NCPDT:Tiva TM4C 计时器在16位周期模式和 PWM 模式之间切换

Guru**** 2535750 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/1165258/tm4c1294ncpdt-tiva-tm4c-timer-switch-between-16-bit-periodic-and-pwm-modes

器件型号:TM4C1294NCPDT
Thread 中讨论的其他器件:EK-TM4C1294XL

您好!

我正在使用 EK-TM4C1294XL EVM。  我需要在 Timer3的16位周期模式和 PWM 模式(同一引脚)之间切换。  如果我之前在带有交替时钟源的16位周期模式中使用定时器、则带有系统时钟源的定时器 PWM 模式不能正常工作。

在下面的代码中、我已经用一个交替时钟源将定时器配置为16位周期模式。 我禁用计时器。 然后使用系统时钟源将其配置为16位 PWM 模式:  

#include <stdbool.h>
#include <stdint.h>
#include <time.h>
#include "driverlib/gpio.h"
#include "driverlib/hibernate.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "inc/hw_hibernate.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"

void Timer3AIntHandler(void) {
    MAP_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
}

void clock_init(void) {
    // System Clock 120 MHz
    MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120E6);

    // Alternating Clock RTCOSC 32768 Hz
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
    while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_HIBERNATE)) {
    }
    MAP_HibernateEnableExpClk(0);// Enable the Hibernation module for operation.
    while (!(HWREG(HIB_RIS) & HIB_RIS_WC))
        ;                                          // Wait for 32.768kHz clock to stabilize.
    MAP_HibernateClockConfig(HIBERNATE_OUT_SYSCLK);// 32.768 kHz Osc, Output Hibernate Clk
    MAP_HibernateRTCEnable();
    MAP_HibernateRTCSet(0);// Load initial RTC value.
    MAP_SysCtlAltClkConfig(SYSCTL_ALTCLK_RTCOSC);
}

void timer_init(void) {
    // T3CCP0: TIMERA :PA.6
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
    while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER3)) {}
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)) {}
    MAP_GPIOPinConfigure(GPIO_PA6_T3CCP0);
    MAP_GPIOPinTypeTimer(GPIO_PORTA_BASE, GPIO_PIN_6);
}

void set_timer_periodic_mode(void) {
    // MAP_TimerClockSourceSet(TIMER3_BASE, TIMER_CLOCK_SYSTEM);
    MAP_TimerClockSourceSet(TIMER3_BASE, TIMER_CLOCK_PIOSC);// alternating clock
    MAP_TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC_UP);
    // uint32_t cycles = 120E3;// System clock: 1 ms timeout
    uint32_t cycles = 32;// Alternating clock: 1 ms timeout
    MAP_TimerPrescaleSet(TIMER3_BASE, TIMER_A, cycles / 65536);
    MAP_TimerLoadSet(TIMER3_BASE, TIMER_A, cycles);
    TimerIntRegister(TIMER3_BASE, TIMER_A, Timer3AIntHandler);
    MAP_TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
    MAP_IntEnable(INT_TIMER3A);
    MAP_IntPrioritySet(INT_TIMER3A, 0xA0);
    MAP_TimerEnable(TIMER3_BASE, TIMER_A);
}

void disable_timer(void) {
    MAP_IntDisable(INT_TIMER3A);
    MAP_TimerIntDisable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
    TimerIntUnregister(TIMER3_BASE, TIMER_A);
    MAP_TimerDisable(TIMER3_BASE, TIMER_A);
}

void set_timer_pwm_mode(void) {
    MAP_TimerClockSourceSet(TIMER3_BASE, TIMER_CLOCK_SYSTEM);
    MAP_TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM);
    uint32_t cycles    = 120E6 / 100;// PWM frequency: 100 Hz
    uint16_t load      = cycles % 65536;
    uint8_t  prescalor = cycles / 65536;
    uint32_t period    = load + prescalor * 65536;
    uint32_t duty      = period / 2;// Dutycyle:  50%
    MAP_TimerPrescaleSet(TIMER3_BASE, TIMER_A, prescalor);
    MAP_TimerLoadSet(TIMER3_BASE, TIMER_A, load);
    MAP_TimerPrescaleMatchSet(TIMER3_BASE, TIMER_A, duty / 65536);
    MAP_TimerMatchSet(TIMER3_BASE, TIMER_A, duty % 65536);
    MAP_TimerEnable(TIMER3_BASE, TIMER_A);
}

int main(void) {
    clock_init();

    MAP_IntMasterEnable();

    timer_init();

    // Timer3 as 16 bit periodic timer with timeout interrupt
    set_timer_periodic_mode();

    // Disable timer
    disable_timer();

    // Timer3 in PWM mode
    set_timer_pwm_mode();

    while (1) {
    }
}

只有在16位周期模式下使用交替时钟源时、才会出现开关问题。 是否有人可以指导我是否在计时器模式之间正确切换?

谢谢、

哈桑

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

    您好、Hassan、

    您并不是这样完全禁用计时器3外设、因此我建议您尝试使用

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER3);

    作为禁用序列的一部分、然后 针对 SET_TIMER_PWM_MODE 添加一行

    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);

    执行的第一行。

    查看这是否解决了您的问题。

    此致、

    Ralph Jacobi

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

     您好 Ralph、

    感谢您的回答。 我已添加 Timer3外设禁用和启用、但问题仍然存在。

     

    #include <stdbool.h>
    #include <stdint.h>
    #include <time.h>
    
    #include "driverlib/gpio.h"
    #include "driverlib/hibernate.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/rom_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    #include "inc/hw_hibernate.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    
    void Timer3AIntHandler(void) {
        MAP_TimerIntClear(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
    }
    
    void clock_init(void) {
        // System Clock 120 MHz
        MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120E6);
    
        // Alternating Clock RTCOSC 32768 Hz
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_HIBERNATE);
        while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_HIBERNATE)) {
        }
        MAP_HibernateEnableExpClk(0);// Enable the Hibernation module for operation.
        while (!(HWREG(HIB_RIS) & HIB_RIS_WC))
            ;                                          // Wait for 32.768kHz clock to stabilize.
        MAP_HibernateClockConfig(HIBERNATE_OUT_SYSCLK);// 32.768 kHz Osc, Output Hibernate Clk
        MAP_HibernateRTCEnable();
        MAP_HibernateRTCSet(0);// Load initial RTC value.
        MAP_SysCtlAltClkConfig(SYSCTL_ALTCLK_RTCOSC);
    }
    
    void timer_init(void) {
        // T3CCP0: TIMERA :PA.6
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
        while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER3)) {}
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)) {}
        MAP_GPIOPinConfigure(GPIO_PA6_T3CCP0);
        MAP_GPIOPinTypeTimer(GPIO_PORTA_BASE, GPIO_PIN_6);
    }
    
    void set_timer_periodic_mode(void) {
        // MAP_TimerClockSourceSet(TIMER3_BASE, TIMER_CLOCK_SYSTEM);
        MAP_TimerClockSourceSet(TIMER3_BASE, TIMER_CLOCK_PIOSC);// alternating clock
        MAP_TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PERIODIC_UP);
        // uint32_t cycles = 120E3;// System clock: 1 ms timeout
        uint32_t cycles = 32;// Alternating clock: 1 ms timeout
        MAP_TimerPrescaleSet(TIMER3_BASE, TIMER_A, cycles / 65536);
        MAP_TimerLoadSet(TIMER3_BASE, TIMER_A, cycles);
        TimerIntRegister(TIMER3_BASE, TIMER_A, Timer3AIntHandler);
        MAP_TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
        MAP_IntEnable(INT_TIMER3A);
        MAP_IntPrioritySet(INT_TIMER3A, 0xA0);
        MAP_TimerEnable(TIMER3_BASE, TIMER_A);
    }
    
    void disable_timer(void) {
        MAP_IntDisable(INT_TIMER3A);
        MAP_TimerIntDisable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
        TimerIntUnregister(TIMER3_BASE, TIMER_A);
        MAP_TimerDisable(TIMER3_BASE, TIMER_A);
    }
    
    void set_timer_pwm_mode(void) {
        MAP_TimerClockSourceSet(TIMER3_BASE, TIMER_CLOCK_SYSTEM);
        MAP_TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM);
        uint32_t cycles    = 120E6 / 100;// PWM frequency: 100 Hz
        uint16_t load      = cycles % 65536;
        uint8_t  prescalor = cycles / 65536;
        uint32_t period    = load + prescalor * 65536;
        uint32_t duty      = period / 2;// Dutycyle:  50%
        MAP_TimerPrescaleSet(TIMER3_BASE, TIMER_A, prescalor);
        MAP_TimerLoadSet(TIMER3_BASE, TIMER_A, load);
        MAP_TimerPrescaleMatchSet(TIMER3_BASE, TIMER_A, duty / 65536);
        MAP_TimerMatchSet(TIMER3_BASE, TIMER_A, duty % 65536);
        MAP_TimerEnable(TIMER3_BASE, TIMER_A);
    }
    
    int main(void) {
        clock_init();
    
        MAP_IntMasterEnable();
    
        timer_init();
    
        // Timer3 as 16 bit periodic timer with timeout interrupt
        set_timer_periodic_mode();
    
        // Disable timer
        disable_timer();
    
        MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER3);
        MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
        while (!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER3)) {}
    
        // Timer3 in PWM mode
        set_timer_pwm_mode();
    
        while (1) {
        }
    }
    

    此致、

    哈桑  

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

    您好、Hassan、

    很抱歉、回复延迟、但我已使用您的代码重新创建问题、并尝试通过解决问题的方式配置此问题。

    我唯一能够实现的分辨率是使用 PIOSC 作为备用时钟源、而不是 SYSCTL_ALTCLK_RTCOSC。

    我深入探究了 TM4C129x 器 件上通用计时器的备用时钟源、我发现在过去、使用通用计时器的系统时钟以外的时钟源存在问题。 从我可以看出、调查结果是 PIOSC 和系统时钟是有效的时钟源、但使用其他备用时钟源可能会导致意外行为、应避免。 此项本应作为勘误项发布、但尚未发布。 但是、在 TivaWare 中、 这一点由用于 TimerClockSourceSet API 的措辞反映、该措辞声明如下:

    //! This function sets the clock source for both timer A and timer B for the
    //! given timer module.  The possible clock sources are the system clock
    //! (\b TIMER_CLOCK_SYSTEM) or the precision internal oscillator
    //! (\b TIMER_CLOCK_PIOSC).

    遗憾的是、所有这些都是我在团队中的前期工作、负责调查的专家不再支持此器件、因此我需要进一步探究在发现问题后未发布勘误表的原因。

    除勘误表发布外、对于您的系统、您需要使用 PIOSC 作为通用定时器的备用时钟、以便根据需要正常工作。

    此致、

    Ralph Jacobi

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

    您好、Ralph、

    感谢你的帮助。 好的、那么我将在32位模式下使用系统时钟来满足我们的要求。 实际上、作为交替时钟源的 PIOSC 不是很精确。

    此致、

    哈桑