可以测试 SPI 通信 winhout 外部模块

Is possible to test SPI communication winhout external module

我有一个非常简单的问题,我想...我正在使用两个 SPI 通信(一个 classis SPI 和第二个 int SPI)在 SAMD21 板上编程,我认为 int SPI 无法正常工作。如果我连接一些传感器,它不会向串行监视器打印任何内容。我很确定,我的代码没问题,但可能会有一些错误...

所以我需要知道,是否有某种方法可以测试 SPI winhout 将外部设备连接到电路板。请不要讨厌代码太长,我使用的 SPI 传感器代码标有“//SPI”。

PS: 抱歉删除了SMUART和MICS6814的测量校准功能,只用了30000字。完整代码在这里:https://mega.nz/file/2QxG0ayZ#4UpEU17ogXnm2NK22zAowlDDRrXzksPzzs05zbuq23o

   #include <Adafruit_BME280.h>  // include Adafruit BME280 library
      #include <Adafruit_INA219.h>  // include INA219
      #include <SD.h>          // include Arduino SD library
      #include "Open_Cansat_GPS.h"
      #include <RTCZero.h>

      //include our new sensors
      #include <MICS6814.h>
      #include <MICS-VZ-89TE.h>
      #include "MQ131.h"

      #include <Wire.h>
      #include <SPI.h>

      #include "RFM69.h"       // include RFM69 library

      // Local
      #define PC_BAUDRATE       115200
      #define MS_DELAY    0  // Number of milliseconds between data sending and LED signalization
      #define LED_DELAY     100
      #define Serial SerialUSB
      RTCZero rtc;

      // RFM69
      #define NETWORKID       0        // Must be the same for all nodes (0 to 255)
      #define MYNODEID        1          // My node ID (0 to 255)
      #define TONODEID        2          // Destination node ID (0 to 254, 255 = broadcast)
      #define FREQUENCY       RF69_433MHZ   // Frequency set up
      #define FREQUENCYSPECIFIC 433000000  // Should be value in Hz, now 433 Mhz will be set
      #define CHIP_SELECT_PIN   43 //radio chip select
      #define INTERUP_PIN       9 //radio interrupt

      // BME280 SETTING
      #define BME280_ADDRESS_OPEN_CANSAT 0x77
      #define SEALEVELPRESSURE_HPA    1013.25

      //define our sensor pins
      //MICS6814
      #define PIN_CO  0
      #define PIN_NO2 0
      #define PIN_NH3 0
      #define MICS6814Pin 6
      //OZONE2CLICK
      const byte pinSS = 2; 
      const byte pinRDY = 12;
      const byte pinSCK = 13;
      const byte O2Pin = 10;
      //SMUART
      bool flag1 = false;
      bool flag2 = false;
      byte rxData[30];
      byte one, two;
      #define DcPin 8
      //MICSVZ89TE
      #define MICSVZ89TEPin 7
      int datas [7];
      bool MICS_status;
      int MICS_voc;
      int MICS_eqco2;
      //PHASES
      float CurrentTime;
      const byte day = 17;
      const byte month = 11;
      const byte year = 15;

      MICS6814 gas(PIN_CO, PIN_NO2, PIN_NH3);

      long accelX, accelY, accelZ;
      float gForceX, gForceY, gForceZ;

      long gyroX, gyroY, gyroZ;
      float rotX, rotY, rotZ;

      #define sd_cs_pin 35 // set SD's chip select pin (according to the circuit)

      RFM69 radio(CHIP_SELECT_PIN, INTERUP_PIN, true);


      typedef struct
      {
        int16_t messageId;
        uint16_t year;
        uint8_t month;
        uint8_t day;
        uint8_t hour;
        uint8_t minute;
        uint8_t sec;
        float longitude;
        float latitude;
        uint8_t num_of_satelites;
        float temperature;
        float pressure;
        float altitude;
        float humidity_bme280;
        float voltage_shunt;
        float voltage_bus;
        float current_mA;
        float voltage_load;
        int16_t rssi;
      } messageOut;

      messageOut cansatdata; //create the struct variable

      Adafruit_BME280 bme;


      Adafruit_INA219 ina219(0x40);


      OpenCansatGPS gps;


      File file; // SD library variable

      // LEDS
      #define D13_led_pin 42  // D13 LED
      #define M_led_pin 36  // MLED

      // Local variables
      int idCounter = 1;
      bool isBmeOk = true;
      bool isSdOk = true;
      bool isRadioOk = true;
      bool isGpsConnected = true;

      // My variables
      float NH3Data;
      float COData;
      float NO2Data;
      float PPMO2;
      float PPBO2;
      float MGM3O2;
      float UGM3O2;
      float SSmoke1;
      float SSmoke2;
      float SSmoke3; 
      float ESmoke1;
      float ESmoke2;
      float ESmoke3;
      int DataCounter = 0;

        void RTCBegin ()
      {
        rtc.begin();
      }

      void RTCSleep ()
    {

      digitalWrite(O2Pin, LOW);
      digitalWrite(MICS6814Pin, LOW);
      digitalWrite(MICSVZ89TEPin, LOW);
      digitalWrite(DcPin, LOW);
      digitalWrite(D13_led_pin, LOW);
      digitalWrite(M_led_pin, LOW);
      GyroscopeSleep();

      byte seconds = 0;
      byte minutes = 00;
      byte hours = 00;

      rtc.setTime(hours, minutes, seconds);
      rtc.setDate(day, month, year);

      rtc.setAlarmTime(00, 00, 10);
      rtc.enableAlarm(rtc.MATCH_HHMMSS);

      rtc.standbyMode();
      TerrestrialPhase();
       // Sleep until next alarm match
    }


