| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-07-28 | gingko | 初次建立 | \\ \\ \\ ===== STM32CubeMX教程三十三——USBD_MSC实验 ===== \\ 1.在主界面选择File-->New Project 或者直接点击ACCEE TO MCU SELECTOR {{ :icore4tx:icore4tx_cube_33_1.png?direct |}} 2.出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。 {{ :icore4tx:icore4tx_cube_33_2.png?direct |}} 3.配置RCC,使用外部时钟源 {{ :icore4tx:icore4tx_cube_33_3.png?direct |}} 4.时基源选择SysTick {{ :icore4tx:icore4tx_cube_33_4.png?direct |}} 5.将PA10,PB7,PB8设置为GPIO_Output {{ :icore4tx:icore4tx_cube_33_5.png?direct |}} 6.引脚模式配置 {{ :icore4tx:icore4tx_cube_33_6.png?direct |}} {{ :icore4tx:icore4tx_cube_33_7.png?direct |}} 7.配置USB_OTG_HS {{ :icore4tx:icore4tx_cube_33_8.png?direct |}} 8.配置USB_DEVICE {{ :icore4tx:icore4tx_cube_33_9.png?direct |}} 9.配置QUADAPI {{ :icore4tx:icore4tx_cube_33_10.png?direct |}} 引脚配置 {{ :icore4tx:icore4tx_cube_33_11.png?direct |}} 10.时钟源设置,选择外部高速时钟源,配置为最大主频 {{ :icore4tx:icore4tx_cube_33_12.png?direct |}} {{ :icore4tx:icore4tx_cube_33_13.png?direct |}} 11.工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK V5.27 {{ :icore4tx:icore4tx_cube_33_14.png?direct |}} 12.点击Code Generator,进行进一步配置 {{ :icore4tx:icore4tx_cube_33_15.png?direct |}} * **Copy all used libraries into the project folder** * 将HAL库的所有.C和.H都复制到所建工程中 * 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便 * 缺点:体积大,编译时间很长 * **Copy only the necessary library files** * 只复制所需要的.C和.H(推荐) * 优点:体积相对小,编译时间短,并且工程可复制拷贝 * 缺点:新增外设时需要重新用STM32CubeMX导入 * **Add necessary library files as reference in the toolchain project configuration file** * 不复制文件,直接从软件包存放位置导入.C和.H * 优点:体积小,比较节约硬盘空间 * 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径 * 自行选择方式即可 13.然后点击GENERATE CODE 创建工程 {{ :icore4tx:icore4tx_cube_33_16.png?direct |}} 创建成功,打开工程。 \\ \\ \\ ===== 实验三十三:USBD_MSC实验——虚拟U盘(SPI FLASH) ===== ==== 一、 实验目的与意义 ==== - 了解STM32 USB SLAVE结构。 - 了解STM32 USB SLAVE特征。 - 掌握USB SLAVE MSC的使用方法。 - 掌握STM32 HAL库中QUADSPI属性的配置方法。 - 掌握KEIL MDK 集成开发环境使用方法。 ==== 二、 实验设备及平台 ==== - iCore4TX 双核心板[[https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22598974120.3.29da532fLkazHH&id=614919247574|点击购买]]。 - JLINK(或相同功能)仿真器。 - Micro USB线缆。 - Keil MDK 开发平台。 - STM32CubeMX开发平台。 - 装有WIN XP(及更高版本)系统的计算机。 ==== 三、 实验原理 ==== === 1.SPI FLASH简介 === * 串行接口设备spi flash就是通过串行的接口进行操作的flash存储设备。flash按照内部存储结构不同,分为两种:nor flash和nand flash。这里spi flash 属于 nor flash。SPI一种通信接口。那么严格的来说SPI Flash是一种使用SPI通信的Flash,即,可能指NOR也可能是NAND。但现在大部分情况默认下人们说的SPI Flash指的是SPI NorFlash。早期Norflash的接口是parallel的形式,即把数据线和地址线并排与IC的管脚连接。但是后来发现不同容量的Norflash不能硬件上兼容(数据线和地址线的数量不一样),并且封装比较大,占用了较大的PCB板位置,所以后来逐渐被SPI(串行接口)Norflash所取代。同时不同容量的SPI Norflash管脚也兼容封装也更小。,至于现在很多人说起NORflash直接都以SPI flash来代称。 * NorFlash根据数据传输的位数可以分为并行(Parallel,即地址线和数据线直接和处理器相连)NorFlash和串行(SPI,即通过SPI接口和处理器相连)NorFlash;区别主要就是:1、SPI NorFlash每次传输一bit位的数据,parallel连接的NorFlash每次传输多个bit位的数据(有x8和x16bit两种);2、SPI NorFlash比parallel便宜,接口简单点,但速度慢。 * NandFlash是地址数据线复用的方式,接口标准统一(x8bit和x16bit),所以不同容量再兼容性上基本没什么问题。但是目前对产品的需求越来越小型化以及成本要求也越来越高,所以SPI NandFlash渐渐成为主流,并且采用SPI NANDFlash方案,主控也可以不需要传统NAND控制器,只需要有SPI接口接口操作访问,从而降低成本。另外SPI NandFlash封装比传统的封装也小很多,故节省了PCB板的空间。 === 2.MSC简介 === * MSC是一种计算机和移动设备之间的传输协议,它允许一个通用串行总线(USB)设备来访问主机的计算设备,使两者之间进行文件传输。 * MSC的通用性和操作简单使他成为移动设备上最常见的文件系统,USB MSC并不需要任何特定的文件系统, 相反,它提供了一个简单的界面来读写接口用于访问任何硬盘驱动器。操作系统可以把MSC像本地硬盘一样格式化,并可以与他们喜欢的任何文件系统格式它,当然也可以创建多个分区。 === 3.原理图 === {{ :icore4tx:icore4tx_arm_hal_33_1.png?direct |}} {{ :icore4tx:icore4tx_arm_hal_33_2.png?direct |}} * 本实验利用SPI FLASH虚拟U盘,用USB线连接PC机与开发板,在电脑上就可以像操作普通U盘那样来操作开发板的FLASH存储设备。 ==== 四、 实验程序 ==== === 1.主函数 === int main(void) { HAL_Init(); SystemClock_Config(); i2c.initialize(); axp152.initialize(); axp152.set_dcdc1(3500);//[ARM & FPGA] axp152.set_dcdc2(1200);//[FPGA INT] axp152.set_dcdc3(3300);//[DCOUT3] axp152.set_dcdc4(3300);//[DCOUT4] axp152.set_aldo1(3300);//[BK3] axp152.set_aldo2(3300);//[ALDOOUT2] axp152.set_dldo1(3300);//[BK0] axp152.set_dldo2(3300);//[BK1] HAL_Delay(200); MX_GPIO_Init(); MX_QUADSPI_Init(); MX_USB_DEVICE_Init(); LED_ON; BSP_QSPI_Init(); while (1) { } } === 2.QUADSPI初始化函数 === 本实验中QSPI我们只是用到了配置的IO,参数没有用到。 uint8_t BSP_QSPI_Init(void) { QSPIHandle.Instance = QUADSPI; /* 调用DeInit函数重置驱动程序 */ if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK) { return QSPI_ERROR; } /* 系统级初始化 */ BSP_QSPI_MspInit(&QSPIHandle, NULL); /* QSPI初始化 */ /* 时钟预分频器设置为1,因此QSPI时钟= 240MHz /(1 + 1)= 120MHz */ QSPIHandle.Init.ClockPrescaler = 1; QSPIHandle.Init.FifoThreshold = POSITION_VAL(W25Q64_FLASH_SIZE) - 1; QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE; QSPIHandle.Init.FlashSize = POSITION_VAL(W25Q64_FLASH_SIZE) - 1; QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE; QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0; QSPIHandle.Init.FlashID = QSPI_FLASH_ID_1; QSPIHandle.Init.DualFlash = QSPI_DUALFLASH_DISABLE; if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK) { return QSPI_ERROR; } return QSPI_OK; void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(qspiHandle->Instance==QUADSPI) { /* QUADSPI时钟使能 */ __HAL_RCC_QSPI_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /** QUADSPI GPIO配置 PB6 ------> QUADSPI_BK1_NCS PF7 ------> QUADSPI_BK1_IO2 PB2 ------> QUADSPI_CLK PD13 ------> QUADSPI_BK1_IO3 PD12 ------> QUADSPI_BK1_IO1 PD11 ------> QUADSPI_BK1_IO0 */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_12|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); } } === 3.STORAGE_Read_HS函数 === #define BLK_NBR 0x800 //块数量 #define BLK_SIZ 0x1000 //块大小 int8_t STORAGE_Read_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { BSP_QSPI_Read(buf, blk_addr * BLK_SIZ, blk_len * BLK_SIZ); return (USBD_OK); } === 4.STORAGE_Write_HS函数 === int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { BSP_QSPI_Write(buf, blk_addr * BLK_SIZ, blk_len * BLK_SIZ); return (USBD_OK); } === 5.STORAGE_GetCapacity_HS函数 === int8_t STORAGE_GetCapacity_HS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)//获取存储容量 { *block_num = BLK_NBR; *block_size = BLK_SIZ; return (USBD_OK); } ==== 五、 实验步骤 ==== - 把仿真器与iCore4TX的SWD调试口相连(直接相连或者通过转接器相连); - 把iCore4TX通过Micro USB线与计算机相连,为iCore4TX供电; - 打开Keil MDK 开发环境,并打开本实验工程; - 烧写程序到iCore4TX上; - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。 ==== 六、 实验现象 ==== * 在“我的电脑”中可以虚拟出一个磁盘进行文件操作,如下图。 {{ :icore4tx:icore4tx_arm_hal_32_3.png?direct |}}