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.

关于TM4C1290 timer设置为pwm模式 并在下一次超时同时更新周期以及占空比的问题

大家好,

我将TM4C1290的定时器配置为pwm模式时,无论上升沿还是下降沿事件触发同步更新pwm的周期和占空比时(占空比保证为50%),都会出现问题(并非必然)。

比如:1)当周期变化(单位us)如:10us开始以5us增量递增,当达到50us后又以5us减量递减回到10us,以此循环。 无论上、下边缘事件更新都现象正常

2)当周期变化(单位us)如:10us开始以10us增量递增,当达到50us后又以10us减量递减回到10us,以此循环。 下边缘事件更新正常,上升沿事件更新不正常

3)当周期变化(单位us)如:10us开始以20us增量递增,当达到50us后又以20us减量递减回到10us,以此循环。 下边缘和上升沿事件都更新不正常

当我只更新周期而不更新占空比时(固定占空比控制寄存器值),无论上升沿还是下降沿事件更新,如何更新都不会出问题。

以下是我捕捉的一组异常波形:(异常点本应是20us的周期,占空比50%)

  • 1.异常的那几个小波形是否有规律呢?
    2.观察异常的时候主频是否产生了变化
    3.是否观察了寄存器中pwm的值
  • 您好,

    1、这种异常是有规律的,都是同一个点出现问题

    2、主频没去测量

    3、我将pwm周期拖长(1ms,异常存在) ,打印出pwm的值与我的预期是一样的。

  • 另外能否上传或私信一下您现在的代码?您是使用的是TI开发板还是您自制的板子?
  • 您好,

    板子是我们自制的,代码如下

    /* timer configuration */
    GPIOPinConfigure(GPIO_PL7_T1CCP1);
    GPIOPinTypeTimer(GPIO_PORTL_BASE, GPIO_PIN_7);
    TimerConfigure(TIMER1_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);
    HWREG(TIMER1_BASE + TIMER_O_TBMR)|=0x00000500; // update on the next timeout.
    TimerControlLevel(TIMER1_BASE,TIMER_B,0);
    TimerControlEvent(TIMER1_BASE, TIMER_B, TIMER_EVENT_POS_EDGE); //TIMER_EVENT_NEG_EDGE);
    TimerIntClear(TIMER1_BASE, TIMER_CAPB_EVENT);
    TimerIntEnable(TIMER1_BASE,TIMER_CAPB_EVENT);
    IntEnable(INT_TIMER1B);
    /* timer start */
    TimerLoadSet(TIMER1_BASE, TIMER_B, 120000 & 0xFFFF); // 1ms period
    TimerPrescaleSet(TIMER1_BASE,TIMER_B, (120000 >> 16)&0xff);
    TimerMatchSet(TIMER1_BASE,TIMER_B, 60000 & 0xFFFF);  // 50% duty
    TimerPrescaleMatchSet(TIMER1_BASE,TIMER_B, (60000 >> 16)&0xff);
    TimerEnable(TIMER1_BASE, TIMER_B);

    /* interrupt handle */
    void Timer1BIntHandler(void)
    {
        static uint32_t period = 120000; // 1ms
        static uint32_t duty = 0;
        static uint8_t inc_flag = 1;
        // printf("timer1B int\n");
        if (inc_flag)
        {
            period += 120000;
            if (period >= 600000)
            {
                inc_flag = 0;   
            }
        }
        else
        {
            period -= 120000;
            if (period <= 120000)
            {
                inc_flag = 1;   
            }
        }
        duty = period >> 1;
        TimerLoadSet(TIMER1_BASE, TIMER_B, period&0xffff);       // period
        TimerPrescaleSet(TIMER1_BASE, TIMER_B, (period >> 16)&0xFF);
        TimerMatchSet(TIMER1_BASE, TIMER_B, duty&0xffff);          // duty
        TimerPrescaleMatchSet(TIMER1_BASE, TIMER_B, (duty >> 16)&0xFF);
        // TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT);
        TimerIntClear(TIMER1_BASE, TIMER_CAPB_EVENT);
    }