2012-04-02 6 views
0

私の質問は、リアルタイムのデータロギングとマルチ割り込みに関するものです。 私はwinAVRによってMCU-ATMega 1280をプログラムして、直交エンコーダ(20um /ピッチ)からパルスを読み取り、フラッシュメモリ(シリアルSPIプロトコルのMicrochip SST25VF080B)にデータを保存しようとしています。エンコーダが動作を終了すると(約2分間)、MCUはメモリから画面にデータをエクスポートします。私のコードは以下の通りです。MCU-ATMegaによるリアルタイムデータロギングのためのマルチ割り込み1280

しかし、なぜ正しく動作しないのか分かりません。 2種類のバグがあります:1つのバグは突然トレンドから外れていますが、もう1つのバグはエンコーダがゆっくりと実行されても突然ジャンプするということです。ジャンプは、ターンがあるときだけ現れると思われる。

私は、ジャンプが予想したような傾向が起こるため、問題はデータの格納にしかないと考えています。私は、私がプログラムでやったようなISRを両方実行するかどうか尋ねたいだけです。 ISRが実行中に別のISRによって介入されるケースがありますか? atmega 1280のデータシートによると、1つのISRが発生している場合、以前の割り込みがルーチンを終了した後で他の割り込みが発生しないように見えます。

#include <stdlib.h> 
    #include <stdio.h> 
    #include <avr/interrupt.h> 
    #include <util/delay.h> 
    #include "USART.h" // this header is for viewing the data on the computer 
    #include "flashmemlib.h" // this header contains the function to read n 
     //write on the memory 

    #define MISO  PB3 
    #define MOSI  PB2 
    #define SCK  PB1 
    #define CS  PB0 
    #define HOLD  PB6 
    #define WP  PB7 
    #define sigA  PD0  //INT0 
    #define sigB  PD2  //INT2 
    #define LED  PD3 


     uint8_t HADD,MADD,LADD, HDATA, LDATA,i; //HADD=high address, MADD-medium address, LADD-low address 
     volatile int buffer[8]; //this buffer will store the encoder pulse 
     uint32_t address = 0; 
     uint16_t DATA16B = 0; 

     int main(void) 
     { 
     INITIALIZE(); //initialize the IO pin, timer CTC mode, SPI and USART protocol 
      for(i=0;i<8;i++) 
       buffer[i]=0; 

     sei(); 

     //AAI process- AAI is just one writing mode of the memory 
     AAIInit(address,0); 
     while (address < 50)  //just a dummy loop which lasts for 5 secs (appox) 
     { 
     _delay_ms(100); 
     address++; 
     } 
     AAIDI();//disable AAI process 
     cli(); //disable global interrupt 
     EIMSK &= ~(1<<INT0); 
     TIMSK1 &= ~(1<<OCIE1A); 

    //code for reading procedure. i thought this part is unnecessary because i am quite //confident that it works correcly 
    return (0); 
    } 


    ISR(INT0_vect) // this interrupt is mainly for counting the number of encoder's pulses 
    { // When an interrupt occurs, we only have to check the level of 
     // of pB to determine the direction 
     PORTB &= ~(1<<HOLD); 
     for(i=0;i<8;i++) 
      buffer[i+1]=buffer[i]; 

     if (PIND & (1<<sigB)) 
      buffer[0]++; 
     else buffer[0]--; 
     PORTB |= (1<<HOLD); 
    } 

    ISR(TIMER0_COMPA_vect) //after around 1ms, this interrupt is triggered. it is for storing the data into the memory. 
    { 
     HDATA =(buffer[7]>>8)&0xFF; 
     LDATA = buffer[7]&0xFF; 
     PORTB &= ~(1<<CS); 
     SEND(AD); 
     SEND(HDATA); 
     SEND(LDATA); 
     PORTB |=(1<<CS); 
    } 

void SEND(volatile uint8_t data) 
{ 
    SPDR = data;     // Start the transmission 
    while (!(SPSR & (1<<SPIF))){} // Wait the end of the transmission 
} 
uint8_t SREAD(void) 
{ 
    uint8_t data; 
    SPDR = 0xff;     // Start the transmission 
    while (!(SPSR & (1<<SPIF))){} // Wait the end of the transmission 
    data=SPDR; 
    return data; 
} 

答えて

0

INT0の割り込みサービスルーチンでは、あなたが書いている:

for(i=0;i<8;i++) 
     buffer[i+1]=buffer[i]; 

i=7あなたは、配列の所定の領域の外に書いている、そしておそらく別の変数を上書きするときことを意味します。だから、あなたはする必要があります:

for(i=0;i<7;i++) 
     buffer[i+1]=buffer[i]; 

AVRは、ATmega1280データシートに基づいて説明したように割り込みを管理します。また、別の割り込みによってISRベクタの割り込みを許可する場合は、次のようにする必要があります(例)。

ISR(INT0_vect, ISR_NOBLOCK) 
{... 
...} 
関連する問題