1、平台的条件
1.1 软件平台:esp-idf_v3.3
1.2 硬件平台: esp32
本人的联系方式: QQ: 1297311998 ,如果有什么问题,请高手不吝赐教
2、如何使用
只是介绍代码的使用情况,用的是乐鑫自带的库文件,和一些简单的原理
2.1 .h 文件
#ifndef sd_card_h_
#define sd_card_h_
#include <stdio.h>
#include <string.h>
// 传感器数据结构体,要存数据
typedef struct
{
uint8_t tem_hum[4];
uint8_t CO2_valu[2];
uint8_t PM_25[2];
uint8_t VOC_valu[2];
uint8_t Li3DH_valu[6];
uint8_t GPS_valu[16];
uint8_t CO[3];
uint8_t NO2[3];
uint8_t SO2[3];
uint8_t Ozone[3];
} STU_HIS;
extern STU_HIS sensor_data;
uint8_t sd_card_init(void);
void task_write_sd_card_data(void);
void task_read_sd_card_data(void);
#endif
2.2 .c文件
2.2.1 sd_card_init 函数
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_vfs_fat.h"
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "sdmmc_cmd.h"
#include "in_flash_data.h"
#include "sd_card.h"
#include "ble_gatts.h"
#include "ff.h"
#include "interface_rtc.h"
STU_HIS sensor_data;
static const char *TAG = "sd_card";
#define USE_SPI_MODE
// 定义 SPI 的io
#ifdef USE_SPI_MODE
#define PIN_NUM_MISO 19//2
#define PIN_NUM_MOSI 23// 15
#define PIN_NUM_CLK 18//14
#define PIN_NUM_CS 5// 13
#endif
static uint8_t is_init_sd_card_failed = 0; // 初始化sd 卡成
uint32_t sd_card_capacity_MB = 0; // 容量 单位为 :MB
// sd_card_init 的初始化---------------
uint8_t sd_card_init(void)
{
ESP_LOGI(TAG, "Using SPI peripheral");
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
slot_config.gpio_miso = PIN_NUM_MISO;
slot_config.gpio_mosi = PIN_NUM_MOSI;
slot_config.gpio_sck = PIN_NUM_CLK;
slot_config.gpio_cs = PIN_NUM_CS;
esp_vfs_fat_sdmmc_mount_config_t mount_config =
{
.format_if_mount_failed = false,
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
// 初始化 SD卡
sdmmc_card_t* card;
esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
// 初始化不成功
if (ret != ESP_OK)
{
is_init_sd_card_failed = 1;
if (ret == ESP_FAIL)
{
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set format_if_mount_failed = true.");
}
else
{
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
}
return ret;
}
// Card has been initialized, print its properties (特性)
sdmmc_card_print_info(stdout, card);
// 得到SD卡的最大容量-----转化为MB,后面检查使用
sd_card_capacity_MB = ((uint64_t) card->csd.capacity) * card->csd.sector_size / (1024 * 1024);
ESP_LOGE(TAG, "sd capatiy %d",sd_card_capacity_MB);
return ret;
}
初始化不成功,重新初始化,3次
static void reset_sd_card(void)
{
uint8_t i;
esp_vfs_fat_sdmmc_unmount();
for(i=0;i>3;i++)
{
delay_ms(100);
if(sd_card_init())
{
break;
}
}
}
2.2.2 sd卡的写入函数
调用的系统文件函数,来进行sd的写入和读取数据
// 比较两个数的大小
static uint16_t chg_2_int16(int16_t a,int16_t b)
{
return a>b ? a-b:b-a;
}
// **检查还剩余的文件大小**
void check_file_size(void)
{
struct stat st;
long sd_file_size =0;
stat("/sdcard/sensor.txt",&st);
sd_file_size = st.st_size;
ESP_LOGE(TAG, "sd_file_size=%ld ------,sd_card_capacity= %d",sd_file_size,sd_card_capacity_MB);
// 已经使用的sd卡容量超过,就删除
if(st.st_size>=((sd_card_capacity_MB-2)*1024*1024))
{
ESP_LOGE(TAG, "remove sd file");
remove("/sdcard/sensor.txt");
}
}
获得传感器的数据---------------------------
//
static uint8_t sd_save_data[sizeof(sensor_data)] ;
void get_sensor_data(void)
{
sd_save_data[len++]=sensor_data.tem_hum[0];
sd_save_data[len++]=sensor_data.tem_hum[1];
sd_save_data[len++]=sensor_data.tem_hum[2];
sd_save_data[len++]=sensor_data.tem_hum[3];
// c02
sd_save_data[len++]=sensor_data.CO2_valu[0];
sd_save_data[len++]=sensor_data.CO2_valu[1] ;
// PM2.5
sd_save_data[len++]=sensor_data.PM_25[0];
sd_save_data[len++]=sensor_data.PM_25[1];
sd_save_data[len++]=sensor_data.PM_25[0];
sd_save_data[len++]=sensor_data.PM_25[1];
sd_save_data[len++]=sensor_data.Li3DH_valu[0];
sd_save_data[len++]=sensor_data.Li3DH_valu[1];
sd_save_data[len++]=sensor_data.Li3DH_valu[2];
}
sd卡的写入函数,正在读取数据的时候不能写
static uint8_t sd_card_reading =0; // 正在读的标志
//write sd card data-----------------------------------
void task_write_sd_card_data(void)
{
int16_t timemin;
static int16_t timemin_b=0;
timemin=sensor_data.UTCTime;
// step 1: write time interval,写入的时间间隔,
// 这边是定时写入
if(chg_2_int16(timemin,timemin_b)>=user_data.save_sensor_minutes)
{
timemin_b=timemin;
}
else
{
return;
}
// step 2: 检测是否真正在读取,或初始化不成功就不进行写入
if((sd_card_reading==1)||(is_init_sd_card_failed==1)) return;
// step 3: ׁ得到传感器的数据-----
get_sensor_data();
// step 4: 检查SD 卡的剩余的大小
check_file_size();
// step 5:打开sd 卡
FILE* pfile = fopen("/sdcard/sensor.txt", "ab+"); //
if (pfile == NULL) //
{
ESP_LOGE(TAG, "Failed to open file for writing");
reset_sd_card();
}
//进行写入数据
fwrite(sd_save_data,sizeof(sensor_data),1,pfile);
// 关闭sd卡
fclose(pfile);
ESP_LOGI(TAG, "sd write sensor data time_interv_s=%d",user_data.save_sensor_minutes);
}
2.2.3 sd卡读取函数
uint8_t read_buffer[sizeof(sensor_data)];//
void task_read_sd_card_data(void)
{
uint32_t read_len =0;
sd_card_reading =1;
memset(read_buffer,0,sizeof(read_buffer));
FILE* pfile = fopen("/sdcard/sensor.txt", "rb");
if (pfile == NULL)
{
ESP_LOGE(TAG, "Failed to open file for writing");
reset_sd_card();
}
while(!feof(pfile))
{
read_len = fread(read_buffer, 1, sizeof(sensor_data) , pfile);
}
sd_card_reading =0;
fclose(pfile);
}
可以加入QQ群:687360507
与大伙沟通交流,技术在于分享而进步