Arduino中断行为不端

时间:2016-05-18 16:32:05

标签: arduino interrupt

我在使用一些C代码时遇到了一些问题我正在为一个arduino项目写作。目标是使用外部多路复用ADC将大量模拟信号数字化,然后将这些数字值加载到外部移位寄存器中,并使用SPI将它们移入Arduino。为了测试我的代码,我只有一个ADC复用4个信号。

中断引脚(20)连接到比较器电路,该电路查看原始模拟信号,并在电压为1V或更高时将引脚拉高。当调用ISR时,它将禁用全局中断" noInterrupts()"设置事件标志,从中断处理程序中分离引脚20,启用全局中断"中断()"最后回到它停止的地方。

我面临一些问题,首先ISR被调用一次,第二次罚款但是在第二次ISR调用之后它再也没有被调用,这是我的秒数问题,中断引脚变低。根据AttachInterupt()函数,只有在引脚20为高电平时才应调用ISR。这可以在我附上的第一张和第二张图片中看到。我注意到的另一件事是中断引脚为高电平的持续时间对第3个ISR是否被调用没有影响。

我不确定这是否是我对Arduino的中断处理的理解问题,或是代码搞砸导致堆栈溢出或类似的问题。

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

//Constants
#define RD 41               //pin 41 conneced to read pin
#define INT1 37             //pin 37 connecte to interrupt 1
#define CLK_INH  53         //pin 53 connected to clk inhibit
#define LD  40              //pin 40 connected to load pin
#define INPUT_MAX 3         //input selector limit (Zero Indexed)
#define SENSORS 3           //how many sensors are used (Zero Indexed)
#define DATA_DUMP 38        //pin 29 controlls the data dump deature
#define BYTE_LEN  1         //number of ADC used
#define DEBUG1 17
#define DEBUG2 16

//Controls
unsigned char selector = 0;     //ACD input selector
volatile byte eventFlag = LOW;         //Control Flag, set to True when event occurs
bool lastButtonState = true;

//Counters
unsigned int i = 0;             //eventLog[i]: event counter
unsigned int j = 0;             //eventLog[i].data[j]: data counter

//Function Delcarations
unsigned char inputSelector (unsigned char my_selector);
void lockAndPop ();
void dataDump ();
void debug (int pin);
bool fallingEdge (bool);          //check for a falling edge of a digital read

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  // put your setup code here, to run once:
  pinMode(RD, OUTPUT);          //Read pin, 0 = begin analog conversion     (ADC)
  pinMode(INT1, INPUT);         //Interrupt pin, 0 = conversion complete    (ADC)
  pinMode(CLK_INH, OUTPUT);      //Clock inhibit pin, 1= no change on output (ShiftRegister)
  pinMode(LD, OUTPUT);          //Shift/Load pin, 1 = data is shifted       (ShiftRegister)
  pinMode(DATA_DUMP, INPUT);
  pinMode(DEBUG1, OUTPUT);
  pinMode(DEBUG2, OUTPUT);

  DDRA = 0xFF;        //Set port A to ouput

  SPI.begin();
  //SPI.mode1 Clock idel low CLOP = 0, Data sampled on falling edge CPHA = 1
  SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE1));  

  digitalWrite(RD, HIGH);       //Stop conversion
  digitalWrite(CLK_INH, HIGH);   //No change on the output
  digitalWrite(LD, LOW);        //Load the shift register
  digitalWrite(DEBUG1, LOW);
  digitalWrite(DEBUG2, LOW);  

  attachInterrupt(digitalPinToInterrupt(20), pin_ISR, HIGH);    //Call pin_ISR when pin20 goes high

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef struct                //event structure, containts a timestamp element and an array of 18 data points
{
  unsigned long int timeStamp;
  unsigned char data[SENSORS];
} Event;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Event eventLog[200];        //an array of structures representing 200 events, once the 200 events have been filled the data will be printed

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  if(fallingEdge(digitalRead(DATA_DUMP))){      //If there is falling edge on the data dump button, call the dataDump function
    dataDump();
  }
  debug(DEBUG2);
  if(eventFlag)                                 //if the Event flag is set to true by ISR begin the conversion steps
  {
    debug(DEBUG1);
    digitalWrite(RD,LOW);         //Start conversion
    while(digitalRead(INT1)){}    //Wait for conversion to complete

    eventLog[i].timeStamp = micros();

    for (j=0; j<=SENSORS; j++) {
      lockAndPop();                         //lock digital value and reset conversion
      PORTA = inputSelector(selector);      //increment the selector pin
      digitalWrite(RD, LOW);                //Start new conversion

      digitalWrite(CLK_INH, LOW);                //Start the data transfer
      eventLog[i].data[j] = SPI.transfer(0);     //read a single byte from the SPI line
      digitalWrite(CLK_INH, HIGH);              //Inhibit clock
      digitalWrite(LD, LOW);
      while(digitalRead(INT1)){}                //wait for previous conversion to end            
      } 
    i++;
    digitalWrite(RD, HIGH);
    selector = 0;  
    if(i>=200){
      dataDump();                           //if the event log hits 200 before a data dump is request, dump the data
    }
    eventFlag = LOW;
    attachInterrupt(digitalPinToInterrupt(20), pin_ISR, HIGH);

  }

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void pin_ISR() {
  noInterrupts();
  detachInterrupt(digitalPinToInterrupt(20));
  eventFlag = HIGH;
  interrupts();
  return;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

unsigned char inputSelector (unsigned char my_selector){
  if(my_selector==INPUT_MAX){           //if the current selector is at the highest value reset to 0
    return 0;
  }
  return my_selector++;                  //increment the input selector by 1
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void lockAndPop (){
   digitalWrite(LD, HIGH);        //Lock in digital value
   digitalWrite(RD, HIGH);        //Reset conversion
   return;
}

void dataDump (){
  detachInterrupt(digitalPinToInterrupt(20));
  char buf[100], *pos = buf;    //create a buffer of 100 charaters, anda pointer to the begining of that buffer
  char *base = buf;             //create a base address to reset the buffer
  unsigned int eventCount = i;               //how many events occured before dump command was called
  unsigned int localCount;      
  unsigned int localData;
  Serial.begin(115200);
  Serial.println(i);
  for (localCount = 0; localCount<=eventCount; localCount++){
    pos += sprintf(pos, "%lu", eventLog[localCount].timeStamp);          //sprintf will append the data to the pointer "pos", and return the number of byte append.
    for (localData = 0; localData<=SENSORS; localData++){
       pos += sprintf(pos, " %d", (unsigned int)(eventLog[localCount].data[localData]));   
    }
    Serial.println(buf);
    pos = base;
  }
  i=0;
  j=0;
  Serial.end();
  attachInterrupt(digitalPinToInterrupt(20), pin_ISR, HIGH);
  return;
}

void debug(int pin){
  digitalWrite(pin, HIGH);
  digitalWrite(pin, LOW);
  return;
}

bool fallingEdge (bool currentButtonState){
  if(!currentButtonState&&lastButtonState){
    lastButtonState = currentButtonState;
    return 1;
  }
  lastButtonState = currentButtonState;
  return 0;
}

High to Low Two events

ISR引脚上发生了一些噪音,但这并不重要,因为我在服务程序中禁用了该特定引脚,因此我不认为这是一个问题< / p>

Noisy ISR pin

0 个答案:

没有答案