MCU外设初始化:为什么参数配置必须优先于使能

在微控制器领域,初始化参数配置阶段至关重要。此时,虽无电源驱动,但微控制器在使能信号到来前,借初始化参数配置这一精细步骤,开启关键准备进程。初始化参数配置如同物理坐标锚定、逻辑指令部署、内在秩序预设,各参数像深埋沃土的种子,坐标、朝向、深度经精密计算,为未来指令运行奠定基础。

下面以国科安芯的MCU芯片AS32A601为例,详细展示下MCU这一严格的设计特性:

‌1. ‌外设检测阶段‌:MCU会尝试检测外设可用性,然后才开始执行用户代码。

  1. 时钟树配置‌:系统时钟(CK_SYS)、AHB、APB等总线时钟必须在其他外设初始化前完成配置。

为什么参数要在使能前配置?

避免电平跳变‌:

  • GPIO复用模式下,若先使能外设再配置复用选择器,会导致短暂电平变化。
  • 普通输出IO默认输出低电平,若先使能再设置高电平,会出现短暂低脉冲。

‌ 防止硬件冲突‌:

  • 时钟使能必须在外设初始化之前,否则会导致外设无法正常工作。
  • 寄存器默认值可能不符合应用需求,直接使能可能导致意外行为。

确保稳定状态‌:

  • 外设使能前需要建立正确的时钟源、中断优先级等基础环境。
  • 参数配置需要一定时间生效,立即使能可能导致功能异常。

时钟配置

通过阅读芯片手册,确认好项目所需外设所在时钟
2. 确保时钟最先配置,再去配置外设

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | void Systemclock_Init() { //注意:此处需要开启系统总线级的时钟配置,具体外设时钟配置可在各模块初始化函数中具体开启,具体请参考时钟树或者下图注释 // 1. 使用串口时,由于串口挂在APB0总线下,需要在此处开启AXIBUS3时钟、AXI4TOAPB0时钟以及APBBUS0时钟。 // 2. 使用延时函数时,需要开启CLINT时钟 // 3. 使用eflash、qspi时,需要开启AXIBUS3时钟、AXILITEBUS2时钟 /* AXIBus3 clock operation Guide*/ AXIBUS3_CLK_ENABLE(); AXI4TOAPB0_CLK_ENABLE(); APBBUS0_CLK_ENABLE(); AXI4TOAPB1_CLK_ENABLE(); APBBUS1_CLK_ENABLE(); AXILITEBUS1_CLK_ENABLE(); AXILITEBUS2_CLK_ENABLE(); EFLASH_CLK_ENABLE(); PLIC_CLK_ENABLE(); CLINT_CLK_ENABLE(); SMU_PLLInitTypeDef SMU_PLLInitStruct; SMU_ClockInitTypeDef SMU_ClockInitStruct; /* Set PLL parameters values */ SMU_PLLInitStruct.OscillatorType = SMU_OSCILLATORTYPE_OSC; SMU_PLLInitStruct.FIRCOscState = DISABLE; SMU_PLLInitStruct.FIRCCalibrationValue = 0x00; SMU_PLLInitStruct.PLLConfig.PLLState = ENABLE; SMU_PLLInitStruct.PLLConfig.PLLSource = SMU_PLLCLK_OSC; SMU_PLLInitStruct.PLLConfig.PLLDivR = 0x01; SMU_PLLInitStruct.PLLConfig.PLLDivQ = 0x01; SMU_PLLInitStruct.PLLConfig.PLLDivN = 0x14; SMU_PLLInitStruct.PLLConfig.PLLDivF = 0xA0; SMU_PLLInit(&SMU_PLLInitStruct); /* Ensure that the EFLASH is consistent with the system clock */ FLASH_UnlockCtrl(); FLASH_SetCLKFreq(0xA0); /* Set System Clock parameters values */ SMU_ClockInitStruct.SYSCLKSelect = SMU_SYSCLK_PLL; SMU_ClockInitStruct.AXI4Bus3CLKDiv = AXI4Bus3CLKDiv1; SMU_ClockInitStruct.APBBus0CLKDiv = APBBus0CLKDiv1; SMU_ClockInitStruct.APBBus1CLKDiv = APBBus1CLKDiv8; SMU_ClockInitStruct.CANX2CLKDiv = CANX2CLKDiv1; SMU_ClockInit(&SMU_ClockInitStruct); EFLASH_CLK_UPDATE_ENABLE(); EFLASH_CLK_UPDATE_DISABLE(); FLASH_LockCtrl(); /* Get System Clock values */ SMU_GetClocksFreq(&SMU_ClocksStruct); } |

GPIO初始化

  1. 开始GPIO对应时钟

  2. 如果是复用IO,首先要配置复用

|-------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | void GPIO_Init(void ) { GPIO_InitTypeDef GPIO_InitStructure; /*开启GPIO所在时钟*/ GPIOD_CLK_ENABLE(); GPIOG_CLK_ENABLE(); GPIOF_CLK_ENABLE(); /* Set GPIO multiplex mapping */ GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_CAN1);//先开启复用模式 GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_CAN1); /* GPIO Configure */ GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_Out_PP; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_9mA; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_IType = GPIO_IPU; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_9mA; GPIO_Init(GPIOD, &GPIO_InitStructure); /* GPIOB Configure */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_Out_PP; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_9mA; GPIO_Init(GPIOG, &GPIO_InitStructure); /* GPIOB Configure */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_IType = GPIO_IPU; GPIO_InitStructure.GPIO_OType = GPIO_Out_PP; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_9mA; GPIO_Init(GPIOF, &GPIO_InitStructure); } |

部分外设参数配置

Usart
  1. 最后使能外设
  2. 配置外设参数
  3. 配置GPIO先配置复用
  4. 开启GPIO和外设时钟

|----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | void User_Print_Init(uint32_t BaudRate) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; PLIC_InitTypeDef PLIC_InitStructure; /*GOPI/外设时钟使能*/ GPIOD_CLK_ENABLE(); USART0_CLK_ENABLE(); /* Set GPIO multiplex mapping */ GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART0); /* USART0_TX */ 开启复用模式 GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART0); /* USART0_RX */ /* GPIO Configure */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_Out_PP; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_4_5mA; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_IType = GPIO_IN_FLOATING; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_4_5mA; GPIO_Init(GPIOD, &GPIO_InitStructure); /*防止配置冲突*/ USART_DeInit(USART0); USART_StructInit(&USART_InitStructure); /* Initializes the USART0 */ USART_InitStructure.USART_BaudRate = BaudRate; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_OverSampling = USART_OverSampling_16; USART_Init(USART0, &USART_InitStructure); /*配置好相关参数后,使能USART*/ USART_Cmd(USART0, ENABLE); USART_ITConfig(USART0, USART_IT_RXNE, ENABLE); /* Configer the USART0 interrupt */ PLIC_InitStructure.PLIC_IRQChannel = USART0_IRQn; PLIC_InitStructure.PLIC_IRQPriority = 1; PLIC_InitStructure.PLIC_IRQChannelCmd = ENABLE; PLIC_Init(&PLIC_InitStructure); } |

