基于STM32CubeMX的HAL库的USB接口使用(MSC基于SD卡模拟U盘)

描述

一、USB简介
    USB(Universal Serial BUS)通用串行总线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在PC领域的接口技术。USB接口支持设备的即插即用和热插拔功能。USB是在1994年底由英特尔、康柏、IBM、Microsoft 等多家公司联合提出的。

USB 发展到现在已经有USB1.0/1.1/2.0/3.0等多个版本。目前用的最多的就是USB1.1,USB2.0和USB3.0 目前已经开始普及。

STM32F103 自带的USB符合USB2.0规范,不过STM32F103的USB 都只能用来做设备,而不能用作主机。

标准USB共四根线组成,除VCC/GND外,另外为D+,D-,这两根数据线采用的是差分电压的方式进行数据传输的。在USB主机上,D-和D+都是接了15K的电阻到GND的,所以在没有设备接入的时候,D+和D-均是低电平。而在USB设备中,如果是高速设备,则会在D+上接一个1.5K的电阻到 VCC,而如果是低速设备,则会在D-上接一个1.5K 的电阻到VCC。这样当设备接入主机的时候,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。

STM32F103的MCU自带USB 从控制器,符合USB规范的通信连接;PC主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被USB外设直接访问。这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用 512 字节缓冲区(专用的512字节,和CAN共用),最多可用于16个单向或8个双向端点。

USB模块同PC主机通信,根据USB规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。整个传输的格式由硬件完成,其中包括 CRC 的生成和校验。

1.1 USB MSC简介

USB大容量存储设备类是一种计算机和移动设备之间的传输协议,它允许一个通用串行总线(USB)设备来访问主机的计算设备,使两者之间进行文件传输。通过这个标准的计算机连接到的设备包括:移动硬盘、移动光驱、U盘、SD、TF等储存卡读卡器、数码相机、各种数字音频播放器和便携式媒体播放器、智能卡阅读器、掌上电脑和手机。

MSC的通用性和操作简单使他成为移动设备上最常见的文件系统,USB MSC并不需要任何特定的文件系统, 相反,它提供了一个简单的界面来读写接口用于访问任何硬盘驱动器。操作系统可以把MSC像本地硬盘一样格式化,并可以与他们喜欢的任何文件系统格式它,当然也可以创建多个分区。

1.2 SDIO简介

SD卡在我们生活中已经非常普遍了,控制器对SD卡进行读写通信操作一般有两种通信接口可选,一种是SPI接口,另外一种就是SDIO接口。SDIO 全称是安全数字输入/输出接口,多媒体卡(MMC)、SD 卡、SD I/O 卡都有SDIO接口。MMC卡可以说是SD卡的前身,现阶段已经用得很少。STM32F1系列控制器有一个SDIO主机接口,它可以与MMC卡、SD 卡、SD I/O卡以及CE-ATA设备进行数据传输。另外,STM32F1系列控制器的SDIO是不支持SPI通信模式的,如果需要用到SPI通信只能使用SPI外设。usb

1.3 SD卡简介

SD卡除了SD-Micro卡之外,还有两种分别是SD和mini-SD,他们分别长这样:

usb

SD卡的四个角有一个是没有的,以便我们认识正反来使用它,SD卡的一侧还有一个可以扳动的读写保护开关,这三种卡里面SD卡最大,SD-Micro最小。根据SD卡的容量,可划分为SDSC、SDHC、SDXC三种标准。现今,市场的主流SD产品是SDHC和SDXC这两种较大容量的存储卡,而SDSC卡因容量过小,已逐渐被市场淘汰。SD卡(三种卡的统称)的存储空间是由一个一个扇区组成的,SD卡的扇区大小是固定的,为512byte(这一点很重要) ,若干个扇区又可以组成一个分配单元(也被成为簇),分配单元常见的大小为4K、8K、16K、32K、64K。需要注意的是,SD-Micro只有8个引脚,而SD卡是有九个引脚的,这两种都可以直线4线通讯。

 

二、新建工程2.1打开软件,点击“新建工程”

usb2.2选择 MCU 和封装

usb

2.3配置时钟

RCC设置,选择HSE为 Crystal/Ceramic Resonator。

usb

配置系统时钟 SYSCLK为 72MHz,修改HCLK的值为72后,输入回车,软件会自动修改所有配置。

