当使用pwm时,_delay_ms似乎不工作。

问题描述 投票:0回答:2

我对单片机编程比较陌生,所以我开始在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灯从变暗到全亮再到全亮的过程中不断切换

c microcontroller avr avr-gcc attiny
2个回答
1
投票

__delay_ms() 是由编译器转换为循环浪费指令,所以只要你的 F_CPU 匹配当前处理器的速度,那么它应该按照预期工作。

我会在你的代码中寻找其他不符合你期望的地方。

上电时的半秒延迟并不是一个很好的诊断测试,因为它发生得很快,只有一次,而且当时可能还有其他事情发生。

也许可以尝试在两个不同的亮度水平之间闪烁,中间有500ms的延迟。在视觉上,这应该是毫不含糊的。

如果这样做符合预期,那么也许可以尝试做一个亮度斜坡并改变循环内的延迟,看看是否符合预期。

最终你会努力到一些不符合预期的东西,然后你就会知道问题出在哪里。你仍然有可能不明白是怎么回事,但至少你可以在这里提出一个更具体的问题,更有可能得到一个有用的答案。

汇报一下你的结果吧!


1
投票

我觉得自己很笨... 这只是一个溢出的错误,因为我用的是 uint8_t 并设置 < 256 在for循环中,条件总是为真(255+1=0)。

我的解决方案是在循环中使用uint16_t。

© www.soinside.com 2019 - 2024. All rights reserved.