gpt4 book ai didi

c - 如何使用 pwm atmega avr 增加亮度或调暗 LED

转载 作者:行者123 更新时间:2023-11-30 16:26:19 26 4
gpt4 key购买 nike

我不知道为什么,LED 脉冲并没有增加亮度,而是每个脉冲之间的周期越来越短。这是从教程中复制的代码,在他的视频中效果很好,但对我来说效果不佳,即使在模拟器中也是如此。怎么会发生这种事?

使用 avr 328p。

#define F_CPU   20000000

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

double dutyCycle = 0;

int main(void)
{
DDRD = (1 << PORTD6);
TCCR0A = (1 << COM0A1) | (1 << WGM00) | (1 << WGM01);
TIMSK0 = (1 << TOIE0);
OCR0A = (dutyCycle/100.0)*255.0;
sei();

TCCR0B = (1 << CS00) | (1 << CS02);
while(1)
{
_delay_ms(100);
dutyCycle += 10;
if(dutyCycle > 100){
dutyCycle = 0;
}
}
}

ISR(TIMER0_OVF_vect){ OCR0A = (dutyCycle/100.0)*255;}

最佳答案

1) 如果某个变量在主代码和中断中同时使用,则必须将其标记为 volatile 。然后对它的每次读或写都会被编译为对相应存储单元的读/写。否则,编译器可以优化,最小化内存访问。因此,在主程序内部写入变量在中断中将不可见。

2) 为什么使用double?除非非常必要,否则不要使用浮点。 AVR没有对浮点运算的硬件支持,因此每个浮点运算将被表示为多个运算。在您的示例中,没有什么可以阻止使用从 0 到 255 变化的整数变量。即使您想使用 0-100 范围变量,您也可以使用整数算术重新计算它。

3) 请注意更新长度超过 1 个字节的变量。 AVR是8位架构。这意味着,更新内存中超过 8 位宽的变量需要一系列多个操作。 double 是 8 个字节长,需要太多这样的操作。中断可能在该系列中间的任何时刻触发,这意味着 ISR 内获得的变量值将仅部分更新,从而导致不可预测的结果。在主代码中,在 cli() - sei() 中关闭 ISR 内部使用的且宽度超过 1 个字节的变量的任何更新。

3) 避免在 ISR 中进行硬计算。根据经验:任何 ISR 都应该尽快完成,所有密集计算都应该放在 ISR 之外。

4) 在此示例中,您根本不需要 ISR!您可以在主代码中编写 OCR0A。

关于c - 如何使用 pwm atmega avr 增加亮度或调暗 LED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53110480/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com