2012-04-02 3 views
0

Мой вопрос касается регистрации данных в реальном времени и многократного прерывания. Я пытаюсь запрограммировать MCU-ATMega 1280 на winAVR, чтобы он считывал импульсы от квадратурного кодировщика (20um/pitch) и сохранял данные во флэш-памяти (Microchip SST25VF080B, последовательный протокол SPI). После завершения работы энкодера (около 2 минут) MCU экспортирует данные из памяти на экран. Мой код ниже.Multi-прерывание для регистрации данных в реальном времени с MCU-ATMega 1280

Но я не знаю, почему он работает неправильно. Есть 2 типа ошибок: одна ошибка - это некоторые моменты, внезапно выходящие из тренда, другая ошибка - это внезапное прыгающее значение, хотя кодер работает медленно. Кажется, что прыжок появляется только при повороте.

Я думаю, проблема может заключаться только в хранении данных, потому что тенденция происходит так, как я ожидал, кроме прыжков. Я просто хочу спросить, запускаю ли я оба ISR, как то, что я сделал в программе. есть ли случай, когда ISR будет вмешаться другим ISR при его запуске? В соответствии с аттестатом atmega 1280, кажется, что при возникновении одного 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) 
{... 
...}