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。但是没用。
怎么了?
该代码存在许多问题。
- 您将处理器置于断电模式,根据数据表,该模式会禁用时钟并且只能发生异步事件。
- 您将其设置为使用以 OCR0A 为顶部的快速 PWM 模式,但您并未在任何地方设置 OCR0A。如果您的计时器计数不够高,您将不会生成任何比较匹配项。从您的循环看来,您希望计时器计数到 255。
- 您只能在 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);
}
}
}
我正在使用 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。但是没用。
怎么了?
该代码存在许多问题。
- 您将处理器置于断电模式,根据数据表,该模式会禁用时钟并且只能发生异步事件。
- 您将其设置为使用以 OCR0A 为顶部的快速 PWM 模式,但您并未在任何地方设置 OCR0A。如果您的计时器计数不够高,您将不会生成任何比较匹配项。从您的循环看来,您希望计时器计数到 255。
- 您只能在 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);
}
}
}