简体   繁体   English

16 位定时器 PWM LED 调光器

[英]16-bit Timer PWM LED Dimmer

I am new to AVR C Programming, I am testing a simple PWM using 16-bit timer on Atmega328p Counter/Timers which is suppose to act as a dimmer to an LED.我是 AVR C 编程的新手,我正在使用 Atmega328p 计数器/定时器上的 16 位定时器测试一个简单的 PWM,它假设充当 LED 的调光器。

My Code:我的代码:

#define F_CPU 16000000UL

void initTimer();

int x = 1;
int n = 1000;

int main(void)
{   

    initTimer();

    DDRB |= (1 << PB1)| (1 << PB2);

    while(1)
    {
        x++; 

        if(x > 65) {
            x = 1;
        }
    }
}

void initTimer() {

    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); 
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); 
    // used for TOP, makes for 50 Hz PWM
    ICR1 = 40000; 
    OCR1A = n * x; 

} 

ISR(TIMER1_OVF_vect)
{
    OCR1A = n * x;  
}

Problem is that it doesn't display the dimming effect, the brightness of the LED stays constant as to whatever value I set for OCR1A (PB1) output pin initially, its suppose to change value as the interrupt happen but its just not doing this, this is suppose to be simple test what am I doing wrong?问题是它不显示调光效果,对于我最初为 OCR1A (PB1) 输出引脚设置的任何值,LED 的亮度保持不变,它假设在中断发生时改变值,但它只是不这样做,这应该是简单的测试我做错了什么?

Update:更新:

As advice I enable the interrupts using the TIMSK1 register and SEI(), however still the same issue the LED brightness stays constant as to whatever the original value of OCR1A that was specified in the initTimer().作为建议,我使用 TIMSK1 寄存器和 SEI() 启用中断,但是仍然存在相同的问题,无论 initTimer() 中指定的 OCR1A 的原始值如何,LED 亮度都保持不变。

int main(void)
{   
    initTimer();
    DDRB |= (1 << PB1)| (1 << PB2);

    while(1)
    {
        x++; 
        if(x > 65) {
            x = 1;
        }
    }
}

void initTimer() {

    ICR1 = 40000; 
    OCR1A = n * x; 
    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); 
    TIMSK1 |= (1 << ICIE1);
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); 
    sei();
}

ISR (TIMER1_COMPA_vect)
{
    OCR1A = n * x;  
}

Although I tried an alternative approach and that gives me the dimming affect:虽然我尝试了另一种方法,这给了我调光效果:

int main(void)
{   

    initTimer();

    DDRB |= (1 << PB1)| (1 << PB2);

    while(1)
    {
        _delay_ms(20);
        OCR1A = n * 4; 
        _delay_ms(20);
        OCR1A = n * 8;
        _delay_ms(20);
        OCR1A = n * 15; 
        _delay_ms(20);
        OCR1A = n * 25;
        _delay_ms(20);
        OCR1A = n * 1; 

    }
}

void initTimer() {

    ICR1 = 40000; 
    OCR1A = n * x; 
    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);   
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); 

} 

So it seems the problem is with the interrupts since PWM affect works but its just not working with the interrupt handler.所以看起来问题出在中断上,因为 PWM 影响有效,但它只是不与中断处理程序一起工作。

The first thing that jumps out at me is x and n should be volatile.我首先想到的是 x 和 n 应该是 volatile 。 You also should enable the interrupt in TIMSK0 register.您还应该在 TIMSK0 寄存器中启用中断。 Also enable interrupts by calling sei.还可以通过调用 sei 来启用中断。

If I were you, I'd start with some know good sample code.如果我是你,我会从一些熟悉的示例代码开始。 The page I mentioned has a example that fires an interrupt every 4ms.我提到的页面有一个示例,它每 4 毫秒触发一次中断。 Take that code and toggle the led on and off.获取该代码并打开和关闭 LED。

Another problem is you are changing x without regard to whether or not the isr was called.另一个问题是你在改变 x 而不管 isr 是否被调用。 So in effect you will get a random x each time in the isr.所以实际上你每次都会在 isr 中得到一个随机的 x。 This code is simple enough it might get stuck in a simple pattern.这段代码很简单,可能会卡在一个简单的模式中。 Instead move the setting of x to your isr.而是将 x 的设置移动到您的 isr。

Here is a good intro to avr timers: https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328这是 avr 计时器的一个很好的介绍: https : //sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328

ICR1 = 40000; 
OCR1A = n * x; 
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);   
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);

This is wrong, you need to configure TCCR1A and TCCR1B before initializing ICR1 and OCR1A.这是错误的,需要在初始化ICR1和OCR1A之前配置TCCR1A和TCCR1B。 See this answer for more details.有关更多详细信息,请参阅此答案

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

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