CAN

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | void User_CANFD3_Init() { CANFD3_CLK_ENABLE(); GPIOC_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStructure; CANFD_InitTypeDef CANFD_InitStructure; PLIC_InitTypeDef PLIC_InitStructure; /* Set GPIO multiplex mapping */ GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_CAN3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_CAN3); /* GPIO Configure */ GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_Out_PP; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_18mA; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_IType = GPIO_IPU; GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_18mA; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Initializes the CANFD1 */ /* Arbitration Phase (Nominal) Baud Rate 500KHz */ /* Data Phase Baud Rate 2MHz */ CANFD_StructInit(&CANFD_InitStructure); CANFD_InitStructure.CANFD_SRR = CANFD_SRR_RESET; CANFD_InitStructure.CANFD_APBRPR = CANFD_APBRPR_10tp; CANFD_InitStructure.CANFD_APBTR_APTS1 = CANFD_APBTR_TS1_11tp; CANFD_InitStructure.CANFD_APBTR_APTS2 = CANFD_APBTR_TS2_4tp; CANFD_InitStructure.CANFD_APBTR_APSJW = CANFD_APBTR_SJW_2tp; CANFD_InitStructure.CANFD_DPBRPR = CANFD_DPBRPR_2tp; CANFD_InitStructure.CANFD_DPBTR_DPTS1 = CANFD_DPBTR_TS1_7tp; CANFD_InitStructure.CANFD_DPBTR_DPTS2 = CANFD_DPBTR_TS2_2tp; CANFD_InitStructure.CANFD_DPBTR_DPSJW = CANFD_DPBTR_SJW_2tp; CANFD_Init(CANFD3, &CANFD_InitStructure); /* CANFD receive filter configure */ CANFD_FilterInit(CANFD3, TB0, 0xFFE00000, 0X62E00000); CANFD_AutoRetransConfig(CANFD3,ENABLE); /* Enable new message received interrupt */ CANFD_ITConfig(CANFD3, CANFD_IT_ERXOK, ENABLE); /* CANFD Enable */ CANFD_Enable(CANFD3); PLIC_StructInit(&PLIC_InitStructure); /* Configer the CANFD1 interrupt */ PLIC_InitStructure.PLIC_IRQChannel = CANFD3_IRQn; PLIC_InitStructure.PLIC_IRQPriority = 2; PLIC_InitStructure.PLIC_IRQChannelCmd = ENABLE; PLIC_Init(&PLIC_InitStructure); CANFD_ClearITPendingBit(CANFD3, CANFD_CLEAR_ALL); } |

通过遵循"参数配置在先,外设使能在后"的原则,并采用结构化初始化流程,可以显著提高MCU系统的稳定性和可靠性。

相关推荐
andxe4 小时前
安科士 AndXe 技术博客:400G QSFP112 SR4 光模块|AI 算力与超算短距互联最优方案
网络·人工智能·光模块·光通信
shiyi.十一5 小时前
第2章:应用层 — 知识要点与架构
网络·计算机网络·架构
DFT计算杂谈6 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
水境传感 李兆栋6 小时前
GNSS 位移监测站 :毫米级感知,筑牢安全监测防线
网络
sramdram6 小时前
MCU微控制器OA打印机方案
单片机·嵌入式硬件·mcu·mcu微控制器
天天爱吃肉82187 小时前
【电源拆解:跟着问答逐一认识开关适配器PCB元器件】
大数据·人工智能·python·功能测试·嵌入式硬件·汽车
中微极客7 小时前
2026主流AI Agent框架技术选型与性能对比
运维·网络·人工智能
科芯创展10 小时前
3.5A,60VIN,异步降压芯片,XZ1815
单片机·嵌入式硬件
茯苓gao10 小时前
嵌入式开发笔记:Qt信号槽机制深度解析——从原理到实战的全方位指南
开发语言·笔记·嵌入式硬件·qt·学习
猿的天空11 小时前
机器人双手迎来全栈训练系统:灵初智能EgoSteer让灵巧手无所不能
网络·人工智能·计算机·ai·程序员·机器人·编程