与其他SPI设备一起使用时,Arduino SD卡无法写入

时间:2017-10-10 19:32:25

标签: arduino sd-card spi

我有一个ADXL355加速度计连接到Adafruit Feather Adalogger。我可以配置和读取传感器。我也可以将二进制值写入SD卡。当我尝试从传感器读取然后将该数据写入SD卡时,会出现问题。我唯一能想到的是我在某种程度上弄乱了SPI通信,但我无法看到它在哪里。我通过pins_arduino.h查看了我的电路板,SD卡(引脚4)与引脚10位于不同的寄存器上,因此我看不出我是如何破坏它的。

我的操作就像这样进行。全局传感器创建,Serial.beginSD.beginSPI.begin,测试传感器连接,创建SD卡输出文件,初始化传感器,读取传感器FIFO,写入文件,永远重复最后2。

文件已创建,但文件大小保持为0,即实际上没有任何内容写入卡片。

传感器可以在4 kHz下工作,使用digitalWrite功能很难实现,所以我切换到使用羽毛上的端口寄存器。我是这样做的:

#include <SM_ADXL355_SPI_fast.h>
#include <SPI.h>
#include <SD.h>

#define cardSelect 4

ADXL355_SPIF adxl355(&DDRB, &PORTB, _BV(6)); // values taken from pins_arduino.h, tested and working on pin 10
void setup() {
  Serial.begin(57600);
  while(!Serial){
    // wait for Serial
  }
  SD.begin(cardSelect);
  SPI.begin();
  while(!adxl355.TestConnection()){
    delay(1000);  
  }
  adxl355.OpenFile("TestSPI.bin");
  adxl355.Initialize(1, 10, 0); // set range to 2g's, frequency to 4 Hz and filter to off
}

void loop() {
  while(true){ // avoid Arduino overhead of their loop function
    adxl355.ReadFIFO();
    adxl355.WriteFIFOToFile();
  }
}

这是ADXL构造函数

ADXL355_SPIF::ADXL355_SPIF(volatile uint8_t * outReg, volatile uint8_t * outPort, uint8_t bitValue) : sensorOutReg(outReg), sensorPort(outPort), sensorBitValue(bitValue){
    *sensorOutReg |= sensorBitValue;
    *sensorPort |= sensorBitValue;
    sensorWriteCount = 0;
}

TestConnection测试DeviceID读取0xADInitialize设置G范围,以Hz为单位的采样率和过滤器。我用串行输出测试了它们,它们正常工作。

OpenFile看起来像这样:

bool ADXL355_SPIF::OpenFile(const String& fileName){
    sensorFile = SD.open(fileName, FILE_WRITE);
    if (!sensorFile){
        Serial.print("Could not create file: ");
        Serial.println(fileName);
        return false;
    }
    return true;
}

运行此文件后,文件确实在名为“TESTSPI.BIN”的SD卡上创建,文件大小为0。

ReadFIFO读取FIFO中的条目数,存储为fifoCount,然后使用FIFO中的值填充缓冲区(sensorFIFO[32][3])。我已将此缓冲区打印到Serial以显示它正在工作。这是函数

void ADXL355_SPIF::ReadFIFO(){
    ReadRegister(ADXL355_RA_FIFO_ENTRIES, 1);
    fifoCount = buffer[0];
    ReadFIFOInternal();
    return;
}

void ADXL355_SPIF::ReadFIFOInternal(){
    SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
    *sensorPort &= ~sensorBitValue;
    uint8_t spiCommand = ADXL355_RA_FIFO_DATA << 1 | ADXL355_READ;
    SPI.transfer(spiCommand);
    int i = 0;
    unsigned long tempV;
    unsigned long value;
    while(i < fifoCount){
        for (int ptr = 0; ptr < 3; ++ptr){
            buffer[0] = SPI.transfer(0x0);
            value = buffer[0];
            value <<= 12;
            tempV = SPI.transfer(0x0);
            tempV <<= 4;
            value |= tempV;
            tempV = SPI.transfer(0x0);
            tempV >>=4;
            value |= tempV;
            if (buffer[0] & 0x80) {
                value |= 0xFFF00000;
            }
            long lValue = static_cast<long>(value);
            sensorFIFO[i][ptr] = scaleFactor * lValue;
        }
        i += 3;
    }
    SPI.endTransaction();
    *sensorPort |= sensorBitValue;
    return;
}

以下是WriteFIFOToFile

void ADXL355_SPIF::WriteFIFOToFile(){
    if (fifoCount > 0){
        sensorFile.write(reinterpret_cast<const char *>(&sensorFIFO), 4 * fifoCount);
    }
    sensorWriteCount += fifoCount;
    if (sensorWriteCount >= 100){
        sensorFile.flush();
        sensorWriteCount = 0;
    }
}

允许它运行一段时间之后,文件大小始终为0.我尝试了一个简单的二进制写入功能来测试卡。它看起来像这样,并且有效。

#include <SD.h>

#define cardSelectPin 4

const float pi=3.14159;

File oFile;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while(!Serial){
    // wait for serial
  }
  SD.begin(cardSelectPin);
  oFile = SD.open("Test.bin", FILE_WRITE);
  Serial.println(sizeof(int));
  Serial.println(sizeof(float));
  float testFloat[32][3];
  for (int i = 0; i < 32; ++i){
    for (int j = 0; j < 3; ++j){
      testFloat[i][j] = pi * (i + 1) + j;
    }
  }
  oFile.write(reinterpret_cast<const char *>(&testFloat), sizeof(float) * 96);
  oFile.close();
  Serial.println("Finished writing file.");
}

void loop() {
  // put your main code here, to run repeatedly:

}

2 个答案:

答案 0 :(得分:1)

问题是没有正确调用flush。我已经创建了一个缓冲区来保存来自FIFO的数据,当它足够充满以便后续读取溢出时,它会刷新卡。那时它会调用sensorWriteCount。这是变量uint8_t的目的。此变量的类型为uint16_t,应该是 FOR v IN 1..2 OUTBOUND "teacher_id" GRAPH "graph_name" FILTER LIKE(v._id, "pupil_collection_name/%") FOR homeworks IN 1 OUTBOUND v GRAPH "graph_name" LIMIT lowerLimit,numberOfItems RETURN homeworks

更改为正确的类型解决了问题。我本来会删除这个问题,因为它归结为一个错字,但是一旦发布了答案,系统就不允许这样做。

答案 1 :(得分:0)

非工作草图和工作草图之间的唯一区别是关闭SD卡。必须关闭SD卡,我遇到了同样的问题,我假设文件在文件关闭调用时在文件系统中写入边界。
要解决您的问题,请使用按钮。当您按下它时,它将关闭文件并停止读取/处理传感器。您也可以使用此按钮再次开始在SD卡上读取和记录传感器数据(切换)。