#include "SdFat.h"
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 0
/*
Change the value of SD_CS_PIN if you are using SPI and
your hardware does not use the default value, SS.
Common values are:
Arduino Ethernet shield: pin 4
Sparkfun SD shield: pin 8
Adafruit SD shields and modules: pin 10
*/
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
// Try max SPI clock for an SD. Reduce SPI_CLOCK if errors occur.
#define SPI_CLOCK SD_SCK_MHZ(50)
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
#if SD_FAT_TYPE == 0
SdFat sd;
File file;
#elif SD_FAT_TYPE == 1
SdFat32 sd;
File32 file;
#elif SD_FAT_TYPE == 2
SdExFat sd;
ExFile file;
#elif SD_FAT_TYPE == 3
SdFs sd;
FsFile file;
#else // SD_FAT_TYPE
#error Invalid SD_FAT_TYPE
#endif // SD_FAT_TYPE
char line[40];
//------------------------------------------------------------------------------
// Store error strings in flash to save RAM.
#define error(s) sd.errorHalt(&Serial, F(s))
//------------------------------------------------------------------------------
// Check for extra characters in field or find minus sign.
char* skipSpace(char* str) {
while (isspace(*str)) str++;
return str;
}
//------------------------------------------------------------------------------
bool parseLine(char* str) {
char* ptr;
// Set strtok start of line.
str = strtok(str, ",");
if (!str) return false;
// Print text field.
Serial.println(str);
// Subsequent calls to strtok expects a null pointer.
str = strtok(nullptr, ",");
if (!str) return false;
// Convert string to long integer.
int32_t i32 = strtol(str, &ptr, 0);
if (str == ptr || *skipSpace(ptr)) return false;
Serial.println(i32);
str = strtok(nullptr, ",");
if (!str) return false;
// strtoul accepts a leading minus with unexpected results.
if (*skipSpace(str) == '-') return false;
// Convert string to unsigned long integer.
uint32_t u32 = strtoul(str, &ptr, 0);
if (str == ptr || *skipSpace(ptr)) return false;
Serial.println(u32);
str = strtok(nullptr, ",");
if (!str) return false;
// Convert string to double.
double d = strtod(str, &ptr);
if (str == ptr || *skipSpace(ptr)) return false;
Serial.println(d);
// Check for extra fields.
return strtok(nullptr, ",") == nullptr;
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
Serial.println("Type any character to start");
while (!Serial.available()) {
yield();
}
// Initialize the SD.
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
return;
}
// Remove any existing file.
if (sd.exists("ReadCsvDemo.csv")) {
sd.remove("ReadCsvDemo.csv");
}
// Create the file.
if (!file.open("ReadCsvDemo.csv", FILE_WRITE)) {
error("open failed");
}
// Write test data.
file.print(
F("abc,123,456,7.89\r\n"
"def,-321,654,-9.87\r\n"
"ghi,333,0xff,5.55"));
// Rewind file for read.
file.rewind();
while (file.available()) {
int n = file.fgets(line, sizeof(line));
if (n <= 0) {
error("fgets failed");
}
if (line[n - 1] != '\n' && n == (sizeof(line) - 1)) {
error("line too long");
}
if (!parseLine(line)) {
error("parseLine failed");
}
Serial.println();
}
file.close();
Serial.println(F("Done"));
}
void loop() {}