首页 文章

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

提问于
浏览
1

我有一个ADXL355加速度计连接到Adafruit Feather Adalogger . 我可以配置和读取传感器 . 我也可以将二进制值写入SD卡 . 当我尝试从传感器读取然后将该数据写入SD卡时,会出现问题 . 我能想到的唯一一件事是我看到了哪里 . 我通过 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读取 0xAD . Initialize 设置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] ) . 我've printed this buffer to Serial to show that it'正在工作 . 这是那个功能

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 回答

  • 1

    问题是没有正确调用 flush . 我已经创建了一个缓冲区来保存来自FIFO的数据,当它足够充满以便后续读取溢出时,它会刷新卡 . 那时它会调用 flush . 这是变量 sensorWriteCount 的目的 . 该变量的类型为 uint8_t ,应该是 uint16_t .

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

  • 0

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

相关问题