USB(Universal Serial Bus通用串行总线)是一个外部总线标准,用于规范电脑与外部设备的连接和通讯,是应用在PC领域的接口技术,支持设备的即插即用和热插拔功能。STM32芯片自带有USB功能,带来了更多的可玩性,但也更加复杂,之前在STM32F103上实现了USB库的移植,由于F103的USB功能简单,移植比较顺利,具体的方法见本人的博客:STM32F1移植USB库实现外部FLASH模拟U盘功能。 移植过程 9、在 usbd_storage_if.c 中添加底层读写 FLASH 的代码: 10、修改启动文件中的堆空间大小 12、在 main.c 中添加 USB 库相关头文件,并初始化 USB 外设 编译下载后可以在 PC 上看到模拟出的U盘:
相较于 STMF1,STM32F4 的功能大为增强,引入了 OTG 功能,最近入手了一块 NUCLEO-64 开发板,板载芯片是 STM32F446RET6,尝试在上面移植 USB 的 MSC 驱动。
在参考了野火和原子的例程后,没能成功移植官网的USB库,其中一个原因在于例程所使用的芯片是 STM32F429,这一芯片的时钟树结构与 STM32F446 存在差异。从 CubeMX 上可以看出,STM32F429 的 USB 时钟只能来自PLL,如图1,无法在运行于推荐的180MHz主频的情况下获得48MHz的USB 时钟,只能采取降频至144MHz,或超频至192MHz(野火和原子的例程采用的方法)。
图1. STM32F429IGTx时钟树
相比于此,STM32F446RE 的 USB 时钟来源可以选择 PLLSAIP,由 PLLSAI 倍频产生,这就同时满足了180MHz的运行频率和 USB 的48MHz时钟的要求。
图2. STM32F446RETx时钟树
由于与 PLLSAI 相关的资料和程序很少,而且 USB 库的移植相对来说确实麻烦,所以采用 CubeMX 来配置HAL库,实现外部FLASH 模拟U盘的功能。
1、在 CubeMX 中选择相对应的芯片,配置 RCC,如下图:
2、在 Connectivity 中选择 USB_OTG_FS(全速模式),配置为 Device_Only 模式,如下图:
3、在 Middleware 中选择 USB_DEVICE,在 Class For FS IP 中选择 Mass Storage Class,由于采用的存储介质是 FLASH,所以MSC_MEDIA_PACKET 配置为 4096 bytes,如果是SD卡采用默认的 512 bytes 配置,如下图:
4、配置 USB 的 中断优先级为5,如下图:
5、配置时钟树,如下图:
6、配置堆空间 Minimum Heap Size 为 0x1200,作为 USB 的缓冲,如下图:
7、由于之前已经写好了外部 FLASH 移植 FATFS 的程序,不想重复折腾,这里将与 USB 驱动相关的文件拷贝出来,直接添加到之前的工程中。CubeMX 生成的与USB相关的文件位于:
“…MiddlewaresSTSTM32_USB_Device_Library”
…Src中的文件
…Inc中的文件
将上述文件拷贝至之前的移植FATFS文件系统的工程文件下,如下图
并将stm32f4xx_hal_msp.c文件也拷贝到User文件夹,打开工程添加USB库文件代码如下:
8、编译后存在两个错误:
这两个错误都是由于将函数定义为了静态函数,在 main.c 文件中将对应函数的 static 关键字去掉,并在 main.h 中声明 Error_Handler() 函数。
在 main.c 中的时钟初始化函数添加PLLSAI的设置,可以复制CubeMX生成工程中的 main.c 文件中的时钟初始化函数void SystemClock_Config(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* 使能HSE,配置HSE为PLL的时钟源,配置PLL的各种分频因子M N P Q * PLLCLK = HSE/M*N/P = 12M / 25 *360 / 2 = 180M */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 360; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; RCC_OscInitStruct.PLL.PLLR = 2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Activate the Over-Drive mode */ if (HAL_PWREx_EnableOverDrive() != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB busses clocks */ /* 选择PLLCLK作为SYSCLK,并配置 HCLK, PCLK1 and PCLK2 的时钟分频因子 * SYSCLK = PLLCLK = 180M * HCLK = SYSCLK / 1 = 180M * PCLK2 = SYSCLK / 2 = 90M * PCLK1 = SYSCLK / 4 = 45M */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48; PeriphClkInitStruct.PLLSAI.PLLSAIM = 4; PeriphClkInitStruct.PLLSAI.PLLSAIN = 96; PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2; PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4; PeriphClkInitStruct.PLLSAIDivQ = 1; PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLSAIP; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } }
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : usbd_storage_if.c * @version : v1.0_Cube * @brief : Memory management layer. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2020 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "usbd_storage_if.h" /* USER CODE BEGIN INCLUDE */ #include "./flash/bsp_spi_flash.h" /* USER CODE END INCLUDE */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ /* USER CODE END PV */ /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY * @brief Usb device. * @{ */ /** @defgroup USBD_STORAGE * @brief Usb mass storage device module * @{ */ /** @defgroup USBD_STORAGE_Private_TypesDefinitions * @brief Private types. * @{ */ /* USER CODE BEGIN PRIVATE_TYPES */ /* USER CODE END PRIVATE_TYPES */ /** * @} */ /** @defgroup USBD_STORAGE_Private_Defines * @brief Private defines. * @{ */ #define STORAGE_LUN_NBR 1 #define STORAGE_BLK_NBR 4096//0x10000 #define STORAGE_BLK_SIZ 4096//0x200 /* USER CODE BEGIN PRIVATE_DEFINES */ /* USER CODE END PRIVATE_DEFINES */ /** * @} */ /** @defgroup USBD_STORAGE_Private_Macros * @brief Private macros. * @{ */ /* USER CODE BEGIN PRIVATE_MACRO */ /* USER CODE END PRIVATE_MACRO */ /** * @} */ /** @defgroup USBD_STORAGE_Private_Variables * @brief Private variables. * @{ */ /* USER CODE BEGIN INQUIRY_DATA_FS */ /** USB Mass storage Standard Inquiry Data. */ const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */ /* LUN 0 */ 0x00, 0x80, 0x02, 0x02, (STANDARD_INQUIRY_DATA_LEN - 5), 0x00, 0x00, 0x00, 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */ 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '.', '0' ,'1' /* Version : 4 Bytes */ }; /* USER CODE END INQUIRY_DATA_FS */ /* USER CODE BEGIN PRIVATE_VARIABLES */ /* USER CODE END PRIVATE_VARIABLES */ /** * @} */ /** @defgroup USBD_STORAGE_Exported_Variables * @brief Public variables. * @{ */ extern USBD_HandleTypeDef hUsbDeviceFS; /* USER CODE BEGIN EXPORTED_VARIABLES */ /* USER CODE END EXPORTED_VARIABLES */ /** * @} */ /** @defgroup USBD_STORAGE_Private_FunctionPrototypes * @brief Private functions declaration. * @{ */ static int8_t STORAGE_Init_FS(uint8_t lun); static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size); static int8_t STORAGE_IsReady_FS(uint8_t lun); static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun); static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); static int8_t STORAGE_GetMaxLun_FS(void); /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ /* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ /** * @} */ USBD_StorageTypeDef USBD_Storage_Interface_fops_FS = { STORAGE_Init_FS, STORAGE_GetCapacity_FS, STORAGE_IsReady_FS, STORAGE_IsWriteProtected_FS, STORAGE_Read_FS, STORAGE_Write_FS, STORAGE_GetMaxLun_FS, (int8_t *)STORAGE_Inquirydata_FS }; /* Private functions ---------------------------------------------------------*/ /** * @brief Initializes over USB FS IP * @param lun: * @retval USBD_OK if all operations are OK else USBD_FAIL */ int8_t STORAGE_Init_FS(uint8_t lun) { /* USER CODE BEGIN 2 */ SPI_FLASH_Init(); if (SPI_FLASH_ReadID() != sFLASH_ID) { //printf("errorrn"); return (USBD_FAIL); } return (USBD_OK); /* USER CODE END 2 */ } /** * @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 */ *block_num = STORAGE_BLK_NBR; *block_size = STORAGE_BLK_SIZ; return (USBD_OK); /* USER CODE END 3 */ } /** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */ int8_t STORAGE_IsReady_FS(uint8_t lun) { /* USER CODE BEGIN 4 */ if (SPI_FLASH_ReadID() == sFLASH_ID) { //printf("errorrn"); return (USBD_OK); } else { return (USBD_FAIL); } //return (USBD_OK); /* USER CODE END 4 */ } /** * @brief . * @param lun: . * @retval USBD_OK if all operations are OK else USBD_FAIL */ int8_t STORAGE_IsWriteProtected_FS(uint8_t lun) { /* USER CODE BEGIN 5 */ return (USBD_OK); /* USER CODE END 5 */ } /** * @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 */ SPI_FLASH_BufferRead(buf, blk_addr*STORAGE_BLK_SIZ, blk_len*STORAGE_BLK_SIZ); return (USBD_OK); /* 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 */ SPI_FLASH_SectorErase(blk_addr*STORAGE_BLK_SIZ); SPI_FLASH_BufferWrite(buf, blk_addr*STORAGE_BLK_SIZ, blk_len*STORAGE_BLK_SIZ); return (USBD_OK); /* USER CODE END 7 */ } /** * @brief . * @param None * @retval . */ int8_t STORAGE_GetMaxLun_FS(void) { /* USER CODE BEGIN 8 */ return (STORAGE_LUN_NBR - 1); /* USER CODE END 8 */ } /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
11、在 stm32f4xx_it.c 添加 USB 中断服务函数/** ****************************************************************************** * @file Templates/Src/stm32f4xx_it.c * @author MCD Application Team * @brief Main Interrupt Service Routines. * This file provides template for all exceptions handler and * peripherals interrupt service routine. ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "stm32f4xx_it.h" extern PCD_HandleTypeDef hpcd_USB_OTG_FS; /** @addtogroup STM32F4xx_HAL_Examples * @{ */ /** @addtogroup Templates * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /******************************************************************************/ /* Cortex-M4 Processor Exceptions Handlers */ /******************************************************************************/ /** * @brief This function handles NMI exception. * @param None * @retval None */ void NMI_Handler(void) { } /** * @brief This function handles Hard Fault exception. * @param None * @retval None */ void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } } /** * @brief This function handles Memory Manage exception. * @param None * @retval None */ void MemManage_Handler(void) { /* Go to infinite loop when Memory Manage exception occurs */ while (1) { } } /** * @brief This function handles Bus Fault exception. * @param None * @retval None */ void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { } } /** * @brief This function handles Usage Fault exception. * @param None * @retval None */ void UsageFault_Handler(void) { /* Go to infinite loop when Usage Fault exception occurs */ while (1) { } } /** * @brief This function handles SVCall exception. * @param None * @retval None */ void SVC_Handler(void) { } /** * @brief This function handles Debug Monitor exception. * @param None * @retval None */ void DebugMon_Handler(void) { } /** * @brief This function handles PendSVC exception. * @param None * @retval None */ void PendSV_Handler(void) { } /** * @brief This function handles SysTick Handler. * @param None * @retval None */ void SysTick_Handler(void) { HAL_IncTick(); } /******************************************************************************/ /* STM32F4xx Peripherals Interrupt Handlers */ /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ /* available peripheral interrupt handler's name please refer to the startup */ /* file (startup_stm32f4xx.s). */ /******************************************************************************/ /** * @brief This function handles PPP interrupt request. * @param None * @retval None */ /*void PPP_IRQHandler(void) { }*/ /** * @} */ /** * @} */ /** * @brief This function handles USB On The Go FS global interrupt. */ void OTG_FS_IRQHandler(void) { /* USER CODE BEGIN OTG_FS_IRQn 0 */ //printf("111rn"); /* USER CODE END OTG_FS_IRQn 0 */ HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); /* USER CODE BEGIN OTG_FS_IRQn 1 */ /* USER CODE END OTG_FS_IRQn 1 */ } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/** ****************************************************************************** * @file main.c * @author Asher * @version V1.0 * @date 2020-05-16 * @brief 外部FLASH模拟U盘 ****************************************************************************** * @attention * * 实验平台: STM32F446RET6 * * * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "./usart/bsp_usart.h" #include "./flash/bsp_spi_flash.h" #include "ff.h" #include "usb_device.h" #include "usbd_core.h" //函数声明 void SystemClock_Config(void); void Error_Handler(void); static void MX_GPIO_Init(void); //全局变量 FATFS fs; /* FatFs文件系统对象 */ FIL fnew; /* 文件对象 */ FRESULT res_flash; /* 文件操作结果 */ UINT fnum; /* 文件成功读写数量 */ BYTE ReadBuffer[1024]={0}; /* 读缓冲区 */ BYTE WriteBuffer[] = "FatFs文件系统测试数据。rn"; /* 写缓冲区*/ BYTE work[FF_MAX_SS]; /** * @brief Main program * @param None * @retval None */ int main(void) { HAL_Init(); SystemClock_Config(); //初始化USB MX_GPIO_Init(); MX_USB_DEVICE_Init(); //初始化串口 USART_Config(); printf("****** FatFs文件系统实验 ******rn"); //在外部SPI Flash挂载文件系统,文件系统挂载时会对SPI设备初始化 //初始化函数调用流程如下 //f_mount()->find_volume()->disk_initialize->SPI_FLASH_Init() res_flash = f_mount(&fs,"0:",1); /*----------------------- 格式化测试 -----------------*/ /* 如果没有文件系统就格式化创建创建文件系统 */ if(res_flash == FR_NO_FILESYSTEM) { printf("》FLASH还没有文件系统,即将进行格式化...rn"); /* 格式化 */ res_flash = f_mkfs("0:",0,work,sizeof work); if(res_flash == FR_OK) { printf("》FLASH已成功格式化文件系统。rn"); /* 格式化后,先取消挂载 */ res_flash = f_mount(NULL,"0:",1); /* 重新挂载*/ res_flash = f_mount(&fs,"0:",1); } else { printf("《《格式化失败。(%d)》》rn",res_flash); while(1); } } else if(res_flash!=FR_OK) { printf("!!外部Flash挂载文件系统失败。(%d)rn",res_flash); printf("!!可能原因:SPI Flash初始化不成功。rn"); while(1); } else { printf("》文件系统挂载成功,可以进行读写测试rn"); } /*----------------------- 文件系统测试:写测试 -------------------*/ /* 打开文件,每次都以新建的形式打开,属性为可写 */ printf("rn****** 即将进行文件写入测试... ******rn"); res_flash = f_open(&fnew, "0:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE ); if ( res_flash == FR_OK ) { printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。rn"); /* 将指定存储区内容写入到文件内 */ res_flash=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum); if(res_flash==FR_OK) { printf("》文件写入成功,写入字节数据:%dn",fnum); printf("》向文件写入的数据为:rn%srn",WriteBuffer); } else { printf("!!文件写入失败:(%d)n",res_flash); } /* 不再读写,关闭文件 */ f_close(&fnew); } else { printf("!!打开/创建文件失败。(%d)rn",res_flash); } /*------------------- 文件系统测试:读测试 --------------------------*/ printf("****** 即将进行文件读取测试... ******rn"); res_flash = f_open(&fnew, "0:FatFs读写测试文件.txt",FA_OPEN_EXISTING | FA_READ); if(res_flash == FR_OK) { printf("》打开文件成功。rn"); res_flash = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum); if(res_flash==FR_OK) { printf("》文件读取成功,读到字节数据:%drn",fnum); printf("》读取得的文件数据为:rn%s rn", ReadBuffer); } else { printf("!!文件读取失败:(%d)n",res_flash); } } else { printf("!!打开文件失败。rn"); } /* 不再读写,关闭文件 */ f_close(&fnew); /* 不再使用文件系统,取消挂载文件系统 */ //f_mount(NULL,"0:",1); /* Infinite loop */ while (1) { } } /** * @brief System Clock Configuration * The system Clock is configured as follow : * System Clock source = PLL (HSI) * SYSCLK(Hz) = 180000000 * HCLK(Hz) = 180000000 * AHB Prescaler = 1 * APB1 Prescaler = 4 * APB2 Prescaler = 2 * HSE Frequency(Hz) = 8000000 * PLL_M = 8 * PLL_N = 360 * PLL_P = 2 * PLL_Q = 7 * PLL_R = 2 * VDD(V) = 3.3 * Main regulator output voltage = Scale1 mode * Flash Latency(WS) = 5 * @param None * @retval None */ void SystemClock_Config(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* 使能HSE,配置HSE为PLL的时钟源,配置PLL的各种分频因子M N P Q * PLLCLK = HSE/M*N/P = 12M / 25 *360 / 2 = 180M */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 360; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; RCC_OscInitStruct.PLL.PLLR = 2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Activate the Over-Drive mode */ if (HAL_PWREx_EnableOverDrive() != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB busses clocks */ /* 选择PLLCLK作为SYSCLK,并配置 HCLK, PCLK1 and PCLK2 的时钟分频因子 * SYSCLK = PLLCLK = 180M * HCLK = SYSCLK / 1 = 180M * PCLK2 = SYSCLK / 2 = 90M * PCLK1 = SYSCLK / 4 = 45M */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48; PeriphClkInitStruct.PLLSAI.PLLSAIM = 4; PeriphClkInitStruct.PLLSAI.PLLSAIN = 96; PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2; PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4; PeriphClkInitStruct.PLLSAIDivQ = 1; PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLSAIP; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); } /** * @brief This function is executed in case of error occurrence. * @param None * @retval None */ void Error_Handler(void) { /* User may add here some code to deal with this error */ while(1) { } } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %drn", file, line) */ /* Infinite loop */ while (1) { } } #endif /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
END
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算