2012-04-02 12 views
0

Meine Frage ist über Echtzeit-Datenprotokollierung und Multi-Interrupt. Ich versuche ein MCU-ATMega 1280 von winAVR zu programmieren, damit es die Impulse vom Quadratur-Encoder (20um/Pitch) liest und die Daten in den Flash-Speicher (Microchip SST25VF080B, serielles SPI-Protokoll) speichert. Nachdem der Encoder seinen Betrieb beendet hat (etwa 2 Minuten), exportiert die MCU die Daten aus dem Speicher auf den Bildschirm. Mein Code ist unten.Multi-Interrupt für die Echtzeit-Datenerfassung mit MCU-ATMega 1280

Aber ich weiß nicht, warum es nicht richtig ausgeführt wird. Es gibt 2 Arten von Bugs: Ein Bug ist einige Punkte plötzlich aus dem Trend, ein anderer Bug ist ein plötzlicher Sprungwert, obwohl der Encoder langsam läuft. Das Springen scheint nur zu erscheinen, wenn es eine Kurve gibt.

Ich denke, das Problem kann nur in der Datenspeicherung liegen, weil der Trend passiert, was ich erwartet habe, außer für die Sprünge. Ich möchte nur fragen, ob ich beide ISR wie das, was ich in dem Programm gemacht habe, laufen lasse. Gibt es einen Fall, in dem eine ISR von einer anderen ISR interveniert wird, wenn sie läuft? Laut atmega 1280 Datenblatt scheint es, dass wenn ein ISR auftritt, kein anderer Interrupt passieren kann, nachdem der vorherige Interrupt seine Routine beendet hat.

#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; 
} 

Antwort

0

Im Interrupt Service Routine von INT0 Sie schreiben:

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

bedeutet, dass, wenn i=7 Sie außerhalb der vorgegebenen Raum des Arrays, schreiben und wahrscheinlich eine andere Variable zu überschreiben. So müssen Sie tun:

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

AVR verwaltet die Interrupts wie Sie beschrieben, basierend auf dem ATmega1280 Datenblatt. Alternativ können Sie, wenn Sie die Unterbrechung eines ISR-Vektors durch einen anderen Interrupt zulassen möchten, wie folgt vorgehen (Beispiel):

ISR(INT0_vect, ISR_NOBLOCK) 
{... 
...} 
Verwandte Themen