簡體   English   中英

Arduino (AVR ATMega328) Timer1 似乎沒有在正確的時間觸發

[英]Arduino (AVR ATMega328) Timer1 does not seem to trigger at the right time

由於 Arduino 上的 PWM 引腳數量最少,我正在嘗試實現二進制代碼調制(也稱為位角調制,BAM),作為 PWM 的替代方案。 使用 BAM 背后的想法是 LED 將在離散時間打開和關閉,從而有效地控制 LED 的亮度。 這個“時間”由字節中相應的位值決定。

例如,如果設置為值 85(共 255 個),即二進制 01010101,這意味着 LED 將交替打開和關閉狀態,但時間長度不同。 第 0 位“1”表示 LED 將亮起 1 個滴答聲,而第 6 位“0”表示 LED 將熄滅 32 個滴答聲,依此類推。 目標是這將足夠快地將 LED 切換到人眼不會注意到的地方,根據值產生亮度錯覺。 較高的值與更亮的 LED 顏色有關。

在執行此操作時,我注意到可以看到 LED 上的刷新率。 我可以看到 LED 什么時候亮,什么時候滅。 它似乎每半秒切換一次端口。 由於我沒有示波器,所以迫不及待想知道。 我在 Arduino 上使用 Timer1 每 8 微秒(125KHz)中斷一次。 每次中斷都會更新連接到 LED 的 PIN 上的狀態,無論是打開還是關閉。

我已經嘗試使用Timer1 庫和通過寄存器來執行此操作,但兩者似乎都會產生錯誤的結果。 目前,我的代碼正在切換一個引腳。 如果中斷正常工作(每次更新8US),那么我應該看到藍色的LED(連接到引腳8)切換狀態每一個刻度。 我的眼睛應該看到的只是一個 LED 燈。

注意:在 Timer1 庫和寄存器之間切換時,我的 ISR 只是在名稱上發生了變化。 請參閱代碼中的注釋。

