繁体   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