首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用单片机ATMega 1280实现实时数据记录的多中断

用单片机ATMega 1280实现实时数据记录的多中断
EN

Stack Overflow用户
提问于 2012-04-02 16:16:12
回答 1查看 230关注 0票数 0

我的问题是关于实时数据记录和多中断。我正在尝试通过winAVR对单片机ATMega1280进行编程,使其读取来自正交编码器的脉冲(20微米/音调),并将数据存储到闪存(微芯片SST25VF080B,串行接口协议)中。在编码器完成其操作后(大约2分钟),MCU将数据从存储器输出到屏幕。我的代码如下。

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

我认为问题可能只存在于数据存储中,因为除了跳跃之外,趋势的发生与我预期的一样。我只想问一下,我是否像在程序中那样运行两个ISR。是否存在ISR在运行时被另一ISR干预的情况?根据atmega 1280数据手册,似乎当一个ISR正在发生时,在前一个中断完成其例程后,不允许发生其他中断。

代码语言:javascript
运行
复制
    #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;
}
EN

回答 1

Stack Overflow用户

发布于 2012-12-25 00:20:52

在INT0的中断服务例程中,您正在编写:

代码语言:javascript
运行
复制
    for(i=0;i<8;i++)
        buffer[i+1]=buffer[i];

这意味着当使用i=7时,您将在数组的预定空间之外进行写入,并且可能会覆盖另一个变量。所以你必须这样做:

代码语言:javascript
运行
复制
    for(i=0;i<7;i++)
        buffer[i+1]=buffer[i];

AVR将根据ATmega1280数据表来管理您所描述的中断。或者,如果您想要允许另一个中断中断ISR向量,则需要执行以下操作(示例):

代码语言:javascript
运行
复制
ISR(INT0_vect, ISR_NOBLOCK)
{...
...}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9972950

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档