Attiny 9 上的脉宽调制 (PWM)

Pulse width modulation (PWM) on Attiny 9

我正在使用 Attiny 9。

我将 LED 连接到 PB1。 我编写了以下代码并将其上传到 Attiny 9。

#define F_CPU 800000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <avr/power.h>

#define D0 PB1

int main(void)
{
  power_adc_disable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  TCCR0A |= (1<<WGM00)|(1<<WGM01)|(1<<COM0B1);
  TCCR0B |= (1<<WGM03)|(1<<WGM02)|(1<<CS00);

  DDRB |= 1<<D0;

  PORTB |= 1<<D0;
  _delay_ms(3000);
  PORTB &= ~(1<<D0);

  for (uint8_t i = 255; 247 < i; --i)
  {
    OCR0B = i;
    _delay_ms(70);
  }

  for (uint8_t i= 247; -1 < i; --i)
  {
    OCR0B = i;
    _delay_ms(4);
  }

  while(1){
    sleep_enable();
    sleep_cpu();
  }

  return 0;
}

我想让LED变亮变暗。但是在我上传代码后,LED 持续亮起。我还阅读了 Attiny 9 的数据表。我遵循了如何使用 PWM。但是没用。

怎么了?

该代码存在许多问题。

  1. 您将处理器置于断电模式,根据数据表,该模式会禁用时钟并且只能发生异步事件。
  2. 您将其设置为使用以 OCR0A 为顶部的快速 PWM 模式,但您并未在任何地方设置 OCR0A。如果您的计时器计数不够高,您将不会生成任何比较匹配项。从您的循环看来,您希望计时器计数到 255。
  3. 您只能在 while 循环之前更改 PWM 的占空比,因此即使您的 PWM 设置正确,您也永远无法看到您想要的 LED 脉冲。

这里有一个 link 示例,说明如何设置 PWM 并更改其占空比: http://allaboutavr.com/index.php/2017/05/13/chapter-5-timers-and-pwm-pulse-width-modulation/

像这样打字:

#include <avr/io.h>
#include <util/delay.h>

#define D0 PB1

int main(void)
{
    DDRB |= 1<<D0;

    TCCR0A |= (1<<WGM00)|(1<<COM0B1);
    TCCR0B |= (1<<WGM02)|(1<<CS00);

    while (1) {
        for (uint8_t i = 0; i < 255; i++) {
            OCR0B = i;
            _delay_ms(4);
        }

        for (uint8_t i = 255; i >= 0; i--) {
            OCR0B = i;
            _delay_ms(4);
        }
    }
}