首页 > 解决方案 > Arduino Mega 到 ADC SPI 通信不工作

问题描述

我正在使用 SPI 通信尝试在外部时钟模式下将我的Arduino Mega 2560作为主机连接到 ADC 芯片作为从机(还连接了一个触摸屏(可以工作)。除了与 Arduino的ADC 芯片通信外,一切正常。Max 1247(RB1 = 255, RB2 = 255, RB3 = 255)

我试过删除定义标题,并改变时钟。都不会改变任何东西(这可能是因为其他错误)。

//Portion of Header

//Defining SPI connections

#define SELPIN 53 //Selection Pin

#define DATAOUT 50 //MIS0

#define DATAIN  51 //MOSI

#define SPICLOCK  52//Clock

#define SSTRB 43 //SSTRB


#include <Adafruit_GFX.h> 

#include "MCUFRIEND_kbv.h"


MCUFRIEND_kbv tft(A3, A2, A1, A0, A4);

int sstrb = 0;  

byte TB1 = B11101111;  

byte RB1;  

byte RB2;  

byte RB3;  

byte RB4;

//SETUP

void setup(){  

  pinMode(SELPIN, OUTPUT);  

  pinMode(sstrb, INPUT);  

  pinMode(DATAOUT, INPUT); 

  pinMode(DATAIN, OUTPUT);

  pinMode(SPICLOCK, OUTPUT);

  //disable device to start.

  digitalWrite(SELPIN, HIGH);

  digitalWrite(SPICLOCK, LOW);

  digitalWrite(DATAIN, LOW);

}

void loop(){

//Some other touch screen stuff prefaces this..

else if (currentPage == '3') {
    if (tp.z > myTouch.pressureThreshhold) {
      x = tp.x;
      y = tp.y;
      //Back button command

      if ((x >= 20) && (x <= 900) && (y >= 0) && (y <= 320)) {
        homescreen();
        currentPage = '0';
      }

      else if ((x >= 700) && (x <= 800) && (y >= 350) && (y <= 875)) {
        //loop

        SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));

        digitalWrite(SELPIN, LOW);

        //The line beneath might take care of transmitting dataout, and receiving datain (vs currently doing seperately)?.

        RB1 = SPI.transfer(TB1);

        Serial.print("\r\nRB1="); Serial.print(RB1);

        digitalRead(sstrb);

        if (sstrb == 0){

          RB2 = SPI.transfer(0x0);

          Serial.print("\r\nRB2="); Serial.print(RB2);

          RB3 = SPI.transfer(0x0);

          Serial.print("\r\nRB3="); Serial.print(RB3);

          digitalWrite(SELPIN, HIGH);

          digitalWrite(SELPIN, LOW);

          SPI.endTransaction();

          tft.fillRoundRect(40, 20, 300, 70, 15, RED);

          tft.setCursor(150, 45);

          tft.setTextColor(WHITE);

          tft.setTextSize(3);

          tft.print("3A");

          tp = myTouch.getPoint();

          pinMode(YP, OUTPUT);

          pinMode(XM, OUTPUT);

          digitalWrite(YP, HIGH);

          digitalWrite(XM, HIGH);

        }

        else{

          Serial.print("SSTRB is high");

        }

      }

    }

  }

}

错误包括 RB1 = 255;RB2 = 255;RB3 = 255 或全零。

标签: arduinospiadc

解决方案


我不能肯定地说这是否是您问题的根源,但我发现了以下内容:

您将 SSTRB 定义为引脚 43

#define SSTRB 43 //SSTRB

但你实际上从未使用过这个值。相反,您还定义了

int sstrb = 0;

下面几行,然后您将其用于将引脚 0 定义为输入

pinMode(sstrb, INPUT);

我认为这应该是

pinMode(SSTRB, INPUT);

然后,你的循环中有这些行

digitalRead(sstrb);
if (sstrb == 0){

其中 digitalRead 实际上什么都不做(从引脚 0 读取并丢弃该值),我假设您想写

sstrb = digitalRead(SSTRB);

否则,sstrb永远不会真正改变并且始终为 0。

此外,由于数据表(https://datasheets.maximintegrated.com/en/ds/MAX1246-MAX1247.pdf#page=13)指出

在外部时钟模式下,[...]。在控制字节的最后一位之后,SSTRB 脉冲高一个时钟周期。

并且您正在使用外部时钟模式,我假设您宁愿等待该脉冲完成后再继续。你可以像这样忙着等待:

bool wasHigh = false;
do {
    sstrb = digitalRead(SSTRB);
    if( sstrb == 1 ){ 
        wasHigh = true; 
    }
}while( !(wasHigh && sstrb == 0) );

请注意,如果脉冲在此等待之前发生或从未发生,您将无休止地停留在此循环中。您可能不想在此处添加中断条件或超时。你当然也可以使用中断来解决这个问题。

附加说明:您在检查是否仅为 0endTransaction的分支中调用。sstrb我不知道 SPI 库如何处理重新开始事务而不先结束旧事务,它可能工作正常,我只是想让你知道这可能是一个潜在的陷阱。


推荐阅读