//SPI


      void OZONE2CLICKCalibrate ()
      {
      Serial.println("2");
        //MQ131.begin(pinSS, pinRDY, O2Pin, LOW_CONCENTRATION, 10000);  //(int _pinCS, int _pinRDY, int _pinPower, MQ131Model _model, int _RL)
        Serial.println("99");
        Serial.println("Calibration in progress...");

        MQ131.calibrate();

        Serial.println("Calibration done!");
        Serial.print("R0 = ");
        Serial.print(MQ131.getR0());
        Serial.println(" Ohms");
        Serial.print("Time to heat = ");
        Serial.print(MQ131.getTimeToRead());
        Serial.println(" s");
        }

      void OZONE2CLICKMeasure ()
      {
        Serial.println("Sampling...");
        MQ131.sample();
        Serial.print("Concentration O3 : ");
        PPMO2 = MQ131.getO3(PPM);
        Serial.print(PPMO2);
        Serial.println(" ppm");
        Serial.print("Concentration O3 : ");
        PPBO2 = MQ131.getO3(PPB);
        Serial.print(PPBO2);
        Serial.println(" ppb");
        Serial.print("Concentration O3 : ");
        MGM3O2 = MQ131.getO3(MG_M3);
        Serial.print(MGM3O2);
        Serial.println(" mg/m3");
        Serial.print("Concentration O3 : ");
        UGM3O2 = MQ131.getO3(UG_M3);
        Serial.print(UGM3O2);
        Serial.println(" ug/m3");
      }

