最近收到了一片國(guó)產(chǎn)工業(yè)級(jí)SD NAND,可以替代SD卡,容量大,貼片封裝,非常適合做飛控"黑匣子"。
不用寫驅(qū)動(dòng)程序自帶壞塊管理的NAND Flash(貼片式TF卡),尺寸小巧,簡(jiǎn)單易用,兼容性強(qiáng),穩(wěn)定可靠,固件可定制,LGA-8封裝,標(biāo)準(zhǔn)SDIO接口,兼容SPI/SD接口,兼容各大MCU平臺(tái),可替代普通TF卡/SD卡,尺寸6x8mm毫米,內(nèi)置SLC晶圓擦寫壽命10萬(wàn)次,通過(guò)1萬(wàn)次隨機(jī)掉電測(cè)試耐高低溫,支持工業(yè)級(jí)溫度-40°~+85°,機(jī)貼手貼都非常方便,速度級(jí)別Class10(讀取速度23.5MB/S寫入速度12.3MB/S)標(biāo)準(zhǔn)的SD 2.0協(xié)議使得用戶可以直接移植標(biāo)準(zhǔn)驅(qū)動(dòng)代碼,省去了驅(qū)動(dòng)代碼編程環(huán)節(jié)。支持TF卡啟動(dòng)的SOC都可以用SD NAND,廠商提供了STM32參考例程及原廠技術(shù)支持,主流容量:128MB/512MB/2GB/4GB/8GB,比TF卡穩(wěn)定,比eMMC便宜。
飛控板上ESP32C3的SDIO接口暫時(shí)用不了,只能先用SPI接口驅(qū)動(dòng)。
評(píng)估板做了個(gè)micro SD卡的接口,方便直接插到帶卡槽的開發(fā)板上進(jìn)行調(diào)試。
ESP32C3的SPI接口是硬件SPI,支持DMA,速度應(yīng)該還可以,但是我用杜邦線連接的,肯定會(huì)影響信號(hào)質(zhì)量,估計(jì)時(shí)鐘很難跑到50MHz了。
接線:
編寫測(cè)試程序:
/* SD card and FAT filesystem example.
This example uses SPI peripheral to communicate with SD card.
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include
#include
#include
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#define EXAMPLE_MAX_CHAR_SIZE 64
static const char *TAG = "example";
#define MOUNT_POINT "/sdcard"
// Pin assignments can be set in menuconfig, see "SD SPI Example Configuration" menu.
// You can also change the pin assignments here by changing the following 4 lines.
#define PIN_NUM_MISO CONFIG_EXAMPLE_PIN_MISO
#define PIN_NUM_MOSI CONFIG_EXAMPLE_PIN_MOSI
#define PIN_NUM_CLK CONFIG_EXAMPLE_PIN_CLK
#define PIN_NUM_CS CONFIG_EXAMPLE_PIN_CS
static esp_err_t s_example_write_file(const char *path, char *data)
{
ESP_LOGI(TAG, "Opening file %s", path);
FILE *f = fopen(path, "w");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return ESP_FAIL;
}
fprintf(f, data);
fclose(f);
ESP_LOGI(TAG, "File written");
return ESP_OK;
}
static esp_err_t s_example_read_file(const char *path)
{
ESP_LOGI(TAG, "Reading file %s", path);
FILE *f = fopen(path, "r");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return ESP_FAIL;
}
char line[EXAMPLE_MAX_CHAR_SIZE];
fgets(line, sizeof(line), f);
fclose(f);
// strip newline
char *pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
return ESP_OK;
}
void app_main(void)
{
esp_err_t ret;
// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
.format_if_mount_failed = true,
#else
.format_if_mount_failed = false,
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
sdmmc_card_t *card;
const char mount_point[] = MOUNT_POINT;
ESP_LOGI(TAG, "Initializing SD card");
// Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
// Please check its source code and implement error recovery when developing
// production applications.
ESP_LOGI(TAG, "Using SPI peripheral");
// By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
// For setting a specific frequency, use host.max_freq_khz (range 400kHz - 20MHz for SDSPI)
// Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
spi_bus_config_t bus_cfg = {
.mosi_io_num = PIN_NUM_MOSI,
.miso_io_num = PIN_NUM_MISO,
.sclk_io_num = PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize bus.");
return;
}
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = PIN_NUM_CS;
slot_config.host_id = host.slot;
ESP_LOGI(TAG, "Mounting filesystem");
ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
} 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;
}
ESP_LOGI(TAG, "Filesystem mounted");
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);
// Use POSIX and C standard library functions to work with files.
// First create a file.
const char *file_hello = MOUNT_POINT"/hello.txt";
char data[EXAMPLE_MAX_CHAR_SIZE];
snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Hello", card->cid.name);
ret = s_example_write_file(file_hello, data);
if (ret != ESP_OK) {
return;
}
const char *file_foo = MOUNT_POINT"/foo.txt";
// Check if destination file exists before renaming
struct stat st;
if (stat(file_foo, &st) == 0) {
// Delete it if it exists
unlink(file_foo);
}
// Rename original file
ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo);
if (rename(file_hello, file_foo) != 0) {
ESP_LOGE(TAG, "Rename failed");
return;
}
ret = s_example_read_file(file_foo);
if (ret != ESP_OK) {
return;
}
// Format FATFS
ret = esp_vfs_fat_sdcard_format(mount_point, card);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to format FATFS (%s)", esp_err_to_name(ret));
return;
}
if (stat(file_foo, &st) == 0) {
ESP_LOGI(TAG, "file still exists");
return;
} else {
ESP_LOGI(TAG, "file doesnt exist, format done");
}
const char *file_nihao = MOUNT_POINT"/nihao.txt";
memset(data, 0, EXAMPLE_MAX_CHAR_SIZE);
snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Nihao", card->cid.name);
ret = s_example_write_file(file_nihao, data);
if (ret != ESP_OK) {
return;
}
//Open file for reading
ret = s_example_read_file(file_nihao);
if (ret != ESP_OK) {
return;
}
// All done, unmount partition and disable SPI peripheral
esp_vfs_fat_sdcard_unmount(mount_point, card);
ESP_LOGI(TAG, "Card unmounted");
//deinitialize the bus after all devices are removed
spi_bus_free(host.slot);
}
這段代碼是使用SPI(串行外設(shè)接口)與SD卡進(jìn)行通信。它展示了如何掛載SD卡、寫入文件、讀取文件、重命名文件、格式化SD卡,最后卸載SD卡。
代碼首先包含了必要的頭文件,并定義了一些常量,如最大字符大小、SD卡的掛載點(diǎn)和SPI通信的引腳分配。
然后定義了兩個(gè)輔助函數(shù):s_example_write_file和s_example_read_file。s_example_write_file函數(shù)打開一個(gè)給定路徑的文件,寫入數(shù)據(jù),然后關(guān)閉文件。如果無(wú)法打開文件,它會(huì)記錄一個(gè)錯(cuò)誤并返回失敗狀態(tài)。s_example_read_file函數(shù)打開一個(gè)給定路徑的文件,從中讀取一行,然后關(guān)閉文件。如果無(wú)法打開文件,它會(huì)記錄一個(gè)錯(cuò)誤并返回失敗狀態(tài)。
app_main函數(shù)是程序的主入口點(diǎn)。它首先定義了掛載SD卡的配置。然后初始化SPI總線和SD卡插槽。如果初始化失敗,它會(huì)記錄一個(gè)錯(cuò)誤并返回。
接下來(lái),它試圖掛載SD卡。如果掛載失敗,它會(huì)記錄一個(gè)錯(cuò)誤并返回。如果掛載成功,它會(huì)記錄一個(gè)成功消息并打印SD卡的屬性。
程序然后在SD卡上寫入一個(gè)文件,檢查另一個(gè)文件是否存在,如果存在則刪除它,然后將第一個(gè)文件重命名為第二個(gè)文件。然后從第二個(gè)文件中讀取。
程序接著格式化SD卡,并檢查第二個(gè)文件是否仍然存在。如果存在,它會(huì)記錄一個(gè)消息并返回。如果不存在,它會(huì)記錄一個(gè)成功消息,寫入第三個(gè)文件,并從第三個(gè)文件中讀取。
最后,卸載SD卡并禁用SPI外設(shè)。
編譯:
燒寫到ESP32C3后運(yùn)行,控制臺(tái)輸出:
I (286) app_start: Starting scheduler on CPU0
I (291) main_task: Started on CPU0
I (291) main_task: Calling app_main()
I (291) example: Initializing SD card
I (301) example: Using SPI peripheral
I (301) example: Mounting filesystem
I (311) gpio: GPIO[1]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (321) sdspi_transaction: cmd=52, R1 response: command not supported
I (361) sdspi_transaction: cmd=5, R1 response: command not supported
I (391) example: Filesystem mounted
Name: CS064
Type: SDHC/SDXC
Speed: 20.00 MHz (limit: 20.00 MHz)
Size: 7382MB
CSD: ver=2, sector_size=512, capacity=15118336 read_bl_len=9
SSR: bus_width=1
I (401) example: Opening file /sdcard/hello.txt
I (411) example: File written
I (411) example: Renaming file /sdcard/hello.txt to /sdcard/foo.txt
I (411) example: Reading file /sdcard/foo.txt
I (421) example: Read from file: 'Hello CS064!'
I (421) vfs_fat_sdmmc: Formatting card, allocation unit size=16384
I (2911) example: file doesnt exist, format done
I (2911) example: Opening file /sdcard/nihao.txt
I (2921) example: File written
I (2921) example: Reading file /sdcard/nihao.txt
I (2921) example: Read from file: 'Nihao CS064!'
I (2921) gpio: GPIO[1]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (2931) example: Card unmounted
I (2931) gpio: GPIO[4]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (2941) gpio: GPIO[6]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (2951) gpio: GPIO[5]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (2961) main_task: Returned from app_main()
可以看到輸出了存儲(chǔ)卡信息:
Name: CS064
Type: SDHC/SDXC
Speed: 20.00 MHz (limit: 20.00 MHz)
Size: 7382MB
CSD: ver=2, sector_size=512, capacity=15118336 read_bl_len=9
SSR: bus_width=1
后面還輸出了讀寫文件相應(yīng)的信息。
-
FlaSh
+關(guān)注
關(guān)注
10文章
1701瀏覽量
153926 -
SPI
+關(guān)注
關(guān)注
17文章
1836瀏覽量
98682 -
存儲(chǔ)芯片
+關(guān)注
關(guān)注
11文章
969瀏覽量
44569 -
ESP32
+關(guān)注
關(guān)注
21文章
1044瀏覽量
20316
發(fā)布評(píng)論請(qǐng)先 登錄
基于XIAO ESP32C3的智能家居四路控制器設(shè)計(jì)

基于ESP32C3的智能小車設(shè)計(jì)

esp32c3項(xiàng)目采用wss_server例程,把wifi斷開的話esp32c3會(huì)重啟,為什么?
idf.py set-target esp32c3無(wú)法生效怎么解決?
采用esp-hosted的spi連接的方式連接esp32c3與linux主機(jī),esp32c3收到的包的數(shù)據(jù)是錯(cuò)的,如何避免?
windowns環(huán)境下esp32c3如何解除flash加密?
esp32c3怎樣保護(hù)flash中的代碼不被拷貝?
如何使用ESP32C3驅(qū)動(dòng)SPI NAND flash
windowns環(huán)境下esp32c3如何解除flash加密?
使用ESP32C3,用ESP-IDF編譯bt_hid_mouse_device例程失敗報(bào)錯(cuò)如何解決?
esp32c3怎樣保護(hù)flash中的代碼不被拷貝?
【開源資料】使用ESP32C3超簡(jiǎn)單制作迷你四足機(jī)器人
深入剖析esp32c3的系統(tǒng)底層啟動(dòng)

基于nanoESP32-C3開發(fā)板用ESP32-c3下試跑Zephyr
【DFRobot Beetle ESP32-C3開發(fā)板試用體驗(yàn)】刷寫micropython固件

評(píng)論