usb2.4配置调试模式

非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器,SYS 设置,选择 Debug 为 Serial Wire。

usb三、USB3.1 参数配置

在 Connectivity 中选择 USB 设置,并勾选 Device(FS) 激活 USB 设备。

usb

在 Parameter Settings 进行具体参数配置。

usb

Speed:Full Speed 12MBit/s(固定为全速)

Low Power:默认 Disabled(在任何不需要使用usb模块的时候,通过写控制寄存器可以使usb模块置于低功耗模式。在这种模式下,不产生任何静态电流消耗,同时usb时钟也会减慢或停止。通过对usb线上数据传输的检测,可以在低功耗模式下唤醒usb模块。也可以将一特定的中断输入源直接连接到唤醒引脚上,以使系统能立即恢复正常的时钟系统,并支持直接启动或停止时钟系统)

3.2 引脚配置

USB 的 DP 引脚必须上拉 1.5K 欧的电阻,电脑才能检测到 USB,否则检测不到。

usb

查看野火指南者开发板原理图可知,需要将 PD6 配置为低电平使能 USB。usb在右边图中找到 PD6 引脚,选择 GPIO_Output。usb

在GPIO output level 中选择 Low 输出低电平。

usb3.3 配置时钟

选择 Clock Configuration,USB 时钟配置为 48MHz,且来源最好是外部晶振分频得到。

usb3.4 USB Device

USB有主机(Host)和设备(Device)之分。一般电脑的USB接口为主机接口,而键盘、鼠标、U盘等则为设备。

部分型号的STM32芯片有1~2个USB接口。像STM32F103系列的有一个USB Device接口,STM32F407系列的有2个USB接口,既可以作为HOST,又可以作为Device,还可以作为OTG接口。

在 Middleware 中选择 USB_DEVICE 设置,在 Class For FS IP 设备类别选择 Mass Storage Class(HID) 大容量存储设备类。

usb

参数配置保持默认(或根据存储介质的最小存储单元修改缓冲区大小)。

usb

MSC_MEDIA_PACKET (Media I/O buffer Size)(读写缓冲区大小):512(默认为512,这个的大小对于USB读写速度会有一些影响,最好和存储介质的最小存储单元一致)

本实验板使用的SD卡(三种卡的统称)的存储空间是由一个一个扇区组成的,SD卡的扇区大小是固定的,为512byte(这一点很重要) ,若干个扇区又可以组成一个分配单元(也被成为簇),分配单元常见的大小为4K、8K、16K、32K、64K。

设备描述符保持默认。

usb

 

四、SDIO

STM32 控制器可以控制使用单线或 4 线传输,本开发板设计使用 4 线传输。

usb

 

4.1 参数配置

在 Connetivity 中选择 SDIO 设置,并选择 SD 4 bits Wide bus 四线SD模式

usb

此时 SDIO 对应的管脚也被选中。

usb

在 Parameter Settings 进行具体参数配置。

Clock transition on which the bit capture is made:Rising transition。主时钟 SDIOCLK 产生 CLK 引脚时钟有效沿选择,可选上升沿或下降沿,它设定 SDIO 时钟控制寄存器(SDIO_CLKCR)的 NEGEDGE 位的值,一般选择设置为上升沿。

SDIO Clock divider bypass:Disable。时钟分频旁路使用,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 BYPASS 位。如果使能旁路,SDIOCLK 直接驱动 CLK 线输出时钟;如果禁用,使用 SDIO_CLKCR 寄存器的 CLKDIV 位值分频 SDIOCLK,然后输出到 CLK 线。一般选择禁用时钟分频旁路。

SDIO Clock output enable when the bus is idle:Disable the power save for the clock。节能模式选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 PWRSAV 位的值。如果使能节能模式,CLK 线只有在总线激活时才有时钟输出;如果禁用节能模式,始终使能 CLK 线输出时钟。

SDIO hardware flow control:The hardware control flow is disabled。硬件流控制选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 HWFC_EN 位的值。硬件流控制功能可以避免 FIFO 发送上溢和下溢错误。

SDIOCLK clock divide factor:6。时钟分频系数,它设定 SDIO_CLKCR 寄存器的 CLKDIV 位的值,设置 SDIOCLK 与 CLK 线输出时钟分频系数:CLK 线时钟频率=SDIOCLK/([CLKDIV+2])。

