0

我的问题是关于实时数据记录和多中断。我正在尝试通过 winAVR 对 MCU-ATMega 1280 进行编程,使其从正交编码器(20um/pitch)读取脉冲并将数据存储到闪存中(Microchip SST25VF080B,串行 SPI 协议)。编码器完成操作后(大约 2 分钟),MCU 将数据从内存中导出到屏幕。我的代码如下。

但我不知道为什么它不能正确运行。有两种错误:一种错误是某些点突然脱离趋势,另一种错误是编码器运行缓慢但突然跳值。跳跃似乎只有在转弯时才会出现。

我认为问题可能只存在于数据存储中,因为除了跳跃之外,趋势就像我预期的那样发生。我只想问我是否像在程序中那样运行两个 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;
}
4

1 回答 1

0

In the Interrupt Service Routine of INT0 you are writing:

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

Means that when i=7 you are writing outside of the array's predetermined space, and probably overwriting another variable. So you have to do:

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

AVR will manage the interrupts as you described, based on the ATmega1280 datasheet. Alternatively, if you want to allow the interruption of an ISR vector by another interrupt you need to do as follows (example):

ISR(INT0_vect, ISR_NOBLOCK)
{...
...}
于 2012-12-24T16:20:52.137 回答