我对单片机编程比较陌生,所以我开始在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
匹配当前处理器的速度,那么它应该按照预期工作。
我会在你的代码中寻找其他不符合你期望的地方。
上电时的半秒延迟并不是一个很好的诊断测试,因为它发生得很快,只有一次,而且当时可能还有其他事情发生。
也许可以尝试在两个不同的亮度水平之间闪烁,中间有500ms的延迟。在视觉上,这应该是毫不含糊的。
如果这样做符合预期,那么也许可以尝试做一个亮度斜坡并改变循环内的延迟,看看是否符合预期。
最终你会努力到一些不符合预期的东西,然后你就会知道问题出在哪里。你仍然有可能不明白是怎么回事,但至少你可以在这里提出一个更具体的问题,更有可能得到一个有用的答案。
汇报一下你的结果吧!
我觉得自己很笨... 这只是一个溢出的错误,因为我用的是 uint8_t
并设置 < 256
在for循环中,条件总是为真(255+1=0)。
我的解决方案是在循环中使用uint16_t。