在微控制器領(lǐng)域,初始化參數(shù)配置階段至關(guān)重要。此時,雖無電源驅(qū)動,但微控制器在使能信號到來前,借初始化參數(shù)配置這一精細(xì)步驟,開啟關(guān)鍵準(zhǔn)備進程。初始化參數(shù)配置如同物理坐標(biāo)錨定、邏輯指令部署、內(nèi)在秩序預(yù)設(shè),各參數(shù)像深埋沃土的種子,坐標(biāo)、朝向、深度經(jīng)精密計算,為未來指令運行奠定基礎(chǔ)。
下面以國科安芯的MCU芯片AS32A601為例,詳細(xì)展示下MCU這一嚴(yán)格的設(shè)計特性:
- 外設(shè)檢測階段:MCU會嘗試檢測外設(shè)可用性,然后才開始執(zhí)行用戶代碼。
- 時鐘樹配置:系統(tǒng)時鐘(CK_SYS)、AHB、APB等總線時鐘必須在其他外設(shè)初始化前完成配置。
為什么參數(shù)要在使能前配置?
避免電平跳變:
① GPIO復(fù)用模式下,若先使能外設(shè)再配置復(fù)用選擇器,會導(dǎo)致短暫電平變化。
② 普通輸出IO默認(rèn)輸出低電平,若先使能再設(shè)置高電平,會出現(xiàn)短暫低脈沖。
防止硬件沖突:
① 時鐘使能必須在外設(shè)初始化之前,否則會導(dǎo)致外設(shè)無法正常工作。
② 寄存器默認(rèn)值可能不符合應(yīng)用需求,直接使能可能導(dǎo)致意外行為。
確保穩(wěn)定狀態(tài):
① 外設(shè)使能前需要建立正確的時鐘源、中斷優(yōu)先級等基礎(chǔ)環(huán)境。
② 參數(shù)配置需要一定時間生效,立即使能可能導(dǎo)致功能異常。
- 時鐘配置
i. 通過閱讀芯片手冊,確認(rèn)好項目所需外設(shè)所在時鐘
ii. 確保時鐘最先配置,再去配置外設(shè)
**void** Systemclock_Init()
{
//注意:此處需要開啟系統(tǒng)總線級的時鐘配置,具體外設(shè)時鐘配置可在各模塊初始化函數(shù)中具體開啟,具體請參考時鐘樹或者下圖注釋
// 1. 使用串口時,由于串口掛在APB0總線下,需要在此處開啟AXIBUS3時鐘、AXI4TOAPB0時鐘以及APBBUS0時鐘。
// 2. 使用延時函數(shù)時,需要開啟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初始化
i. 開始GPIO對應(yīng)時鐘
ii. 如果是復(fù)用IO,首先要配置復(fù)用
**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);//先開啟復(fù)用模式
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);
}
- 部分外設(shè)參數(shù)配置
a) Usart
i. 開啟GPIO和外設(shè)時鐘
ii. 配置GPIO先配置復(fù)用
iii. 配置外設(shè)參數(shù)
iv. 最后使能外設(shè)
**void** User_Print_Init(uint32_t BaudRate)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
PLIC_InitTypeDef PLIC_InitStructure;
/*GOPI/外設(shè)時鐘使能*/
GPIOD_CLK_ENABLE();
USART0_CLK_ENABLE();
/* Set GPIO multiplex mapping */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART0); /* USART0_TX */ 開啟復(fù)用模式
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);
/*配置好相關(guān)參數(shù)后,使能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);
}
b) CAN
**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);
}
通過遵循"參數(shù)配置在先,外設(shè)使能在后"的原則,并采用結(jié)構(gòu)化初始化流程,可以顯著提高MCU系統(tǒng)的穩(wěn)定性和可靠性。
審核編輯 黃宇
-
mcu
+關(guān)注
關(guān)注
147文章
18440瀏覽量
381013 -
參數(shù)
+關(guān)注
關(guān)注
11文章
1868瀏覽量
33654
發(fā)布評論請先 登錄
GraniStudio:IO初始化以及IO資源配置例程
GraniStudio:初始化例程
定義IO初始化結(jié)構(gòu)體
IM 系列設(shè)備過載保護機制下界面初始化中斷的底層邏輯與解決方案
stm32cubumx使用1.28.0固件包無法初始化fsmc怎么解決?
stm32cubumx使用1.28.0固件包無法初始化fsmc怎么解決?
stm32cubumx使用1.28.0固件包無法初始化fsmc怎么解決?
STM32CubeMX用于STM32配置和初始化C代碼生成
初始化AFE4400的時候,哪些控制字是必須最先寫的?
ADS1259初始化程序必須執(zhí)行兩次才能夠初始化成功,為什么?
STM32F407 MCU使用SD NAND?不斷電初始化失效解決方案

MCU外設(shè)初始化:為什么參數(shù)配置必須優(yōu)先于使能
評論