전원 인가시 포맷 실행함.
eraseCard() 함수는 섹터를 '0'으로 채우는 기능인데 에러 발생함
formatCard() 함수로 실제 데이터 삭제없이 빠른 포맷 실행.
/*
* This program will format SD/SDHC/SDXC cards.
* Warning all data will be deleted!
*
* This program attempts to match the format
* generated by SDFormatter available here:
*
* http://www.sdcard.org/consumers/formatter/
*
* For very small cards this program uses FAT16
* and the above SDFormatter uses FAT12.
*/
#ifndef DISABLE_FS_H_WARNING
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
#endif // DISABLE_FS_H_WARNING
#include "SdFat.h"
#include "sdios.h"
#include "U8glib.h"
#include <Wire.h> //for nano sda scl a4 a5
// OLED 설정
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);
/*
Set DISABLE_CS_PIN to disable a second SPI device.
For example, with the Ethernet shield, set DISABLE_CS_PIN
to 10 to disable the Ethernet controller.
*/
const int8_t DISABLE_CS_PIN = -1;
/*
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)
// SPI_CLOCK 값을 낮춤
//#define SPI_CLOCK SD_SCK_MHZ(16) // 50MHz → 16MHz로 낮춤
// 또는
#define SPI_CLOCK SD_SCK_MHZ(4) // 더 낮춤
// Try to select the best SD card configuration.
#if defined(HAS_TEENSY_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif defined(HAS_BUILTIN_PIO_SDIO)
// See the Rp2040SdioSetup example for boards without a builtin SDIO socket.
#define SD_CONFIG SdioConfig(PIN_SD_CLK, PIN_SD_CMD_MOSI, PIN_SD_DAT0_MISO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_TEENSY_SDIO
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_TEENSY_SDIO
//==============================================================================
// Serial output stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
uint32_t cardSectorCount = 0;
uint8_t sectorBuffer[512] __attribute__ ((aligned (4)));
//------------------------------------------------------------------------------
// SdCardFactory constructs and initializes the appropriate card.
SdCardFactory cardFactory;
// Pointer to generic SD card.
SdCard* m_card = nullptr;
//------------------------------------------------------------------------------
#define sdError(msg) \
{ \
cout << F("error: ") << F(msg) << endl; \
sdErrorHalt(); \
}
//-
// -----------------------------------------------------------------------------
void sdErrorHalt() {
if (!m_card) {
cout << F("Invalid SD_CONFIG") << endl;
dis_oled3( "","Error:", "Invalid SD_CONFIG", "Check wiring", "");
} else if (m_card->errorCode()) {
if (m_card->errorCode() == SD_CARD_ERROR_CMD0) {
cout << F("No card, wrong chip select pin, or wiring error?") << endl;
dis_oled3( "","Error:", "No SD Card", "or wiring error", "Check CS pin");
}
cout << F("SD errorCode: ") << hex << showbase;
printSdErrorSymbol(&Serial, m_card->errorCode());
cout << F(" = ") << int(m_card->errorCode()) << endl;
cout << F("SD errorData = ") << int(m_card->errorData()) << endl;
dis_oled3( "","SD Error:", String(m_card->errorCode()), String(m_card->errorData()), "");
}
while (true) {
delay(1000);
}
}
void clearSerialInput() {
uint32_t m = micros();
do {
if (Serial.read() >= 0) {
m = micros();
}
} while (micros() - m < 10000);
}
//------------------------------------------------------------------------------
// OLED 표시 함수
void dis_oled3(String msg1, String msg2, String msg3, String msg4, String msg5) {
int idx[] = {10, 26, 39, 52, 65};
String str[5];
str[0] = msg1;
str[1] = msg2;
str[2] = msg3;
str[3] = msg4;
str[4] = msg5;
u8g.firstPage();
do {
u8g.setFont(u8g_font_unifont);
for (int i = 0; i < 5; i++) {
u8g.setPrintPos(0, idx[i]);
u8g.print(str[i]);
}
} while (u8g.nextPage());
}
//------------------------------------------------------------------------------
// 진행 상태 표시 함수
void showProgress(String message, int progress = -1) {
String progressBar = "---";
if (progress >= 0) {
progressBar = "";
for (int i = 0; i < 3; i++) {
if (i < progress % 4) {
progressBar += "*";
} else {
progressBar += "-";
}
}
}
dis_oled3("","SD Formatter", message, progressBar, "");
}
//------------------------------------------------------------------------------
// flash erase all data
uint32_t const ERASE_SIZE = 262144L;
void eraseCard() {
cout << endl << F("Erasing\n");
showProgress("Erasing card", 0);
uint32_t firstBlock = 0;
uint32_t lastBlock;
uint16_t n = 0;
int progressCount = 0;
do {
lastBlock = firstBlock + ERASE_SIZE - 1;
if (lastBlock >= cardSectorCount) {
lastBlock = cardSectorCount - 1;
}
if (!m_card->erase(firstBlock, lastBlock)) {
sdError("erase failed");
}
// 진행 상태 업데이트 (3초마다)
if (millis() % 3000 < 100) {
showProgress("Erasing card", progressCount % 4);
progressCount++;
}
firstBlock += ERASE_SIZE;
} while (firstBlock < cardSectorCount);
cout << endl;
if (!m_card->readSector(0, sectorBuffer)) {
sdError("readBlock");
}
cout << hex << showbase << setfill('0') << internal;
cout << F("All data set to ") << setw(4) << int(sectorBuffer[0]) << endl;
cout << dec << noshowbase << setfill(' ') << right;
cout << F("Erase done\n");
showProgress("Erase complete", 3);
delay(1000);
}
//------------------------------------------------------------------------------
void formatCard() {
showProgress("Formatting", 0);
ExFatFormatter exFatFormatter;
FatFormatter fatFormatter;
// Format exFAT if larger than 32GB.
bool rtn = cardSectorCount > 67108864
? exFatFormatter.format(m_card, sectorBuffer, &Serial)
: fatFormatter.format(m_card, sectorBuffer, &Serial);
if (!rtn) {
sdErrorHalt();
}
showProgress("Format complete", 3);
cout << F("Format completed successfully!") << endl;
delay(1000);
}
//------------------------------------------------------------------------------
void printConfig(SdSpiConfig config) {
if (DISABLE_CS_PIN < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CS_PIN to disable an SPI device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CS_PIN) << endl;
pinMode(DISABLE_CS_PIN, OUTPUT);
digitalWrite(DISABLE_CS_PIN, HIGH);
}
cout << F("\nAssuming the SD chip select pin is: ") << int(config.csPin);
cout << F("\nEdit SD_CS_PIN to change the SD chip select pin.\n");
}
//------------------------------------------------------------------------------
void printConfig(SdioConfig config) {
(void)config;
cout << F("Assuming an SDIO interface.\n");
}
//------------------------------------------------------------------------------
void setup() {
// OLED 초기화
u8g.firstPage();
do {
u8g.setFont(u8g_font_unifont);
u8g.setPrintPos(0, 10);
u8g.print("Initializing...");
} while (u8g.nextPage());
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
showProgress("Initializing", 0);
delay(1000);
// 카드 초기화 후 지연 시간 추가
m_card = cardFactory.newCard(SD_CONFIG);
if (!m_card || m_card->errorCode()) {
sdError("card init failed.");
return;
}
// 추가: 초기화 후 안정화를 위한 대기 시간
delay(100);
// 추가: 카드가 idle 상태에서 벗어났는지 확인
uint32_t start = millis();
while (m_card->errorCode() && millis() - start < 5000) {
delay(10);
}
// 자동으로 포맷 시작
showProgress("Starting format", 1);
delay(1000);
// Select and initialize proper card driver.
showProgress("Detecting SD card", 2);
m_card = cardFactory.newCard(SD_CONFIG);
if (!m_card || m_card->errorCode()) {
sdError("card init failed.");
return;
}
cardSectorCount = m_card->sectorCount();
if (!cardSectorCount) {
sdError("Get sector count failed.");
return;
}
// 카드 정보 표시
showProgress("Card detected", 3);
delay(1000);
cout << F("\nCard size: ") << cardSectorCount * 5.12e-7;
cout << F(" GB (GB = 1E9 bytes)\n");
cout << F("Card size: ") << cardSectorCount / 2097152.0;
cout << F(" GiB (GiB = 2^30 bytes)\n");
cout << F("Card will be formated ");
if (cardSectorCount > 67108864) {
cout << F("exFAT\n");
showProgress("Format: exFAT", 0);
} else if (cardSectorCount > 4194304) {
cout << F("FAT32\n");
showProgress("Format: FAT32", 0);
} else {
cout << F("FAT16\n");
showProgress("Format: FAT16", 0);
}
delay(1000);
// 자동으로 지우기 + 포맷 수행 (F 옵션)
// showProgress("Starting erase", 1);
// eraseCard();
showProgress("Starting format", 2);
formatCard();
// 완료 메시지
showProgress("COMPLETE!", 3);
dis_oled3("","SD Erase", "COMPLETE!", "Card is ready", "Remove card");
cout << F("Format completed successfully!") << endl;
}
void loop() {
// 완료 후 아무 작업도 하지 않음
delay(1000);
}'diy > 아두이노' 카테고리의 다른 글
| SD 메모리 포맷 전용기기 만들기(1) (0) | 2025.10.11 |
|---|---|
| [에러]irremote 라이브러리 결과가 항상 ffff(65536) (1) | 2024.01.14 |
| 아두이노 나노로 리모컨 카운터(계수기) 만들기 (0) | 2024.01.13 |
| 리모콘 ir신호 표시기 만들기 (1) | 2023.09.30 |
| 이산화탄소 측정기(MH-Z14) 만들기 2 (0) | 2022.10.07 |