_delay_ms 使用 pwm 时似乎不起作用
_delay_ms seems not to work when using pwm
我对微控制器编程还比较陌生,所以我开始在 ATtiny85 上进行试验。
第一个程序只是简单地打开一个 LED,然后稍微延迟一下(经典的闪烁程序)。
现在我想慢慢增加LED的亮度。这是代码:
#define F_CPU 1000000L
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#define LED PB0
void setup(void);
void loop(void);
void analogOutput(int8_t brightness);
int main(void)
{
setup();
while (1)
{
loop();
}
return 0;
}
void setup()
{
TCCR0A = (1 << WGM00) | (1 << WGM01);
TCCR0B = (1 << CS00) | (1 << CS01);
DDRB = (1 << LED);
PORTB = 0;
}
void loop()
{
int8_t brightness = 0;
analogOutput(brightness);
_delay_ms(500);
for (brightness = 0; brightness < 256; ++brightness)
{
analogOutput(brightness);
_delay_ms(10);
}
}
void analogOutput(int8_t brightness)
{
if (brightness == 0)
{
// digital output LOW
TCCR0A &= ~(1 << COM0A1);
PORTB &= ~(1 << LED);
}
else if (brightness == 255)
{
// digital output HIGH
TCCR0A &= ~(1 << COM0A1);
PORTB |= (1 << LED);
}
else
{
PORTB &= ~(1 << LED);
// analog output
TCCR0A |= (1 << COM0A1);
OCR0A = brightness;
}
}
我预计 LED 会关闭半秒,然后增加亮度。
但是如果我 运行 代码 LED 会变得更亮,就好像 _delay_ms(500)
被忽略了一样。
analogOutput
函数的灵感来源于Arduino库的函数
这里有什么问题?为什么延迟没有按预期工作?
编辑
我改变了我的循环功能,新内容:
void loop()
{
analogOutput(127);
_delay_ms(500);
analogOutput(255);
_delay_ms(500);
}
这很有效,我现在有一个 LED 灯可以不断地从暗淡到完全亮起然后再亮起。
__delay_ms()
被编译器转换为周期浪费指令,因此只要您的 F_CPU
与处理器的当前速度匹配,那么它应该按预期工作。
我会在您的代码中查找未按您预期工作的其他地方。
开机延迟半秒不是一个很好的诊断测试,因为它发生得很快,只有一次,而且那时可能还会发生其他事情。
也许可以尝试在两个不同的亮度级别之间闪烁 500 毫秒的延迟。从视觉上看,这应该是明确的。
如果按预期工作,则可以尝试进行亮度渐变并更改循环内的延迟以查看是否按预期工作。
最终你会遇到一些不符合预期的事情,然后你就会知道问题出在哪里。您仍然有可能不明白发生了什么,但至少您可以在这里提出更具体的问题,并且更有可能获得有用的答案。
报告你的结果!
我觉得很蠢。。这只是一个溢出错误,因为我在for循环中使用了uint8_t
并设置了< 256
,条件总是为真(255 + 1 = 0)。
我的解决方案是使用 uint16_t 作为循环
我对微控制器编程还比较陌生,所以我开始在 ATtiny85 上进行试验。
第一个程序只是简单地打开一个 LED,然后稍微延迟一下(经典的闪烁程序)。
现在我想慢慢增加LED的亮度。这是代码:
#define F_CPU 1000000L
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#define LED PB0
void setup(void);
void loop(void);
void analogOutput(int8_t brightness);
int main(void)
{
setup();
while (1)
{
loop();
}
return 0;
}
void setup()
{
TCCR0A = (1 << WGM00) | (1 << WGM01);
TCCR0B = (1 << CS00) | (1 << CS01);
DDRB = (1 << LED);
PORTB = 0;
}
void loop()
{
int8_t brightness = 0;
analogOutput(brightness);
_delay_ms(500);
for (brightness = 0; brightness < 256; ++brightness)
{
analogOutput(brightness);
_delay_ms(10);
}
}
void analogOutput(int8_t brightness)
{
if (brightness == 0)
{
// digital output LOW
TCCR0A &= ~(1 << COM0A1);
PORTB &= ~(1 << LED);
}
else if (brightness == 255)
{
// digital output HIGH
TCCR0A &= ~(1 << COM0A1);
PORTB |= (1 << LED);
}
else
{
PORTB &= ~(1 << LED);
// analog output
TCCR0A |= (1 << COM0A1);
OCR0A = brightness;
}
}
我预计 LED 会关闭半秒,然后增加亮度。
但是如果我 运行 代码 LED 会变得更亮,就好像 _delay_ms(500)
被忽略了一样。
analogOutput
函数的灵感来源于Arduino库的函数
这里有什么问题?为什么延迟没有按预期工作?
编辑
我改变了我的循环功能,新内容:
void loop()
{
analogOutput(127);
_delay_ms(500);
analogOutput(255);
_delay_ms(500);
}
这很有效,我现在有一个 LED 灯可以不断地从暗淡到完全亮起然后再亮起。
__delay_ms()
被编译器转换为周期浪费指令,因此只要您的 F_CPU
与处理器的当前速度匹配,那么它应该按预期工作。
我会在您的代码中查找未按您预期工作的其他地方。
开机延迟半秒不是一个很好的诊断测试,因为它发生得很快,只有一次,而且那时可能还会发生其他事情。
也许可以尝试在两个不同的亮度级别之间闪烁 500 毫秒的延迟。从视觉上看,这应该是明确的。
如果按预期工作,则可以尝试进行亮度渐变并更改循环内的延迟以查看是否按预期工作。
最终你会遇到一些不符合预期的事情,然后你就会知道问题出在哪里。您仍然有可能不明白发生了什么,但至少您可以在这里提出更具体的问题,并且更有可能获得有用的答案。
报告你的结果!
我觉得很蠢。。这只是一个溢出错误,因为我在for循环中使用了uint8_t
并设置了< 256
,条件总是为真(255 + 1 = 0)。
我的解决方案是使用 uint16_t 作为循环