//SPI

      void MICSVZ89TEMeasure()
      {
        delay(5000);
          MICS_VZ_89TE myMICS;
          MICS_status = myMICS.begin();
          myMICS.readSensor();
          MICS_eqco2 = myMICS.getCO2();
          MICS_voc = myMICS.getVOC();
          Serial.print("MICS VOC PPB: ");
          Serial.println(MICS_voc);
          Serial.print("MICS CO2 PPM: ");
          Serial.println(MICS_eqco2);
          delay(1000);
      }

      void GyroscopeTurnOn() 
    {
      Wire.begin();
      setupMPU();
      }

    void GyroscopeMeasure() {
      recordAccelRegisters();
      recordGyroRegisters();
      printData();
    }

    void setupMPU(){
      Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
      Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
      Wire.write(0b00000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
      Wire.endTransmission();  
      Wire.beginTransmission(0b1101000); //I2C address of the MPU
      Wire.write(0x1B); //Accessing the register 1B - Gyroscope Configuration (Sec. 4.4) 
      Wire.write(0x00000000); //Setting the gyro to full scale +/- 250deg./s 
      Wire.endTransmission(); 
      Wire.beginTransmission(0b1101000); //I2C address of the MPU
      Wire.write(0x1C); //Accessing the register 1C - Acccelerometer Configuration (Sec. 4.5) 
      Wire.write(0b00000000); //Setting the accel to +/- 2g
      Wire.endTransmission(); 
    }

    void GyroscopeSleep(){
      Wire.beginTransmission(0b1101000); //This is the I2C address of the MPU (b1101000/b1101001 for AC0 low/high datasheet sec. 9.2)
      Wire.write(0x6B); //Accessing the register 6B - Power Management (Sec. 4.28)
      Wire.write(0b01000000); //Setting SLEEP register to 0. (Required; see Note on p. 9)
      Wire.endTransmission();
    }

    void recordAccelRegisters() {
      Wire.beginTransmission(0b1101000); //I2C address of the MPU
      Wire.write(0x3B); //Starting register for Accel Readings
      Wire.endTransmission();
      Wire.requestFrom(0b1101000,6); //Request Accel Registers (3B - 40)
      while(Wire.available() < 6);
      accelX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
      accelY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
      accelZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
      processAccelData();
    }

    void processAccelData(){
      gForceX = accelX / 16384.0;
      gForceY = accelY / 16384.0; 
      gForceZ = accelZ / 16384.0;
    }

    void recordGyroRegisters() {
      Wire.beginTransmission(0b1101000); //I2C address of the MPU
      Wire.write(0x43); //Starting register for Gyro Readings
      Wire.endTransmission();
      Wire.requestFrom(0b1101000,6); //Request Gyro Registers (43 - 48)
      while(Wire.available() < 6);
      gyroX = Wire.read()<<8|Wire.read(); //Store first two bytes into accelX
      gyroY = Wire.read()<<8|Wire.read(); //Store middle two bytes into accelY
      gyroZ = Wire.read()<<8|Wire.read(); //Store last two bytes into accelZ
      processGyroData();
    }

    void processGyroData() {
      rotX = gyroX / 131.0;
      rotY = gyroY / 131.0; 
      rotZ = gyroZ / 131.0;
    }

    void printData() {
      Serial.print("Gyro (deg)");
      Serial.print(" X=");
      Serial.print(rotX);
      Serial.print(" Y=");
      Serial.print(rotY);
      Serial.print(" Z=");
      Serial.print(rotZ);
      Serial.print(" Accel (g)");
      Serial.print(" X=");
      Serial.print(gForceX);
      Serial.print(" Y=");
      Serial.print(gForceY);
      Serial.print(" Z=");
      Serial.println(gForceZ);
    }

    void TerrestrialPhase()
      {    
        Serial.println("------------------------------");
        Serial.println("TERRESTRIAL PHASE IN PROGRESS");
        Serial.println("------------------------------");
        Serial.println(" ");    
        digitalWrite(DcPin, HIGH);
        digitalWrite(MICS6814Pin, HIGH);
        digitalWrite(MICSVZ89TEPin, HIGH);
        digitalWrite(O2Pin, HIGH);
        delay(2000);
        MICSVZ89TEMeasure();
        MICSVZ89TEMeasure();
        MICSVZ89TEMeasure();
        MICSVZ89TEMeasure();
        MICS6814Calibrate();
        MICS6814Measure();
        SMUARTTurnOn();
        delay(10000);
        SMUARTMeasure();
        delay(10000);
        SMUARTMeasure();
        delay(1000);
        SMUARTMeasure();
        delay(1000);
        SMUARTMeasure();
        delay(1000);
        OZONE2CLICKCalibrate();
        OZONE2CLICKMeasure();
        SDSave();
        delay(10000);
        RTCBegin();
        RTCSleep();
      }

      void LandingChecker()
      {
        CurrentTime = millis();
        Serial.println(CurrentTime);
        if (CurrentTime >= 30000)
        {
          Serial.println("------------------------------");
          Serial.println("AIR PHASE DONE");
          Serial.println("------------------------------");
          Serial.println(" ");
          Serial.println("------------------------------");
          Serial.println("STARTING TESTING PHASE");
          Serial.println("------------------------------");
          Serial.println(" ");
          TestingPhase1();
        }
            else 
        {
          Serial.println("------------------------------");
          Serial.println("AIR PHASE IN PROGRESS");
          Serial.println("------------------------------");
          Serial.println(" ");
        }
      }

      void WaitingPhase()
      {  
      digitalWrite(O2Pin, LOW);
      digitalWrite(MICS6814Pin, LOW);
      digitalWrite(MICSVZ89TEPin, LOW);
      digitalWrite(DcPin, LOW);
      digitalWrite(D13_led_pin, LOW);
      digitalWrite(M_led_pin, LOW);
      GyroscopeSleep();

      byte seconds = 0;
      byte minutes = 00;
      byte hours = 00;

      rtc.setTime(hours, minutes, seconds);
      rtc.setDate(day, month, year);

      rtc.setAlarmTime(00, 00, 10);
      rtc.enableAlarm(rtc.MATCH_HHMMSS);

      rtc.standbyMode();
      TerrestrialPhase();
      }

      void TestingPhase2()
      {    
          Serial.println("------------------------------");
          Serial.println("TESTING PHASE DONE");
          Serial.println("------------------------------");
          Serial.println(" ");
          Serial.println("------------------------------");
          Serial.println("STARTING TERRESTRIAL PHASE");
          Serial.println("------------------------------");
          Serial.println(" ");
          TerrestrialPhase();
      }

      void TestingPhase1()
      {

        if (((gForceX >= 3.60) || (gForceX <= 0.40)) && ((gForceY >= 2.9) && (gForceY <= 3.20)))
        {
          Serial.println("------------------------------");
          Serial.println("SATELITE POSITION: VERY GOOD");
          Serial.println("------------------------------");
          Serial.println(" ");
          TestingPhase2();
        }

        else if (((gForceX >= 3.30) || (gForceX <= 0.70)) && ((gForceY >= 2.9) && (gForceY <= 3.30)))
        {
          Serial.println("------------------------------");
          Serial.println("SATELITE POSITION: GOOD");
          Serial.println("------------------------------");
          Serial.println(" ");
          TestingPhase2();
        }

        else if (((gForceX >= 3) || (gForceX <= 1)) && ((gForceY >= 2.9) && (gForceY <= 4)))
        {
          Serial.println("------------------------------");
          Serial.println("SATELITE POSITION: OK");
          Serial.println("------------------------------");
          Serial.println(" ");
          TestingPhase2();
        }

        else
        {
          Serial.println("------------------------------");
          Serial.println("SATELITE POSITION: BAD");
          Serial.println("------------------------------");
          Serial.println(" ");
          Serial.println("------------------------------");
          Serial.println("TESTING PHASE FAILED");
          Serial.println("------------------------------");
          Serial.println(" ");
          WaitingPhase();
        }
        }

      void SDSave()
      {
        while(!Serial);

        if (!SD.begin(sd_cs_pin))
        {
          Serial.println("SD card initialization failed!");
          return;
        }

        Serial.println("SD card initialized");

        file = SD.open("data.txt", FILE_WRITE); // Open test.txt for write

        // Rrite to the file and print info to serial
        // print an error to the serial in case it does not succeed
        if (file) 
        {
          file.println("--------------------------");
          file.println("GyKoVySAT terrestrial data");
          file.println("--------------------------");
            file.println("OZONE");
          file.println(PPMO2);
            file.print(" ppm");
          file.println(PPBO2);
            file.print(" ppb");
          file.println(MGM3O2);
            file.print(" mg/m³");

            file.println("SMOKE PARTICLES STANDART");
          file.println(UGM3O2);
             file.print(" μg/m³");
          file.println(SSmoke1);
            file.print(" μg/m³");
          file.println(SSmoke2);
            file.print(" μg/m³");
          file.println(SSmoke3);

            file.println("SMOKE PARTICLES ENVIROMENTAL");
          file.println(ESmoke1);
            file.print(" μg/m³");
          file.println(ESmoke2);
            file.print(" μg/m³");
          file.println(ESmoke3);
            file.print(" μg/m³");

            file.println("VOC");
          file.println(MICS_voc);
            file.print(" ppm");

            file.println("CO2");
          file.println(MICS_eqco2);
            file.print(" ppm");

            file.println("CO");
          file.println(COData);
            file.print(" ppm");

            file.println("NO2");
          file.println(NO2Data);
            file.print(" ppm");

            file.println("NH3");
          file.println(NH3Data);
            file.print(" ppm");


            file.println("DATA FOR ANALYZATION");
          file.println(PPMO2);
            file.print(";");
          file.print(PPBO2);
            file.print(";");
          file.print(MGM3O2);
            file.print(";");
          file.print(UGM3O2);
            file.print(";");
          file.print(SSmoke1);
            file.print(";");
          file.print(SSmoke2);
            file.print(";");
          file.print(SSmoke3);
            file.print(";");
          file.print(ESmoke1);
            file.print(";");
          file.print(ESmoke2);
            file.print(";");
          file.print(ESmoke3);
            file.print(";");
          file.print(MICS_voc);
            file.print(";");
          file.print(MICS_eqco2);
            file.print(";");
          file.print(COData);
            file.print(";");
          file.print(NO2Data);
            file.print(";");
          file.print(NH3Data);
            file.print(";");
          file.print(DataCounter);
            file.print(";");
          file.close();

          DataCounter =  DataCounter + 1;
        } 
        else 
        {
          Serial.println("Error opening data.txt for writing");
        }
        TerrestrialPhase();
      }

      void setup()
      {


        // wait for the Arduino serial (on your PC) to connect
        // please, open the Arduino serial console (right top corner)
        // note that the port may change after uploading the sketch
        // COMMENT OUT FOR USAGE WITHOUT A PC!
        // while(!Serial);

        Serial.println("openCanSat PRO");

        Serial.print("Node ");
        Serial.print(MYNODEID,DEC);
        Serial.println(" ready");

        // begin communication with the BME280 on the previously specified address
        // print an error to the serial in case the sensor is not found
        if (!bme.begin(BME280_ADDRESS_OPEN_CANSAT))
        {
          isBmeOk = false;
          Serial.println("Could not find a valid BME280 sensor, check wiring!");
          return;
        }

        // begin communication with the INA219
        ina219.begin();

        // check of Gps is connected
        Wire.beginTransmission(0x42); // 42 is addres of GPS
        int error = Wire.endTransmission();

        if (error != 0)
        {
          isGpsConnected = false;
        }

        // begin communication with gps
        gps.begin();

        // Uncomment when you want to see debug prints from GPS library
        // gps.debugPrintOn(57600);

        if(!radio.initialize(FREQUENCY, MYNODEID, NETWORKID))
        {
          isRadioOk = false;
          Serial.println("RFM69HW initialization failed!");
        }
        else
        {
          radio.setFrequency(FREQUENCYSPECIFIC);
          radio.setHighPower(true); // Always use this for RFM69HW
        }

        pinMode(D13_led_pin, OUTPUT);
        pinMode(DcPin, OUTPUT);
        pinMode(MICS6814Pin, OUTPUT);
        pinMode(MICSVZ89TEPin, OUTPUT);
        pinMode(O2Pin, OUTPUT);
        GyroscopeTurnOn();
      }

      void loop()
      {
        cansatdata.messageId = idCounter;
        GyroscopeMeasure();
        LandingChecker();    

        Serial.println("MessageId = " + static_cast<String>(cansatdata.messageId));

        cansatdata.temperature = 0;
        cansatdata.pressure = 0;
        cansatdata.altitude = 0;

        if(isBmeOk)
        {
          cansatdata.temperature += bme.readTemperature();
          cansatdata.pressure += bme.readPressure() / 100.0F;
          cansatdata.altitude += bme.readAltitude(SEALEVELPRESSURE_HPA);
          cansatdata.humidity_bme280 = bme.readHumidity();
        }

        Serial.println("Temperature = " + static_cast<String>(cansatdata.temperature) + " *C");
        Serial.println("Pressure = " + static_cast<String>(cansatdata.pressure) + " Pa");
        Serial.println("Approx altitude = " + static_cast<String>(cansatdata.altitude) + " m");
        Serial.println("Humidity = " + static_cast<String>(cansatdata.humidity_bme280) + " %");

        // read values from INA219 into structure
        cansatdata.voltage_shunt = ina219.getShuntVoltage_mV();
        cansatdata.voltage_bus = ina219.getBusVoltage_V();
        cansatdata.current_mA = ina219.getCurrent_mA();
        cansatdata.voltage_load = cansatdata.voltage_bus + (cansatdata.voltage_shunt / 1000);

        Serial.println("Shunt Voltage: " + static_cast<String>(cansatdata.voltage_shunt) + " mV");
        Serial.println("Bus Voltage: " + static_cast<String>(cansatdata.voltage_bus) + " V");
        Serial.println("Current: " + static_cast<String>(cansatdata.current_mA) + " mA");
        Serial.println("Load Voltage: " + static_cast<String>(cansatdata.voltage_load) + " V");

        // Initialize GPS
        cansatdata.year = 0;
        cansatdata.month = 0  ;
        cansatdata.day = 0;
        cansatdata.hour = 0;
        cansatdata.minute = 0;
        cansatdata.sec = 0;
        cansatdata.latitude = 0;
        cansatdata.longitude = 0;
        cansatdata.num_of_satelites = 0;

        // save start time in millisec
        uint32_t start = millis();

        // END LED BLINK
        digitalWrite(D13_led_pin, LOW);


        pinMode(M_led_pin, INPUT);
        // END LED BLINK

        if(isGpsConnected)
        {
          if (gps.scan(250))
          {
            cansatdata.year = gps.getYear();
            cansatdata.month = gps.getMonth();
            cansatdata.day = gps.getDay();
            cansatdata.hour = gps.getHour();
            cansatdata.minute = gps.getMinute();
            cansatdata.sec = gps.getSecond();
            cansatdata.latitude = gps.getLat();
            cansatdata.longitude = gps.getLon();
            cansatdata.num_of_satelites = gps.getNumberOfSatellites();
            Serial.println(String("Time to find fix: ") + (millis() - start) + String("ms"));
            Serial.println(String("Datetime: ") + String(cansatdata.year) + "/"+ String(cansatdata.month) + "/"+ String(cansatdata.day) + " " + String(cansatdata.hour) + ":"+ String(cansatdata.minute) + ":"+ String(cansatdata.sec));
            Serial.println(String("Lat: ") + String(cansatdata.latitude, 7));
            Serial.println(String("Lon: ") + String(cansatdata.longitude, 7));
            Serial.println(String("Num of sats: ") + String(cansatdata.num_of_satelites));
            Serial.println();
          }
          else
          {
            Serial.println("Gps have no satelit to fix.");
          }
        }

        // RFM69HW
        cansatdata.rssi = 0;

        if(isRadioOk)
        {
          cansatdata.rssi = radio.RSSI;
          Serial.println("Signal = " + static_cast<String>(radio.RSSI));

          radio.send(TONODEID, (const void*)&cansatdata, sizeof(cansatdata));
        }

        Serial.println();

        // START LED hart beat
        pinMode(M_led_pin, OUTPUT);

        digitalWrite(D13_led_pin, HIGH);

        digitalWrite(M_led_pin, HIGH);
        // START LED hart beat

        if(!isGpsConnected)
        {
        delay(200);
        }

        idCounter ++;

      }

大多数 SPI 接口可以置于 'loopback' 模式,这使得代码可以轻松检查 activity 以验证 transmitted/received 数据

关于:

if (error != 0)
{
    isGpsConnected = false;
}

// begin communication with gps
gps.begin();   

如果没有连接 GPS,则不应尝试与 GPS 通信。建议:

if (error != 0)
{
    isGpsConnected = false;
    return;
}

else
{
    // begin communication with gps
    gps.begin();
}