2014-01-21 46 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變量很可能是原因。謝謝.. –