有人可以看看我的 Timer 實現。 我有一種感覺,這就是問題所在,但我無法弄清楚。

    #include <TimerOne.h>
    #include <SPI.h>
    #include "avr/io.h"
    #include "LEDArray.h"

    #define TIMER_US        (8) //125KHz in microseconds
    #define NUM_OF_LEDS     ((LEDS_PER_ROW)*(LEDS_PER_COL))
    #define LEDS_PER_ROW    (8)
    #define LEDS_PER_COL    (8)

    volatile byte BAM_pos = 0;
    volatile byte BAM_tick = 0;

    // OutputDataH, OutputDataM, and OutputDataL
    // totals to 24 bits. There are 24 pins
    // that I need to shift data to. These three variables
    // will hold the data value corresponding to the associated 
    // bit level
    volatile byte OutputDataH = 0;
    volatile byte OutputDataM = 0;
    volatile byte OutputDataL = 0;
    //bool UpdateLedOutput = 1;

    volatile byte green = 0;
    volatile byte blue = 0;

    void InitTimer(){
      TCCR1A = 0;
      TCCR1B = 0;
      TCNT1  = 0;

      OCR1A = 127;            // compare match register == 16MHz/((prescalar=1)*125KHz) - 1
      TCCR1B |= (1 << WGM21);   // CTC mode
      TCCR1B |= (1<<CS20);    // 1x prescaler 
      TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
    }

    void InitPins(){
        // initialize the digital pin as an output.
        SHIFT_REGISTER |= (DATA | CLOCK | SS );
        // set control pins as low
        SHIFT_PORT &= ~(DATA | LATCH | CLOCK);

            // initialize the led pins for testing
            pinMode(4, OUTPUT);
            pinMode(8, OUTPUT);
    }

    ISR(TIMER0_COMPA_vect){
    //void timerISR(){ //use this with Timer1 Library instead
        //ISR(TIMER1_COMPA_vect){
        //Move onto next bit, reset BAM state
        if(BAM_tick >= 120){ //8 + 16 + 32 + 64
            BAM_tick = 0;
            BAM_pos = 0;
        }

        // Move onto the next bit at these ticks. Ticks are in 8 microsecond increments
        if(BAM_tick==8 || BAM_tick == 24 || BAM_tick == 56){
            BAM_pos++;
        }

        BAM_pos %= 4; //wrap counter after going through four bits

    // if(UpdateLedOutput){ Change the LED state only when the bit position is updated

            //For every LED, look at enabled bit, if true determine corresponding LEDs_Output bits through the LEDs rgb values
            //There are 3 groups of LEDs, each using 1 byte (8 bits -> 8 pins)
            //We, therefore, have a HIGH, MIDDLE, and LOW byte values that we will shift out
            for(int i=0; i<8; i++){
                if( ((ledOutput.all) & (1<<i))){ 
                //ledOutput.all is of size 24 bits. each bit tells us whether the pin should be enabled for this tick or not
                    OutputDataH |= (1<<i);
                }
            }
            for(int i=8; i<16; i++){
                if( ((ledOutput.all) & (1<<i))){
                    OutputDataM |= (1<<i);
                }
            }
            for(int i=16; i<24; i++){
                if( ((ledOutput.all) & (1<<i))){
                    OutputDataL |= (1<<i);
                }
            }           

            UpdateLedOutput = 0;
    //  }

        //Update LED OUTPUT after we have reach the end of the bits time
    //  if(BAM_tick==8 || BAM_tick == 24 || BAM_tick == 56){
    //      UpdateLedOutput = 1;
    //  }

        //Consume the tick
        BAM_tick++;

        //Shift out the data
        /*Latch_Low();
        sendData(OutputDataH);
        sendData(OutputDataM);
        sendData(OutputDataL);
        Latch_High();
        Latch_Low();
        */


        //different shifting data
    /*
        if(green & (1<<BAM_pos))
            //PORTD |= (1<<PORTD4);
            digitalWrite(4, LOW);
        else 
            digitalWrite(4, HIGH);
           //PORTD &= (0<<PORTD4);

        if(blue & (1<<BAM_pos))
            //PORTB |= (1<<PORTB0);
            digitalWrite(8, LOW);
        else 
            digitalWrite(8, HIGH);//PORTB &= (0<<PORTB0);
        */
        digitalWrite(8, digitalRead(8) ^1);
    }




    void setup() {
         InitData();
         InitPins();
         InitTimer();
        //Timer1.initialize(TIMER_US); 
        //Timer1.attachInterrupt(timerISR);
         EnableSPI(); //Enable SPI as Master
         Serial.begin(9600);
    }


    void loop() {
        // do almost nothing!
       while(1){
         PulseThroughColors();
       }
    }

    //This should slowly increase the brightness of the corresponding pin on the RGB LED
    // Blue should increase brightness, and then decrease it in the opposite manner, indefinitely
    void PulseThroughColors(){
        blue = 0;
        green = 0;
        int i=0;
        for(i=0; i< 255; i++)
            blue = i;
        for (i=255; i>0; i--)
            blue = 0;
        //for(i=0; i< 255; i++)
        //  green = i;
        //for (i=255; i>0; i--)
        //  green  = 0;
    }

所以我的代碼中有兩個錯誤。 首先,我增加了計數器以 250KHz (4us) 中斷。 其次,我設置 BAM 級別(接近 ISR 末尾)的方式不正確。 我忘了我有一個共陽極 LED,這意味着為了打開顏色,我必須將相應的引腳設置為低電平,而不是我的示例中所示的高電平。 固定段位於下方。 謝謝所有看過這個的人。

void InitTimer(){
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;

    TCCR1A = B00000000;
    TCCR1B = B00001011;
    OCR1A=30;
    TIMSK1 = B00000010;
}

ISR(...){
 ........
if(green & (1<<BAM_pos))
    PORTD &= ~(1<<PORTD4);
else 
   PORTD |= (1<<PORTD4);

if(blue & (1<<BAM_pos))
    PORTB &= ~(1<<PORTB0);
else 
    PORTB |= (1<<PORTB0);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM