Arduino 由于最大中断频率

问题描述 投票:0回答:1

我正在尝试实现我自己的从FPGA到Arduino的SPI通信,其中我的FPGA作为MASTER并生成用于通信的芯片使能和时钟。 FPGA 在上升沿发送数据,在下降沿接收数据,我的 FPGA 代码工作正常。

在 Arduino 端,我在中断时捕获该主时钟,并在其上升沿接收数据并在其下降沿发送数据,但如果我从 10 KHz 增加时钟速度,通信将无法正常工作。

根据我的理解,Arduino Due 工作在 84 MHz,处理 1 MHz 中断不是一个大问题。您能告诉我如何使用 Arduino Due 处理这个高速时钟吗?

Arduino 代码如下:

void ISR1();
// this constant won't change
const int  S_CLK = 19; //  slow clock in this case FPGA is master
const int  MOSI_C =  51; //   Master out slave in in this case arduino
//receive data from FPGA
const int  MISO_C = 50; //  Master in slave out in this case arduino
//transmit data from FPGA
const int  SS_C = 53; // the pin that the pushbutton is attached to
const int TRANS_INDEX = 32; //index that is used to transmit data in this
cas 32 bits are transmitted
const int REC_INDEX = 48;

#define CLK_MAIN    84000000UL

//Variables will change

int ss_check = 0; //used for reading of slave select
int mosi_data[REC_INDEX + 2]; //delcare receiving data array length
int count = 0; //used for convertion of bits to bytes
int index_r_stat = 0; //give us a value of status that
how much bits are received
int flag = 0; //used for stop reading s
int miso_out[TRANS_INDEX] = {
  1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0
};
int miso_index = 0; //used for above array
int last_clk_state = 1; //used for the detection of rising and
falling edge

int check_clk;
void setup() {
  //   initialize the button pin as a input
  pinMode(S_CLK , INPUT);
  pinMode(MOSI_C , INPUT);
  pinMode(MISO_C , OUTPUT);
  pinMode(SS_C , INPUT);
  //   initialize serial communication
  Serial.begin(9600);
}

void loop() {
  //   read the pushbutton input pin
  ss_check = digitalRead(SS_C);
  //Serial.println(ss_check);
  //WAIT until slave select is not read
  if (ss_check == 0) {
    //attach interrupt so that data is
    attachInterrupt(digitalPinToInterrupt(S_CLK), ISR1, CHANGE);
  }
  if ((index_r_stat == (REC_INDEX + 1)) && (flag == 0)) {
    for (int i = 1; i < (REC_INDEX + 1); i = i + 1) {
      Serial.print(mosi_data[i]);
      flag = 1;
      if (count < 7) {
        count = count + 1;
      } else {
        count = 0;
        Serial.println();
      }
    }
  }
}

void ISR1() {
  if ((last_clk_state == 1) && (digitalRead(S_CLK) == 0)) {
    check_clk = 0;
    //this code is used to transmit data to FPGA
    if (miso_index < TRANS_INDEX - 1) {
      digitalWrite(MISO_C, miso_out[miso_index]);
      miso_index = miso_index + 1;
    } else {
      miso_index = miso_index;
    }
  } else {
    check_clk = 1;
    //this code is used for reading data from FPGA
    if (index_r_stat < (REC_INDEX + 1)) {
      mosi_data[index_r_stat] = digitalRead( MOSI_C);
      index_r_stat = index_r_stat + 1;
    } else {
      detachInterrupt(S_CLK);
      index_r_stat = index_r_stat;
    }
  }
  last_clk_state = digitalRead(S_CLK);
}
c++ arduino microcontroller gnu processor
1个回答
0
投票

您的 ISR 子例程可能是实现更高 SPI 速度的限制因素,特别是如果它没有针对快速执行进行优化。是的,Arduino Due 的 CPU 运行频率为 84 MHZ,但是您的 ISR 例程是否只需 84 cc 即可执行以达到 1MHZ?我认为你上面列出的代码需要 100-1000CC 的量级。所以时钟周期的上限为 84KHZ。还有上升沿和下降沿的 ISR。所以将其除以 2。

以下是优化 ISR 以实现更快 SPI 通信的一些注意事项:

直接寄存器访问 考虑直接访问 GPIO 寄存器以实现更快的读写操作,而不是使用 Arduino 库函数(例如 digitalRead() 和 digitalWrite())。这可以显着减少开销并提高 ISR 性能。

通过简化 ISR 内的数据处理来优化数据处理,以最大程度地减少延迟。如果可能的话,也许只分配时间用于写作,其他时间用于阅读。您可以读取一个字节,然后写入一个字节。另外,看看是否可以使用使用 SPI 硬件的 SPI 库缓冲区。所以你可以以字节而不是位来读取。

© www.soinside.com 2019 - 2024. All rights reserved.