简体   繁体   English

如何使用Pwm Atmega AVR增加亮度或使LED变暗

[英]How to increase brightness or dim the LED using pwm atmega avr

I dont know why but instead of increasing brightness, LED pulses, the period between each pulse is getting shorter. 我不知道为什么,但不是增加亮度,而是增加LED脉冲,每个脉冲之间的间隔越来越短。 This is copied code from tutorial, in his video it worked fine but for me it didnt, even in simulator. 这是从教程中复制的代码,在他的视频中效果很好,但对我来说,即使在模拟器中也没有。 How can that happen? 怎么会这样

Using avr 328p. 使用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) If some variable is used simultaneously in the main code and in an interrupt, then it has to be marked as volatile . 1)如果在主代码和中断中同时使用某些变量,则必须将其标记为volatile Then every read or write to it will be compiled as reading/writing of the corresponding memory cell. 然后,对其的每次读取或写入都将被编译为相应存储单元的读取/写入。 Otherwise, the compiler can optimize, minimizing memory access. 否则,编译器可以进行优化,从而最大程度地减少内存访问。 So, writing to the variable inside the main program will not be visible in the interrupt. 因此,在中断中看不到写入主程序内部的变量。

2) Why are you using double ? 2)为什么要使用double Do not use floating point unless it strongly necessary. 除非非常有必要,否则不要使用浮点数。 AVR has no hardware support for the floating-point arithmetic, so each floating-point operation will be represented as multiple operations. AVR不支持浮点运算的硬件,因此每个浮点运算将表示为多个运算。 In your example, nothing stops from use integer variable which changes from 0 to 255. Even if you want to use 0-100 range variable, you can recalculate it using integer arithmetics. 在您的示例中,使用从0到255的整数变量不会停止任何事情。即使您要使用0-100范围变量,也可以使用整数算术重新计算它。

3) Be aware updating variables which are more than 1 byte long. 3)注意更新超过1个字节长的变量。 AVR is an 8-bit architecture. AVR是8位架构。 That means, updating of variables in memory more than 8-bit wide, requires a series of multiple operations. 这意味着,要更新内存中超过8位宽的变量,需要执行一系列的多次操作。 double which is 8 bytes long, requires too much of such operations. 长度为8个字节的double ,需要太多此类操作。 The interrupt may fire in any moment in the middle of that series, that means, the value of the variable, obtained inside the ISR will be updated only partially, causing unpredictable results. 该中断可能在该系列的中间时刻触发,这意味着在ISR内部获取的变量的值将仅部分更新,从而导致不可预测的结果。 In the main code eclose in cli() - sei() any update of variables which are used inside the ISR and more than 1 byte wide. 在主代码中, cli() - sei()任何更新都将在ISR内部使用,且变量的更新应超过1个字节。

3) Avoid hard calculations in the ISR. 3)避免在ISR中进行艰难的计算。 As a rule of thumb: any ISR should complete as soon as possible, all intense calculations should be placed outside the ISR. 根据经验:任何ISR都应尽快完成,所有密集的计算都应放在ISR之外。

4) In this example, you need no ISR at all! 4)在此示例中,您完全不需要ISR! You can write OCR0A just inside the main code. 您可以在主代码中编写OCR0A。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM