IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【正点原子STM32连载】第五十九章 USB U盘(Host)实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1 -> 正文阅读

[嵌入式]【正点原子STM32连载】第五十九章 USB U盘(Host)实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

1)实验平台:正点原子MiniPro H750开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-336836-1-1.html
4)对正点原子STM32感兴趣的同学可以加群讨论:879133275

第五十九章 USB U盘(Host)实验

本章我们介绍STM32H750的USB HOST应用,即通过USB HOST功能,实现读写U盘/读卡器等大容量USB存储设备。
本章分为如下几个小节:
59.1 U盘简介
59.2 硬件设计
59.3 程序设计
59.4 下载验证

59.1 U盘简介

U盘,全称USB闪存盘,英文名“USB flash disk”。它是一种使用USB接口的无需物理驱动器的微型高容量移动存储产品,通过USB接口与主机连接,实现即插即用,是最常用的移动存储设备之一。
STM32H750的USB OTG FS支持U盘,并且ST官方提供了USB HOST大容量存储设备(MSC)例程,ST官方例程路径:光盘8,STM32参考资料1,STM32CubeH7固件包 STM32Cube_FW_H7_V1.6.0 ProjectsSTM32H743I-EVAL Applications USB_Host
MSC_Standalone。本实验,我们就要移植该例程到开发板上,以通过STM32H750的USB HOST接口,读写U盘或SD卡读卡器等设备。
59.2 硬件设计

  1. 例程功能
    本实验代码,开机后,检测字库,然后初始化USB HOST,并不断轮询。当检测并识别U盘后,在LCD上面显示U盘总容量和剩余容量,此时便可以通过USMART调用FATFS相关函数,来测试U盘数据的读写了,方法同FATFS实验一模一样。
    LED0闪烁,提示程序运行。
  2. 硬件资源
    1)RGB灯
    RED :LED0 - PB4
    GREEN :LED1 - PE6
    2)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面)
    3)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
    4)USB_HOST接口(D-/D+连接在PA11/PA12上)
  3. 原理图
    本开发板的USB HOST接口采用的是贴片USB母座,它和USB SLAVE的5PIN MiniUSB接头是共用USB_DM和USB_DP信号的,所以USB HOST和USB SLAVE功能不能同时使用。USB HOST和STM32的连接原理图,如下图所示:
    在这里插入图片描述

图59.2.1 USB母座与STM32的连接电路图
从上图可以看出,USB座是直接连接到STM32H750上面的,所以硬件上不需要我们做什么操作,可直接使用。
需要注意的是:这个USB母座(USB_HOST)和MiniUSB座是共用D+和D-的,所以他们不能同时使用。这个在使用的时候,要特别注意!本实验测试时,数据线要用USB_ UART接口连接到电脑!
下面,看看开发板上的USB母座(USB_HOST)的位置,请将U盘插入这个接口上。
在这里插入图片描述

图59.2.2 U盘与开发板的连接示意图
59.3 程序设计
59.3.1 程序流程图
在这里插入图片描述

图59.3.1.1 USB U盘(Host)实验程序流程图
59.3.2 程序解析
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。
本实验,我们在:实验37 硬件JPEG解码实验的基础上修改,代码移植自ST官方例程:STM32Cube_FW_H7_V1.6.0\Projects\STM32H743I_EVAL\Applications\USB_Host\MSC_Standalone。有了这个官方例程做指引,我们就知道具体需要哪些文件,从而实现本实验。
本实验的具体移植步骤,我们这里就不一一介绍了,最终移植好之后的工程分组截图,如图59.3.2.1所示:
在这里插入图片描述

图59.3.2.1 USB U盘(Host)实验工程分组
上图工程分组中的Middlewares/USB_CORE和Middlewares/USB_CLASS分组下的.c文件,直接拷贝ST官方USB HOST库,我们重点要修改的是USB_APP文件夹下面的代码,接下来重点介绍下。

  1. USB驱动代码
    usbh_conf.c提供了USB主机库的回调及MSP初始化函数,当USB状态机处理完不同事务的时候,会调用这些回调函数,我们通过这些回调函数,就可以知道USB当前状态,比如:是否连接上了?是否断开了?等,根据这些状态,用户应用程序可以执行不同操作,完成特定功能。该.c文件我们重点介绍3个函数,首先是初始化PCD MSP函数,其定义如下:
/**
 * @brief       初始化PCD MSP
 * @param       hpcd:PCD结构体指针
 * @retval      无
 */
void HAL_PCD_MspInit(PCD_HandleTypeDef * hpcd)
{
    GPIO_InitTypeDef gpio_init_struct;
    /* USB时钟设置,使用HSI48MHz,具体配置请看sys_stm32_clock_init函数 */

    if (hpcd->Instance == USB2_OTG_FS)
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();                           	/* 使能GPIOA时钟 */

        gpio_init_struct.Pin = GPIO_PIN_11 | GPIO_PIN_12; 
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;              /* 复用 */
        gpio_init_struct.Pull = GPIO_NOPULL;                  	/* 浮空 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;	/* 高速 */
        gpio_init_struct.Alternate = GPIO_AF10_OTG1_FS;     	/* 复用为OTG1_FS */
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);/* 初始化PA11和PA12引脚 */

        __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();      /* 使能OTG FS时钟 */
        HAL_NVIC_SetPriority(OTG_FS_IRQn, 1, 0);/* 优先级设置为抢占1,子优先级0 */
        HAL_NVIC_EnableIRQ(OTG_FS_IRQn);         	/* 使能OTG FS中断 */
    }
    else if (hpcd->Instance == USB1_OTG_HS)
    {
        /* USB1 OTG本例程没用到,故不做处理 */
    }
}
HAL_HCD_MspInit函数,用于使能USB时钟,选择内核时钟源,初始化IO口,设置中断等。该函数在HAL_HCD_Init函数里面被调用。

接下来介绍的是USB OTG 中断服务函数,其定义如下:

/**
 * @brief       USB OTG 中断服务函数
 *   @note      处理所有USB中断
 * @param       无
 * @retval      无
 */
void OTG_FS_IRQHandler(void)
{
    HAL_HCD_IRQHandler(&hhcd);
}
	OTG_FS_IRQHandler函数,是USB的中断服务函数,通过调用HAL_HCD_IRQHandler函数,实现对USB各种事务的处理。
最后介绍的是USBH底层初始化函数,其定义如下:
/**
 * @brief       USBH 底层初始化函数
 * @param       phost       : USBH句柄指针
 * @retval      USB状态
 *   @arg       USBH_OK(0)   , 正常;
 *   @arg       USBH_BUSY(1) , 忙;
 *   @arg       其他         , 失败;
 */
USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost)
{
#ifdef USE_USB_FS
    /* 设置LL驱动相关参数 */
    hhcd.Instance = USB2_OTG_FS;             		/* 使用USB2 OTG */
    hhcd.Init.Host_channels = 11;            		/* 主机通道数为11个 */
    hhcd.Init.dma_enable = 0;                		/* 不使用DMA */
    hhcd.Init.low_power_enable = 0;         		/* 不使能低功耗模式 */
    hhcd.Init.phy_itface = HCD_PHY_EMBEDDED;	/* 使用内部PHY */
    hhcd.Init.Sof_enable = 0;                 		/* 禁止SOF中断 */
    hhcd.Init.speed = HCD_SPEED_FULL;       		/* USB全速(12Mbps) */
    hhcd.Init.vbus_sensing_enable = 0;      		/* 不使能VBUS检测 */
    hhcd.Init.lpm_enable = 0;                		/* 使能连接电源管理 */

    hhcd.pData = phost;                        		/* hhcd的pData指向phost */
    phost->pData = &hhcd;                      		/* phost的pData指向hhcd */

    HAL_HCD_Init(&hhcd);                       		/* 初始化LL驱动 */
#endif

#ifdef USE_USB_HS
    /* 未实现 */
#endif
    USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&hhcd));
    return USBH_OK;
}
USBH_LL_Init函数,用于初始化USB底层设置,因为我们定义的是:USE_USB_FS,因此会设置USB OTG使用USB2_OTG_FS,然后完成各种设置,比如,使用内部PHY,使用全速模式,不使能VBUS检测等,详见以上代码。该函数在USBH_Init函数里面被调用。  

usbh_diskio.c提供U盘和FATFS文件系统之间的输入/输出接口函数,这里总共有5个函数,首先介绍的是初始化USBH函数,其定义如下:

/**
 * @brief       初始化 USBH
 * @param       无
 * @retval      无
 */
DSTATUS USBH_initialize(void)
{
    return RES_OK;
}
USBH_initialize函数,用于初始化U盘,我们不需要做任何事情,直接返回OK即可。
下面介绍的是获取U盘状态函数,其定义如下:
/**
 * @brief       获取U盘状态
 * @param       无
 * @retval      无
 */
DSTATUS USBH_status(void)
{
    DRESULT res=RES_ERROR;
    MSC_HandleTypeDef *MSC_Handle=hUSBHost.pActiveClass->pData;
    if(USBH_MSC_UnitIsReady(&hUSBHost,MSC_Handle->current_lun))
    {
        printf("U盘状态查询成功\r\n");
        res=RES_OK;
    }else
    {
        printf("U盘状态查询失败\r\n");
        res=RES_ERROR;
    }
    return res;
}
USBH_status函数,用于获取U盘状态,本实验暂时用不到。
下面介绍的是U盘读扇区操作函数,其定义如下:
/**
 * @brief       U盘读扇区操作
 * @param       buff   : 数据缓冲首地址
 * @param       sector : 扇区地址
 * @param       count  : 需要读取的扇区数
 * @retval      执行结果(详见DRESULT定义)
 */
DRESULT USBH_read(BYTE *buff, DWORD sector, UINT count)
{
    DRESULT res = RES_ERROR;
    MSC_LUNTypeDef info;
    MSC_HandleTypeDef *MSC_Handle=hUSBHost.pActiveClass->pData;
    
    if(USBH_MSC_Read(&hUSBHost,MSC_Handle->current_lun,sector,buff,count)
==USBH_OK)
    {
        res = RES_OK;
    }else
    {
        printf("U盘读取失败\r\n");
        USBH_MSC_GetLUNInfo(&hUSBHost,MSC_Handle->current_lun, &info);
        switch (info.sense.asc)
        {
            case SCSI_ASC_LOGICAL_UNIT_NOT_READY:
            case SCSI_ASC_MEDIUM_NOT_PRESENT:
            case SCSI_ASC_NOT_READY_TO_READY_CHANGE:
                USBH_ErrLog("USB Disk is not ready!");
                res = RES_NOTRDY;
                break;
            default:
                res = RES_ERROR;
                break;
        }
    }
    return res;
}

USBH_read函数,用于从U盘指定位置,读取指定长度的数据。
下面介绍的是U盘写扇区操作函数,其定义如下:

/**
 * @brief       U盘写扇区操作
 * @param       buff   : 数据缓冲首地址
 * @param       sector : 扇区地址
 * @param       count  : 需要写入的扇区数
 * @retval      执行结果(详见DRESULT定义)
 */
DRESULT USBH_write(const BYTE *buff,DWORD sector,UINT count)
{
    DRESULT res = RES_ERROR;
    MSC_LUNTypeDef info;
    MSC_HandleTypeDef *MSC_Handle=hUSBHost.pActiveClass->pData;
if(USBH_MSC_Write(&hUSBHost,MSC_Handle->current_lun,sector,
(BYTE *)buff,count) == USBH_OK)
    {
        res=RES_OK;
    }else
    {
        printf("U盘写入失败\r\n");
        USBH_MSC_GetLUNInfo(&hUSBHost,MSC_Handle->current_lun, &info);
        switch (info.sense.asc)
        {
            case SCSI_ASC_WRITE_PROTECTED:
                USBH_ErrLog("USB Disk is Write protected!");
                res = RES_WRPRT;
                break;
            case SCSI_ASC_LOGICAL_UNIT_NOT_READY:
            case SCSI_ASC_MEDIUM_NOT_PRESENT:
            case SCSI_ASC_NOT_READY_TO_READY_CHANGE:
                USBH_ErrLog("USB Disk is not ready!");
                res = RES_NOTRDY;
                break;
            default:
                res = RES_ERROR;
                break;
        }
    }
    return res;
}

USBH_write函数,用于往U盘指定位置,写入指定长度的数据。
最后介绍的是U盘IO控制操作函数,其定义如下:

/**
 * @brief       U盘IO控制操作
 * @param       cmd    : 控制命令
 * @param       buff   : 控制数据
 * @retval      执行结果(详见DRESULT定义)
 */
DRESULT USBH_ioctl(BYTE cmd,void *buff)
{
    DRESULT res = RES_ERROR;
    MSC_LUNTypeDef info;
    MSC_HandleTypeDef *MSC_Handle=hUSBHost.pActiveClass->pData;
    switch(cmd)
    {
        case CTRL_SYNC:
            res=RES_OK;
            break;
        case GET_SECTOR_COUNT : /* 获取扇区数量 */
            if(USBH_MSC_GetLUNInfo(&hUSBHost,MSC_Handle->current_lun, 
&info)==USBH_OK)
            {
                *(DWORD*)buff=info.capacity.block_nbr;
                res = RES_OK;
                printf("扇区数量:%d\r\n",info.capacity.block_nbr);
            }else
            {
                res = RES_ERROR;
            }
            break;
        case GET_SECTOR_SIZE :/* 获取扇区大小 */
            if(USBH_MSC_GetLUNInfo(&hUSBHost,MSC_Handle->current_lun,&info) 
== USBH_OK)
            {
                *(DWORD*)buff=info.capacity.block_size;
                res = RES_OK;
                printf("扇区大小:%d\r\n",info.capacity.block_size);
            }else
            {
                res = RES_ERROR;
            }
            break;
        case GET_BLOCK_SIZE :   /* 获取一个扇区里面擦除块的大小 */
            if(USBH_MSC_GetLUNInfo(&hUSBHost,MSC_Handle->current_lun,&info)
==USBH_OK)
            {
                *(DWORD*)buff=info.capacity.block_size/USB_DEFAULT_BLOCK_SIZE;
                printf("每个扇区擦除块:%d\r\n", 
info.capacity.block_size/USB_DEFAULT_BLOCK_SIZE);
                res = RES_OK;
            }else
            {
                res = RES_ERROR;
            }
            break;
        default:
                res = RES_PARERR;
    }
    return res;
}

USBH_ioctl函数,可以用于获取U盘扇区数量、扇区大小和块大小等信息。
我们将这5个函数在diskio.c里面和FATFS完成对接,同时需要设置FATFS支持3个磁盘(SD卡、SPI FLASH和U盘),需要在ffconf.h文件里面将FF_VOLUMES的宏定义值改成3,以支持FATFS操作U盘。
2. main.c代码
下面是main.c的程序,具体如下:

USBH_HandleTypeDef hUSBHost;    /* USB Host处理结构体 */

static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id)
{
    uint32_t total, free;
    uint8_t res = 0;
    printf("id:%d\r\n", id);

    switch (id)
    {
        case HOST_USER_SELECT_CONFIGURATION:
            break;

        case HOST_USER_DISCONNECTION:
            f_mount(0, "2:", 1);        /* 卸载U盘 */
            text_show_string(30, 140, 200, 16, "设备连接中...", 16, 0, RED);
            lcd_fill(30, 160, 239, 220, WHITE);
            break;

        case HOST_USER_CLASS_ACTIVE:
            text_show_string(30, 140, 200, 16, "设备连接成功!", 16, 0, RED);
            f_mount(fs[2], "2:", 1);    /* 重新挂载U盘 */
            res = exfuns_get_free("2:", &total, &free);
            if (res == 0)
            {
                lcd_show_string(30, 160, 200, 16, 16, "FATFS OK!", BLUE);
                lcd_show_string(30, 180, 200, 16, 16, "U Disk Total Size:     MB", 
BLUE);
                lcd_show_string(30, 200, 200, 16, 16, "U Disk  Free Size:     MB", 
BLUE);
/* 显示U盘总容量 MB */
                lcd_show_num(174, 180, total >> 10, 5, 16, BLUE);
                lcd_show_num(174, 200, free >> 10, 5, 16, BLUE);
            }
            else
            {
                printf("U盘存储空间获取失败\r\n");
            }
            break;

        case HOST_USER_CONNECTION:
            break;

        default:
            break;
    }
}
int main(void)
{
    uint8_t t = 0;
    sys_cache_enable();                   	/* 打开L1-Cache */
    HAL_Init();                             	/* 初始化HAL库 */
    sys_stm32_clock_init(240, 2, 2, 4);	/* 设置时钟, 480Mhz */
    delay_init(480);                       	/* 延时初始化 */
    usart_init(115200);                   	/* 串口初始化为115200 */
    mpu_memory_protection();             	/* 保护相关存储区域 */
    led_init();                             	/* 初始化LED */
    lcd_init();                             	/* 初始化LCD */
    key_init();                             	/* 初始化按键 */
    my_mem_init(SRAMIN);                  	/* 初始化内部内存池(AXI) */
    my_mem_init(SRAM12);                  	/* 初始化SRAM12内存池(SRAM1+SRAM2) */
    my_mem_init(SRAM4);                   	/* 初始化SRAM4内存池(SRAM4) */
    my_mem_init(SRAMDTCM);               	/* 初始化DTCM内存池(DTCM) */
    my_mem_init(SRAMITCM);               	/* 初始化ITCM内存池(ITCM) */
    exfuns_init();                        	/* 为fatfs相关变量申请内存 */
    f_mount(fs[0], "0:", 1);            	/* 挂载SD卡 */
    f_mount(fs[1], "1:", 1);            	/* 挂载FLASH */
    piclib_init();                        	/* 初始化画图 */
    while (fonts_init())                 	/* 检查字库 */
    {
        lcd_show_string(30, 50, 200, 16, 16, "Font Error!", RED);
        delay_ms(200);
        lcd_fill(30, 50, 240, 66, WHITE);   /* 清除显示 */
        delay_ms(200);
    }
    text_show_string(30, 50, 200, 16, "STM32", 16, 0, RED);
    text_show_string(30, 70, 200, 16, "USB U盘 实验", 16, 0, RED);
    text_show_string(30, 90, 200, 16, "正点原子@ALIENTEK", 16, 0, RED);
    text_show_string(30, 120, 200, 16, "设备连接中...", 16, 0, RED);
    USBH_Init(&hUSBHost, USBH_UserProcess, 0);
    USBH_RegisterClass(&hUSBHost, USBH_MSC_CLASS);
    USBH_Start(&hUSBHost);
    while (1)
    {
        USBH_Process(&hUSBHost);
        delay_ms(10);
        t++;
        if (t == 50)
        {
            t = 0;
            LED0_TOGGLE();
        }
    }
}

其中,USBH_HandleTypeDef是一个用于USB主机类通信处理的结构体类型,它包含了USB主机通信的各种变量、结构体参数、传输状态和管道信息等。凡是USB主机类通信,都必须要用定义一个这样的结构体,这里定义成:hUSBHost。
同USB Device类通信类似,USB Host的初始化过程如下:
1,调用USBH_Init函数,初始化USB主机内核;
2,调用USBH_RegisterClass函数,链接MSC主机类驱动程序到主机内核;
3,调用USBH_Start函数,启动USB通信;
经过以上三步处理,USB主机就启动了,所有USB事务,都是通过USB中断触发,并由USB驱动库自动处理。USB中断服务函数在usbh_conf.c里面:

/**
 * @brief       USB OTG 中断服务函数
 *   @note      处理所有USB中断
 * @param       无
 * @retval      无
 */
void OTG_FS_IRQHandler(void)
{
    HAL_HCD_IRQHandler(&hhcd);
}

该函数调用HAL_HCD_IRQHandler函数来处理各种USB中断请求。
整个main函数代码比较简单,不过我们在main函数里面,必须不停的调用:USBH_Process函数,该函数用于实现USB主机通信的核心状态机处理,该函数必须在主函数里面被循环调用,而且调用频率得比较快才行(越快越好),以便及时处理各种事务。
USBH_UserProcess函数是USB主机用户处理回调函数,参数id表示USB主机当前的一些状态,总共有6种状态:

#define HOST_USER_SELECT_CONFIGURATION   0x01U  	/* USB进入配置状态 */
#define HOST_USER_CLASS_ACTIVE             0x02U  	/* USB初始化配置完成 */
#define HOST_USER_CLASS_SELECTED          0x03U  	/* USB选择了一个类 */
#define HOST_USER_CONNECTION               0x04U  	/* USB连接成功 */
#define HOST_USER_DISCONNECTION           0x05U  	/* USB连接断开 */
#define HOST_USER_UNRECOVERED_ERROR      0x06U  	/* USB发生了不可恢复错误 */

本例程我们只用了:HOST_USER_DISCONNECTION和HOST_USER_CLASS_ACTIVE两个状态。程序运行后,如果没有U盘插入,则不会执行到USBH_UserProcess函数,当插入U盘,并成功识别之后,USBH_UserProcess函数会进入:HOST_USER_CLASS_ACTIVE状态,我们就可以挂载U盘,并显示容量等信息,表示U盘识别完成。此时,如果我们把U盘拔出,则会进入:HOST_USER_DISCONNECTION状态,表示U盘拔出,我们取消U盘的挂载,并显示设备连接中…(表示当前正在连接设备)。
最后,我们需要将FATFS相关测试函数(mf_open/ mf_close等函数),加入USMART管理,这里和FATFS实验一模一样,可以参考该实验的方法操作。
59.4 下载验证
将程序下载到开发板后,然后在USB_HOST端子插入U盘/读卡器(带卡),注意:此时USB SLAVE口不要插USB线到电脑,否则会干扰!
等U盘成功识别后,便可以看到LCD显示U盘容量等信息,如图59.4.1所示:
在这里插入图片描述

图59.4.1 U盘识别成功
此时,我们便可以通过USMART来测试U盘读写了,如图59.4.2和图59.4.3所示:
在这里插入图片描述

图59.4.2 测试读取U盘读取
在这里插入图片描述

图59.4.3 测试U盘写入
图59.4.2分别是通过发送:mf_scan_files(“2:”)和mf_scan_files(“2:/PICTURE”),扫描U盘根目录所有文件和PICTURE目录下的所有文件,然后通过piclib_ai_load_picfile(“2:/PICTURE/示例图片.jpg”,0,0,480,800,1),解码图片,并显示在LCD上面。说明读U盘是没问题的。
图59.4.3通过发送:mf_open(“2:test u disk.txt”,7),在U盘根目录创建test u disk.txt这个文件,然后发送:mf_write(“这是一个测试,写入文件”,22),写入“这是一个测试,写入文件”到这个文件里面,然后发送:mf_close(),关闭文件,完成一次文件创建。最后,发送:mf_scan_files(“2:”),扫描U盘根目录文件,发现比图59.4.3所示多出了一个test u disk.txt的文件,说明U盘写入成功。
这样,就完成了本实验的设计目的:实现U盘的读写操作。最后,大家还可以调用其他函数,实现相关功能测试,这里就不给大家一一演示了。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:14:20  更:2022-10-31 12:15:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 2:34:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计