atmega328P 上的软件 PWM 使用硬件定时器

问题描述

我想在 atmega328P(使用 16Mhz 晶体)上使用 timer1 来处理 3 个 LED 和伺服电机的软件 PWM。我开始意识到我轻微计算错误

ISR( TIMER1_COMPA_vect ) { // timer 1 ISR
    static uint8_t dutyCycle = 0 ;
    static uint16_t servopulse = 0 ;

    if ( servopulse == 0 )       PORTB |= (1 << 5);
    if ( dutyCycle == 0 ) {
        if ( redLed.pwm    > 0 ) PORTB |= (1 << 4);
        if ( yellowLed.pwm > 0 ) PORTB |= (1 << 3);
        if ( greenLed.pwm  > 0 ) PORTB |= (1 << 2);
    }
    
    if ( servopulse == servoPos )      PORTB &= ~(1 << 5);
    if ( dutyCycle ==    redLed.pwm )  PORTB &= ~(1 << 4);
    if ( dutyCycle == yellowLed.pwm )  PORTB &= ~(1 << 3);
    if ( dutyCycle ==  greenLed.pwm )  PORTB &= ~(1 << 2);
    
    dutyCycle ++ ; // overflows to 0 on it's own
    servopulse ++ ;
        
    if ( servopulse == overflowVal ) servopulse = 0 ; 
}

我之前用 60Hz 的 LED 成功地完成了这个方法。在第一个中断中,我打开所有 IO,在接下来的中断中,我使用一个计数器并轮询此计数器是否与其中一个占空比匹配,如果匹配,我将关闭 LED。计数器本身在 256 个周期后自然会溢出到 0。

我认为在我进行适当的数学运算之前,伺服器的 50Hz 信号不会那么难。

度数信息在1ms范围内。我的理论是,如果我想使用这种方法,两次中断之间的时间应该至少为 0.001s / 180 = 5,5556E-6,这意味着 ISR 频率为 180kHz(前提是我想要完整的 180 度分辨率)。

我还没有测试过这个特定的 ISR。我不知道我可以多久调用一次定时器中断,但我认为这可能会导致一些严重的性能问题。

我可以完成这项工作吗?如果是这样,我该怎么办?

我能想到的最好的另一件事是使用定时器寄存器来精确控制伺服脉冲的长度,并利用剩余的 18/20 毫秒来处理 LED PWM,但代价是失去 100% 的占空比能力。但我愿意接受建议。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)