编译环境:arduino 编写
开发板选择:esp32 cam开发板
手里恰好有一块esp32 cam的开发板,随使用了文件系统驱动SD卡,方便后期使用,使用SDMMC接口访问SD卡 。
在文件读取部分稍微处理了一下,读取SD卡wifi信息进行连接,这样避免配网或者修改wifi信息,示例代码读取WiFi并且连接。
使用这玩意,SD卡DATA1 和LED灯使用一个I/O口,这就有点离谱,只要有数据读写,灯就被点亮。
此原理图来源esp32 cam开发板:
外接47K上拉电阻。U0TXD和T0RXD用于烧录固件。
ESP-32S Module | SD |
---|---|
14(GPIO12) | HS2_DATA2(DATA2) |
16(GPIO13) | HS2_DATA2(CD/DATA3) |
23(SDI/SD1) | HS2_CMD(CMD) |
13(GPIO14) | HS2_CLK(CLK) |
24(GPIO2) | HS2_DATA0(DATA0) |
26(GPIO4) | HS2_DATA1(DATA1) |
1、文件操作常用API
包含在:FS.cpp 文件中,有意向可以查看。
打开文件:
File FS::open(const String& path, const char* mode)
File FS::open(const char* path, const char* mode)
path:为打开路径,mode:为打开方式,mode可选FILE_READ、FILE_WRITE、FILE_APPEND,即只读模式、写入模式、追加模式;
写入文件:
File print(const char * message)
message:要写入的信息
size_t File::write(uint8_t c)
size_t File::write(const uint8_t *buf, size_t size)
读取文件:
int File::available()
返回当前指针下可读取字节数;
int File::read()
size_t File::read(uint8_t* buf, size_t size)
size_t readBytes(char *buffer, size_t length)
读取数据,该操作会移动文件指针;
关闭当前文件:
void File::close()
在不移动文件指针的情况下读取一个字节数据:
int File::peek()
移动文件指针,mode可选SeekSet、SeekCur、SeekEnd,分别为正常移动、移动到文件头、移动到文件尾:
bool File::seek(uint32_t pos, SeekMode mode)
返回当前文件指针位置:
size_t File::position() const
返回当前文件的大小:
size_t File::size() const
返回当前文件是否有效:
File::operator bool() const
返回最后修改文件时间:
time_t File::getLastWrite()
返回当前文件名:
const char* File::name() const
返回当前文件是否为目录:
boolean File::isDirectory(void)
打开下一个文件:
File File::openNextFile(const char* mode)
返回到目录中首文件位置:
void File::rewindDirectory(void)
检查文件或路径是否存在:
bool FS::exists(const char* path)
bool FS::exists(const String& path)
移除文件:
bool FS::remove(const char* path)
bool FS::remove(const String& path)
重命名文件,依次输入旧的、新的包含完整文件名的路径:
bool FS::rename(const char* pathFrom, const char* pathTo)
bool FS::rename(const String& pathFrom, const String& pathTo)
创建目录:
bool FS::mkdir(const char *path)
bool FS::mkdir(const String &path)
删除目录:
bool FS::rmdir(const char *path)
bool FS::rmdir(const String &path)
判断指定的目录是否是加载点:
void FSImpl::mountpoint(const char * mp)
const char * FSImpl::mountpoint()
如果是挂载点返回0,如果不是就返回非0
2、SPIFFS文件系统
包含在:SD_MMC.h头文件
挂载文件系统:
bool begin(const char * mountpoint="/sdcard", bool mode1bit=false);
取消挂载文件系统:
void end()
检测SD卡大小:
uint64_t cardSize();
格式化文件系统:
bool format()
返回文件系统总字节数:
size_t totalBytes()
返回文件系统已用字节数:
size_t usedBytes()
3 、读取SD卡WiFi并且连接
新建一个“/WiFi/WiFi.txt ”路径用于保存WiFi信息
写入WiFi信息:
看清楚自己建立的WiFi信息路径。
首先在代码里面添加变量,保存WiFi信息:
const char* ssid = "";
const char* password = "";
其次读取SD卡信息:
定义一些变量,处理读取信息。
char seps[]= "\r\n";
char *stass;
char *buf[3];
int i=0;
String comdata = "";
//stass = NULL;
//读取 文件
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path,FILE_READ);//FILE_READ 只读模式
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
comdata += char(file.read());//方便读取使用
//Serial.write(file.read()); //发送字节
}
file.close();
Serial.println(comdata);
char * p=(char*)comdata.c_str();
stass=strtok(p,seps);
//Serial.println(stass);
/* 继续获取其他的子字符串 */
while( stass != NULL ) {
buf[i] = stass;
++i;
stass = strtok(NULL, seps);
}
ssid = buf[0];
password = buf[1];
Serial.println(buf[0]);
Serial.println(buf[1]);
}
4、完整示例代码
完整代码包含文件夹的创建、文件夹删除、文件读取、文件写入、文件名修改、移除文件,WiFi信息读取连接。
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include <time.h>
#include <WiFi.h>
const char* ssid = "";
const char* password = "";
long timezone = 1;
byte daysavetime = 1;
// 显示全部文件名称
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.print (file.name());
time_t t= file.getLastWrite();
struct tm * tmstruct = localtime(&t);
Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
if(levels){
listDir(fs, file.name(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.print(file.size());
time_t t= file.getLastWrite();
struct tm * tmstruct = localtime(&t);
Serial.printf(" LAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct->tm_year)+1900,( tmstruct->tm_mon)+1, tmstruct->tm_mday,tmstruct->tm_hour , tmstruct->tm_min, tmstruct->tm_sec);
}
file = root.openNextFile();
}
}
//新建文件夹
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
// 移除文件夹
void removeDir(fs::FS &fs, const char * path){
Serial.printf("Removing Dir: %s\n", path);
if(fs.rmdir(path)){
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
char seps[]= "\r\n";
char *stass;
char *buf[3];
int i=0;
String comdata = "";
//stass = NULL;
//读取 文件
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path,FILE_READ);//FILE_READ 只读模式
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
comdata += char(file.read());//方便读取使用
//Serial.write(file.read()); //发送字节
}
file.close();
Serial.println(comdata);
//char string[]=comdata;
char * p=(char*)comdata.c_str();
stass=strtok(p,seps);
//Serial.println(stass);
/* 继续获取其他的子字符串 */
while( stass != NULL ) {
buf[i] = stass;
++i;
stass = strtok(NULL, seps);
}
ssid = buf[0];
password = buf[1];
Serial.println(buf[0]);
Serial.println(buf[1]);
}
//写入文件
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
// 追加文件
void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
// 修改名字
void renameFile(fs::FS &fs, const char * path1, const char * path2){
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
// 删除
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
void setup(){
Serial.begin(115200);
// We start by connecting to a WiFi network
Serial.println();
if(!SD_MMC.begin()){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
//输出SD卡类型
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
listDir(SD_MMC, "/", 0);
removeDir(SD_MMC, "/mydir");
createDir(SD_MMC, "/mydir");
deleteFile(SD_MMC, "/mydir/hello.txt");
writeFile(SD_MMC, "/mydir/hello.txt", "Hello World!\r\n");
appendFile(SD_MMC, "/mydir/hello.txt", "Moonbeam");
listDir(SD_MMC, "/", 0);
readFile(SD_MMC, "/WiFi/WiFi.txt");
SD_MMC.end();// 取消挂载SD卡
pinMode(4, OUTPUT); //Light
digitalWrite(4, LOW);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Contacting Time Server");
configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
struct tm tmstruct ;
delay(2000);
tmstruct.tm_year = 0;
getLocalTime(&tmstruct, 5000);
Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1951,( tmstruct.tm_mon)+1, (tmstruct.tm_mday)+25,(tmstruct.tm_hour)+13 , (tmstruct.tm_min)+36, tmstruct.tm_sec);
Serial.println("");
}
void loop(){
}