2014-01-21 49 views
0

我已经为Atmega128写了一个pwm代码。我在比较匹配时使用非反相脉冲的快速PWM模式,我需要在特定时间更改OCR0值。但它并没有改变。任何人都知道这里有什么问题?pwm值不变

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



uint8_t tick_1sec; 



void timer1_init(void) // 1 second timer 
{ 
    OCR1A = 15624; 

    TIMSK |= (1<<OCIE1A); 
    TCCR1B = (1<<WGM12);  //CTC mode 
    TCCR1B |= (1<<CS12)|(0<<CS11)|(1<<CS10);  
} 



ISR(TIMER1_COMPA_vect) //1 second interrupt 
{ 
    cli(); 
    tick_1sec = 1; 
    sei();   
} 



void timer0_init(void) // fast pwm with OC0 non-inverting mode 
{ 
    TCCR0 = (1<<FOC0)|(1<<WGM01)|(1<<WGM00); 
    TCCR0 |= (1<<COM01)|(0<<COM00); 
    TCCR0 |= (1<<CS02)|(1<<CS01)|(1<<CS00); 
    OCR0 = 63; 
    TIMSK |= (1<<OCIE0); 
} 



int main(void) 
{ 
    uint8_t t = 0; 

    DDRB = 0xFF; 

    timer0_init();  
    timer1_init(); 
    sei(); 

    while(1){ 

     if (tick_1sec) 
     { 
      tick_1sec = 0; 
      t++; 
      if (t == 10){ 
       OCR0 = 127; 
      } 
      else if (t == 20){ 
       OCR0 = 191; 
      } 
      else if (t == 30){ 
       OCR0 = 63; 
       t = 0; 
      } 
     } 
    } 

    return 0; 
} 
+0

请正确格式化您的代码,并使用四个空格。 –

+0

我编辑过它们。 –

回答

2

检查事项:

我建议宣布tick_1secvolatile,以防止过度优化的该寄存器编译器。

你的时钟频率是多少?您的ISR只会在您的CPU频率为16MHz(==> 16.000.000/1024/15624)时发送1s呼叫

您可能在您的硬件中有一个LED,您可以从a)ISR b)第一个if()main,看看是否已经达到。

更新:“挥发性”

通过@skyrift在他的评论中提供的链接是非常值得一读。

当你使用Atmel Studio时,编译你的代码一次带/不带volatile关键字,并比较编译器正在做什么==>解决方案资源管理器/输出文件/ * .lss ...你会看到每个C语句以及如何编译器将其转换为机器代码......在使用微型计算机时,一段时间内值得一试的练习...

+1

这几乎肯定是问题所在 - avr-gcc会清除大部分变量,这些变量在未声明为volatile的中断中被修改。在这里看到第5部分:http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=89843&start=all&postdays=0&postorder=asc – skyrift

+0

我花时间看它并修改了代码,就像你跟其他部分一样一样。我不知道确切的原因,但后来才奏效。将Tick_1sec声明为volatile变量很可能是原因。谢谢.. –