esp-idf4.4 esp32s3 usb_cdc和u盘使用

本文章前提是已经搭建好esp-idf4.4的环境

1.    在esp-idf或者电脑任意目录克隆esp-iot-solution,git clone -b usb/add_usb_solutions --recursive https://github.com/espressif/esp-iot-solution ,克隆的过程中可能会失败,大多是因为esp-iot-solution目录下的lvgl失败,不过不影响,我们只需要确保esp-iot-solution/components/usb/tinyusb完整就可以。

2.由于要测试U盘,所以文件系统少不了,直接选用esp-idf/examples/storage/sd_card/sdmmc的demo

3.设置demo顶层目录的的CMakeList.txt,将tinyusb添加至项目中,内容如下:由于我是把iot克隆到esp-idf目录下,所以路径为 {IDF_PATH}/esp-iot-solution/components/usb/tinyus

# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS {IDF_PATH}/esp-iot-solution/components/usb/tinyusb)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(sd_card)

4.配置工程,打开usb msc和cdc功能,如下:

esp-idf4.4 esp32s3 usb_cdc和u盘使用_第1张图片

 

 esp-idf4.4 esp32s3 usb_cdc和u盘使用_第2张图片

 

 5.程序修改如下:

/* SD card and FAT filesystem example.
   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.
*/

// This example uses SDMMC peripheral to communicate with SD card.

#include 
#include 
#include 
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include "tusb_msc.h"
#include "tusb_cdc_acm.h"

static const char *TAG = "example";


#define MOUNT_POINT "/sdcard"
static bool usb_install = false;
static bool usb_cdc = false;
static uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1];
static void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event)
{
    /* initialization */
    size_t rx_size = 0;

    printf("%s need = %d\n", __func__, CONFIG_TINYUSB_CDC_RX_BUFSIZE);
    /* read */
    esp_err_t ret = tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size);
    if (ret == ESP_OK) {

        printf("rx_buf[%s]\n", buf);

    } else {
        ESP_LOGE(TAG, "Read error");
    }

}

void usb_cdc_init(void)
{
	if(usb_install == false)
	{
		tinyusb_config_t tusb_cfg = {
			.descriptor = NULL,
			.string_descriptor = NULL,
			.external_phy = false // In the most cases you need to use a `false` value
		};
		ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
		usb_install = true;
	}


    tinyusb_config_cdcacm_t amc_cfg = { 
        .usb_dev = TINYUSB_USBDEV_0,
        .cdc_port = TINYUSB_CDC_ACM_0,
        .rx_unread_buf_sz = 4096,
        .callback_rx = &tinyusb_cdc_rx_callback, // the first way to register a callback
        .callback_rx_wanted_char = NULL,
        .callback_line_state_changed = NULL,
        .callback_line_coding_changed = NULL
    }; // the configuration uses default values
    ESP_ERROR_CHECK(tusb_cdc_acm_init(&amc_cfg));
	usb_cdc = true;
    ESP_LOGI(TAG, "USB initialization cdc device DONE");
}

void usb_msc_init(void)
{
	if(usb_install == false)
	{
		tinyusb_config_t tusb_cfg = {
			.descriptor = NULL,
			.string_descriptor = NULL,
			.external_phy = false // In the most cases you need to use a `false` value
		};
		ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
		usb_install = true;
	}
    tinyusb_config_msc_t msc_cfg = {
        .pdrv = 0,
    };
    ESP_ERROR_CHECK(tusb_msc_init(&msc_cfg));
    ESP_LOGI(TAG, "USB initialization msc device DONE");

}
void cdc_printf(const char* fmt,...) 
{
	if(usb_cdc == true)
	{
		uint8_t buffer[256] = {0};
		va_list ap;
		va_start(ap,fmt);          			//ap指向fmt的地址
		vsprintf((char *)buffer,fmt,ap);	//vsprintf返回数组的长度
		va_end(ap);
		
		tinyusb_cdcacm_write_queue(0,buffer,strlen((const char *)buffer));
		tud_cdc_n_write_flush(0);
//	tinyusb_cdcacm_write_flush(0, 0);
	}
}

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 SDMMC peripheral");
    sdmmc_host_t host = SDMMC_HOST_DEFAULT();
    // 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.
    sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();

    // To use 1-line SD mode, change this to 1:
    slot_config.width = 4;
    // On chips where the GPIOs used for SD card can be configured, set them in
    // the slot_config structure:
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
    slot_config.clk = GPIO_NUM_14;
    slot_config.cmd = GPIO_NUM_11;
    slot_config.d0 = GPIO_NUM_4;
    slot_config.d1 = GPIO_NUM_45;
    slot_config.d2 = GPIO_NUM_48;
    slot_config.d3 = GPIO_NUM_13;
#endif

    // Enable internal pullups on enabled pins. The internal pullups
    // are insufficient however, please make sure 10k external pullups are
    // connected on the bus. This is for debug / example purpose only.
    slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;

    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdmmc_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 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";

    ESP_LOGI(TAG, "Opening file %s", file_hello);
    FILE *f = fopen(file_hello, "w");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return;
    }
    fprintf(f, "Hello %s!\n", card->cid.name);
    fclose(f);
    ESP_LOGI(TAG, "File written");

    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;
    }

    // Open renamed file for reading
    ESP_LOGI(TAG, "Reading file %s", file_foo);
    f = fopen(file_foo, "r");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return;
    }

    // Read a line from file
    char line[64];
    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);
    usb_cdc_init();
    usb_msc_init();
    while(1)
    {
        cdc_printf("test\r\n") ;
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    // All done, unmount partition and disable SDMMC peripheral
    // esp_vfs_fat_sdcard_unmount(mount_point, card);
    ESP_LOGI(TAG, "Card unmounted");
}

6.运行结果如下:

电脑首先会弹出一个u盘和虚拟串口,U盘的图就不截了,大家可以测试一下;打开串口助手,选usb虚拟的端口运行如下:

esp-idf4.4 esp32s3 usb_cdc和u盘使用_第3张图片

 usb发送数据测试:

esp-idf4.4 esp32s3 usb_cdc和u盘使用_第4张图片

 esp端接收串口打印如下:

esp-idf4.4 esp32s3 usb_cdc和u盘使用_第5张图片

 

你可能感兴趣的:(esp32,单片机)