这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
icore3_arm_hal_40 [2020/04/21 15:08] fmj 创建 |
icore3_arm_hal_40 [2022/03/18 15:12] sean |
||
---|---|---|---|
行 2: | 行 2: | ||
|技术支持电话|**0379-69926675-801** ||| | |技术支持电话|**0379-69926675-801** ||| | ||
|技术支持邮件|Gingko@vip.163.com ||| | |技术支持邮件|Gingko@vip.163.com ||| | ||
- | |技术论坛|http://www.eeschool.org ||| | ||
^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ||
| V1.0 | 2020-04-21 | gingko | 初次建立 | | | V1.0 | 2020-04-21 | gingko | 初次建立 | | ||
行 10: | 行 9: | ||
\\ | \\ | ||
\\ | \\ | ||
+ | |||
===== STM32CbeMX教程四十——STM32产生随机数据实验 ===== | ===== STM32CbeMX教程四十——STM32产生随机数据实验 ===== | ||
行 61: | 行 61: | ||
\\ | \\ | ||
- | ===== 实验二十二:USBD_MSC实验——虚拟U盘 ===== | + | ===== 实验四十:STM32产生随机数实验 ===== |
==== 一、 实验目的与意义 ==== | ==== 一、 实验目的与意义 ==== | ||
- | - 了解STM32 USB SLAVE结构。 | + | - 了解STM32 RNG结构。 |
- | - 了解STM32 USB SLAVE特征。 | + | - 了解STM32 RNG特征。 |
- | - 掌握USB SLAVE MSC使用方法。 | + | - 掌握RNG使用方法。 |
+ | - 掌握STM32 HAL库中RNG属性的配置方法 | ||
- 掌握Keil MDK集成开发环境使用方法。 | - 掌握Keil MDK集成开发环境使用方法。 | ||
行 78: | 行 79: | ||
- 装有WIN XP(及更高版本)系统的计算机。 | - 装有WIN XP(及更高版本)系统的计算机。 | ||
==== 三、 实验原理 ==== | ==== 三、 实验原理 ==== | ||
- | === 1、SDMMC简介 === | + | === 1、RNG简介 === |
- | * USDMMC指的是SD、SDIO 、MMC卡主机接口,提供APB2外设总线和多媒体卡(MMCs),数字安全记忆卡(SD)和SDIO卡。 | + | * 随机数发生器 (RNG) 是一个以连续模拟噪声为基础的随机数发生器,在主机读数时提供一个32位的随机数。 |
- | * MMC的全称是”Multi Media Card”――所以也通常被叫做”多媒体卡”,是一种小巧大容量的快闪存储卡,特别应用于移动电话 和数字影像及其他移动终端中。 | + | === 2、RNG 主要特性 === |
- | * SD卡,数字安全记忆卡(Secure Digital Memory Card),是 用于移动设备的标准记忆卡。SD卡数据传送和物理规范由MMC发 展而来,大小和MMC差不多。长宽和MMC一样,比MMC稍微厚了一点。兼容性方面SD卡向下兼容多媒体卡(Multi Media Card)。 | + | * 提供由模拟量发生器产生的 32 位随机数 |
- | *SDIO是在SD内存卡接口的基础上发展起来的外设接口,SDIO接 口兼容以前的SD内存卡,并且可以连接SDIO接口的设备。目前,根据SDIO协议的SPEC,SDIO接口支持的设备总类有蓝牙,网卡,电视卡等。 | + | * 两个连续随机数的间隔为 40 个 PLL48CLK 时钟信号周期 |
+ | * 通过监视 RNG 熵来标识异常行为(产生稳定值,或产生稳定的值序列) | ||
+ | * 可被禁止以降低功耗 | ||
+ | === 3、RNG 框图 === | ||
+ | {{ :icore3:icore3_arm_hal_40_1.png?direct |}} | ||
+ | === 4、RNG 功能说明 == | ||
+ | * 随机数发生器采用模拟电路实现。此电路产生馈入线性反馈移位寄存器 (RNG_LFSR)的种子,用于生成32位随机数。 | ||
+ | * 该模拟电路由几个环形振荡器组成,振荡器的输出进行异或运算以产生种子。RNG_LFSR 由 专用时钟 (PLL48CLK)按恒定频率提供时钟信息,因此随机数质量与 HCLK 频率无关。当将大量种子引入RNG_LFSR后,RNG_LFSR的内容会传入数据寄存器 (RNG_DR)。 | ||
+ | * 同时,系统会监视模拟种子和专用时钟 PLL48CLK。状态位(RNG_SR寄存器中)指示何时在种子上出现异常序列,或指示何时PLL48CLK时钟频率过低。检测到错误时生成中断。 | ||
+ | === 5、实验原理 === | ||
+ | * iCore3中使用的STM32F407IGTx芯片带有RNG(随机数产生器),实验将通过串口将产生的随机数打印到电脑屏幕上。 | ||
- | === 2、USB模块介绍 === | ||
- | * USB模块为PC主机和微控制器所实现的功能之间提供了符合USB规范的通信连接。PC主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被USB外设直接访问。这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用512字节缓冲区,最多可用于16个单向或8个双向端点。 | ||
- | * USB模块同PC主机通信,根据USB规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。整个传输的格式由硬件完成,其中包括CRC的生成和校验。每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数。当USB模块识别出一个有效的功能/端点的令牌分组时,(如果需要传输数据并且端点已配置)随之发生相关的数据传输。 | ||
- | * USB模块通过一个内部的16位寄存器实现端口与专用缓冲区的数据交换。在所有的数据传输完成后,如果需要,则根据传输的方向,发送或接收适当的握手分组。在数据传输结束时,USB模块将触发与端点相关的中断,通过读状态寄存器和/或者利用不同的中断处理程序,微控制器可以确定:哪个端点需要得到服务;产生如位填充、格式、CRC、协议、缺失ACK、缓冲区溢出/缓冲区未满等错误时,正在进行的是哪种类型的传输。 | ||
- | |||
- | === 3、USB MSC简介 == | ||
- | * USB大容量存储设备(英语:USB mass storage device class,也称为USB MSC或UMS)是一个协议,允许一个USB接口的设备与主计算设备相连接,以便在两者之间传输文件。对于主计算设备来说,USB设备看起来就像一个移动硬盘,允许拖放型文件传送。它实际上是由USB实施者论坛所通过许多通讯协议的汇总,这一标准提供了许多设备的界面。包括移动硬盘、闪存盘、移动光学驱动器、读卡器、数码相机、数码音乐播放器、PDA以及手机等等。 | ||
- | === 4、USBD_MSC实验介绍: === | ||
- | * 对于iCore3想要变为一个U盘,首先需要存储介质,TF卡作为iCore3开发板中的文件存储器,可以将TF卡虚拟为U盘。此时iCore3设备中的STM32核心将作为协议载体,承载着分别与TF卡和主机通信的任务。 | ||
- | * USBD_MSC实验是用STM32F407的USB接口通过STM32_HAL库生成的代码达到iCore3上的TF卡虚拟成为一个U盘。 | ||
- | === 5、实验介绍: === | ||
- | * 通过移植ST官方提供的代码来实现STM32将TF卡虚拟成U盘,然后就可以像操作U盘一样操作TF卡,本实验使用HAL库生成代码,生成方法参考iCore3_CubeMX教程二十二_USBD_MSC。硬件连接示意图如下图: | ||
- | {{ :icore3:icore3_arm_hal_22_1.png?direct |}} | ||
==== 四、 实验程序 ==== | ==== 四、 实验程序 ==== | ||
行 102: | 行 100: | ||
<code c> | <code c> | ||
int main(void) | int main(void) | ||
- | { | + | { |
+ | uint32_t random_num; | ||
HAL_Init(); | HAL_Init(); | ||
SystemClock_Config(); | SystemClock_Config(); | ||
MX_GPIO_Init(); | MX_GPIO_Init(); | ||
- | MX_USB_DEVICE_Init(); | + | MX_RNG_Init(); |
- | MX_SDIO_SD_Init(); | + | MX_UART4_Init(); |
+ | LED_GREEN_ON; | ||
+ | usart4.initialize(9600); | ||
+ | usart4.printf("Hello, I am iCore3!\r\n"); | ||
while (1) | while (1) | ||
{ | { | ||
- | LED_RED_ON; | + | HAL_Delay(1000); |
- | LED_GREEN_OFF; | + | HAL_RNG_GenerateRandomNumber(&hrng,&random_num); |
- | LED_BLUE_OFF; | + | usart4.printf("随机数产生器产生的随机数为:%x\r\n",random_num); |
- | HAL_Delay(500); | + | |
- | LED_RED_OFF; | + | |
- | LED_GREEN_ON; | + | |
- | LED_BLUE_OFF; | + | |
- | HAL_Delay(500); | + | |
- | LED_RED_OFF; | + | |
- | LED_GREEN_OFF; | + | |
- | LED_BLUE_ON; | + | |
- | HAL_Delay(500); | + | |
} | } | ||
- | } | ||
- | </code> | ||
- | * Main函数中对SDIO与USB分别进行了初始化,在while循环中用三色灯循环点亮表明程序正在运行。 | ||
- | === 2. 初始化函数 === | ||
- | <code c> | ||
- | void MX_SDIO_SD_Init(void) { | ||
- | hsd.Instance = SDIO; | ||
- | hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; | ||
- | hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; | ||
- | hsd.Init.ClockPowerSave=SDIO_CLOCK_POWER_SAVE_DISABLE; | ||
- | hsd.Init.BusWide = SDIO_BUS_WIDE_1B; | ||
- | hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; | ||
- | hsd.Init.ClockDiv = 0; | ||
- | if (HAL_SD_Init(&hsd) != HAL_OK) { | ||
- | Error_Handler(); | ||
- | } | ||
- | if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) { | ||
- | Error_Handler(); | ||
- | } | ||
- | } | ||
- | |||
- | </code> | ||
- | === 3. 接口函数 === | ||
- | * 在usbd_storage_if.c文件中是USB_MSC初始化与读写相关函数。需要在这个文件下编写相关读写SDIO的相关函数,分别为STORAGE_GetCapacity_HS获取容量信息函数STORAGE_Read_HS读SDIO函数与STORAGE_Write_HS写SDIO函数。分别引入SD卡的接口函数。HAL_SD_GetCardInfo获取SD卡信息函数,HAL_SD_ReadBlocks读取SD卡函数,HAL_SD_WriteBlocks写SD卡函数以及HAL_SD_GetCardState获取SD卡状态信息函数。 | ||
- | * 获取容量信息函数 | ||
- | <code c> | ||
- | int8_t STORAGE_GetCapacity_HS(uint8_t lun, uint32_t *block_num, uint16_t *block_size) | ||
- | { | ||
- | /* USER CODE BEGIN 10 */ | ||
- | HAL_SD_GetCardInfo(&hsd,&SDCardInfo); | ||
- | |||
- | *block_num = STORAGE_BLK_NBR; | ||
- | *block_size = STORAGE_BLK_SIZ; | ||
- | return (USBD_OK); | ||
- | /* USER CODE END 10 */ | ||
} | } | ||
</code> | </code> | ||
- | * 读SDIO函数 | + | * 主函数调用了RNG库中的函数HAL_RNG_GenerateRandomNumbe,这个函数将会把产生的随机数放入到指针random_num中,直接打印这个指针,程序将会通过串口向电脑打印产生的随机数,开启绿色LED显示程序正在运行。 |
- | <code c> | + | |
- | int8_t STORAGE_Read_HS(uint8_t lun, uint8_t *buf, | + | |
- | uint32_t blk_addr, uint16_t blk_len) | + | |
- | { | + | |
- | /* USER CODE BEGIN 13 */ | + | |
- | uint32_t timeout = 10000; | + | |
- | if(HAL_SD_ReadBlocks(&hsd,buf,blk_addr,(uint32_t)blk_len, timeout) == USBD_OK){ | ||
- | while(HAL_SD_GetCardState(hsd)!= HAL_OK) | ||
- | { | ||
- | if (timeout-- == 0) | ||
- | { | ||
- | return -1; | ||
- | } | ||
- | } | ||
- | } | ||
- | return (USBD_OK); | ||
- | /* USER CODE END 13 */ | ||
- | } | ||
- | |||
- | </code> | ||
- | * 写SDIO函数 | ||
- | <code c> | ||
- | int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, | ||
- | uint32_t blk_addr, uint16_t blk_len) | ||
- | { | ||
- | /* USER CODE BEGIN 14 */ | ||
- | uint32_t timeout = 10000; | ||
- | | ||
- | if(HAL_SD_WriteBlocks(hsd,buf, blk_addr, blk_len, timeout) == USBD_OK){ | ||
- | while(HAL_SD_GetCardState(hsd)!= HAL_OK) | ||
- | { | ||
- | if (timeout-- == 0) | ||
- | { | ||
- | return -1; | ||
- | } | ||
- | } | ||
- | } | ||
- | return (USBD_OK); | ||
- | /* USER CODE END 14 */ | ||
- | } | ||
- | </code> | ||
==== 五、 实验步骤 ==== | ==== 五、 实验步骤 ==== | ||
- 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连); | - 把仿真器与iCore3的SWD调试口相连(直接相连或者通过转接器相连); | ||
- | - 将跳线帽插在USB OTG; | + | - 把iCore3通过Micro USB线与计算机相连,为iCore3供电; |
- | - 将Micro SD卡插入TF卡座里面; | + | |
- | - 把iCore3(USB OTG)通过Micro USB线与计算机相连,为iCore3供电; | + | |
- 打开Keil MDK 开发环境,并打开本实验工程; | - 打开Keil MDK 开发环境,并打开本实验工程; | ||
- 烧写程序到iCore3上; | - 烧写程序到iCore3上; | ||
- | - 即可在电脑上操作磁盘。 | + | - 也可以进入Debug模式,单步运行或设置断点验证程序逻辑; |
+ | - 打开串口软件。 | ||
==== 六、 实验现象 ==== | ==== 六、 实验现象 ==== | ||
- | * 下载程序到iCore3上之后,可以从设备管理器内查看到USB大容量存储设备。同时可以看到设备和驱动器里面多了一个磁盘。可以对该磁盘进行操作,即可读写Micro SD卡。 | + | * LED_GREEN将会被点亮,串口软件上将会显示随机产生的数字。 |
- | {{ :icore3:icore3_arm_hal_22_2.png?direct |}} | + | {{ :icore3:icore3_arm_hal_40_2.png?direct |}} |