SDIO_CK 引脚的时钟信号在卡识别模式时要求不超过 400KHz,而在识别后的数据传输模式时则希望有更高的速度(最大不超过 25MHz),所以会针对这两种模式配置 SDIOCLK 的时钟。

这里参数描述建议将SDIOCLK clock divede factor 参数使用默认值为0,SDIOCLK为72MHz,可以得到最大频率36MHz,但请注意,有些型号的SD卡可能不支持36MHz这么高的频率,所以还是要以实际情况而定。

 

4.2 配置DMASDIO 外设支持生成 DMA 请求,使用 DMA 传输可以提高数据传输效率,因此在 SDIO 的控制代码中,可以把它设置为 DMA 传输模式或轮询模式,ST 标准库提供 SDIO 示例中针对这两个模式做了区分处理。应用中一般都使用DMA 传输模式。点击 DMA Settings 添加 SDIO 对应 DMA2 的通道4。DMA模式选择循环模式,方向选为内存到外设。usb

Priority:当发生多个 DMA 通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器也管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,可以在 DMA_CCRx 寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通 道编号,编号越低优先权越高,比如通道 0 高于通道 1。在大容量产品和互联型产品中,DMA1 控制器拥有高于 DMA2 控制器的优先级。

Mode:Normal 表示单次传输,传输一次后终止传输。Circular 表示循环传输,传输完成后又重新开始继续传输,不断循环永不停止。

Increment Address:Peripheral 表示外设地址自增。Memory 表示内存地址自增。Data Width:Byte 一个字节。Half Word 半个字,等于两字节。Word 一个字,等于四字节。

 

4.3 配置NVIC

首先SD可以开启DMA读取或者单纯的SD的中断,但是其中优先级一定要为 SD > SD DMA Rx/Tx > USB,不然当SD卡在读写的时候被其他中断打断,会直接导致U盘掉盘,中途卡顿。

usb五、生成代码六、修改usbd_storage_if.c

打开工程文件夹usbd_storage_if.c文件

usb6.1 声明SD卡句柄

  •  
  •  
  •  

/* USER CODE BEGIN EXPORTED_VARIABLES */extern SD_HandleTypeDef hsd;/* USER CODE END EXPORTED_VARIABLES */

6.2 修改获取SD卡容量信息函数

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

/** * @brief . * @param lun: . * @param block_num: . * @param block_size: . * @retval USBD_OK if all operations are OK else USBD_FAIL */int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size){ /* USER CODE BEGIN 3 */ HAL_SD_CardInfoTypeDef info; if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) { HAL_SD_GetCardInfo(&hsd, &info); *block_num = info.LogBlockNbr; *block_size = info.LogBlockSize; return USBD_OK; } return USBD_FAIL; /* USER CODE END 3 */}

6.3 修改存储读写函数
 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len){ /* USER CODE BEGIN 6 */ int8_t ret = USBD_FAIL; if(HAL_SD_ReadBlocks(&hsd, buf, blk_addr, blk_len, HAL_MAX_DELAY) == HAL_OK) { ret = USBD_OK; while(HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY); while HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER); } return ret; /* USER CODE END 6 */}

/** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len){ /* USER CODE BEGIN 7 */ int8_t ret = USBD_FAIL; if(HAL_SD_WriteBlocks(&hsd, buf, blk_addr, blk_len, HAL_MAX_DELAY) == HAL_OK) { ret = USBD_OK; while(HAL_SD_GetState(&hsd) == HAL_SD_STATE_BUSY); while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER); } return ret; /* USER CODE END 7 */}
 

七、查看效果

编译工程,下载到板子上,插上USB线连接到电脑上,识别出为大容量存储设备。

usb

注意:如果设备带有感叹号,则参考下面八、注意事项。

usb

弹出格式化对话框,直接格式化就行,文件系统选择FAT模式。

usbusb

新建一个文档,名为测试.txt。然后在文档中输入一些内容。

usb

重新上电断开后再次打开U盘看里面的内容和已用空间。

usb八、注意事项
 

用户代码要加在 USER CODE BEGIN N 和 USER CODE END N 之间,否则下次使用 STM32CubeMX 重新生成代码后,会被删除。

usb如果USB端口出现感叹号设备无法启动的问题,可适当将堆改大,如0x400usbusb

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分