最新教程下載:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255
第16章 STM32F407必備的HAL庫API(重要)
本章教程為大家講解制作一個STM32F4的例子所需的最基本API函數,對於一些常用的API函數,一定要熟練掌握這些函數都是實現了什么功能,不常用的函數有個了解即可,用到的時候再去學。
16.1 初學者重要提示
16.2 那些是必備的API
16.3 源文件stm32f4xx_hal.c
16.4 stm32f4xx_hal_rcc.c
16.5 stm32f4xx_hal_cortex.c
16.6 總結
16.1 初學者重要提示
1、 對於一些常用的函數,大家一定要熟練的掌握都實現了什么功能,比如HAL_Init,HAL_RCC_OscConfig,HAL_RCC_ClockConfig等。最好的辦法是把這些函數的源碼讀一遍。
16.2 那些是必備的API
這里我們通過一個簡單的初始化流程來了解STM32F4的工程模板所必備的庫文件和API:
1、 第1步:系統上電復位,進入啟動文件startup_stm32f407xx.s,在這個文件里面執行復位中斷服務程序。
- 在復位中斷服務程序里面執行函數SystemInit,此函數在文件system_stm32f4xx.c里面。
- 之后是調用編譯器封裝好的函數,比如用於MDK的啟動文件是調用__main,最終進入到main函數。
2、 第2步:進入到main函數就可以開始用戶應用程序編程了。在這個函數里面要做幾個重要的初始化,依次是:
- HAL庫初始化函數HAL_Init,需要用到文件stm32f4xx_hal.c。
- 系統時鍾初始化,需要用到庫文件stm32f4xx_hal_rcc.c。
前面的兩步完成后,就可以開始做用戶需要的按鍵、串口等方面的初始化和應用代碼的實現了。這里把我們需要學習的幾個庫文件整理出來,依次有:
- startup_stm32f407xx.s
- system_stm32f4xx.c
- stm32f4xx_hal.c
- stm32f4xx_hal_cortex.c
- stm32f4xx_hal_rcc.c
- core_cm4.h
其中startup_stm32f429xx.s和system_stm32f4xx.c已經在第13章為大家講解過,這里不再贅述。。本章教程重點為大家講解文件stm32f4xx_hal.c、stm32f4xx_hal_cortex.c和sm32f4x_hal_rcc.c(core_cm4.h文件在后面章節為大家講解)。
16.3 源文件stm32f4xx_hal.c(重要)
這個文件比較雜,像基准電壓大小配置,EXTI配置,IO補償配置等都在這個文件里面設置。學習這個文件注意事項:
- HAL庫中各個外設驅動里面的延遲實現是基於此文件提供的時間基准,而這個時間基准既可以使用滴答定時器實現也可以使用通用的定時器實現,默認情況下是用的滴答定時器。
- 函數HAL_Init里面會調用時間基准初始化函數HAL_InitTick,而調用函數HAL_RCC_ClockConfig也會調用時間基准初始化函數HAL_InitTick。
- 如果在中斷服務程序里面調用延遲函數HAL_Delay要特別注意,因為這個函數的時間基准是基於滴答定時器或者其他通用定時器實現,實現方式是滴答定時器或者其他通用定時器里面做了個變量計數。如此一來,結果是顯而易見的,如果其他中斷服務程序調用了此函數,且中斷優先級高於滴答定時器,會導致滴答定時器中斷服務程序一直得不到執行,從而卡死在里面。所以滴答定時器的中斷優先級一定要比它們高。
16.3.1 函數HAL_Init
函數原型:
HAL_StatusTypeDef HAL_Init(void) { /* 配置Flash的指令預取,指令Cache和數據Cache */ #if (INSTRUCTION_CACHE_ENABLE != 0U) __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); #endif #if (DATA_CACHE_ENABLE != 0U) __HAL_FLASH_DATA_CACHE_ENABLE(); #endif #if (PREFETCH_ENABLE != 0U) __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); #endif /* 設置中斷優先級分組 */ HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); /* 使用滴答定時器做為默認時基,配置為1ms滴答,另外系統上電后默認使用的HSI時鍾 */ HAL_InitTick(TICK_INT_PRIORITY); /* 初始化底層硬件 */ HAL_MspInit(); /* 返回HAL_OK */ return HAL_OK; }
函數描述:
此函數用於初始化HAL庫,此函數主要實現如下功能:
- 設置NVIC優先級分組是4。
- 設置滴答定時器的每1ms中斷一次。
- HAL庫不像之前的標准庫,在系統啟動函數SystemInit里面做了RCC初始化,HAL庫是沒有做的,所以進入到main函數后,系統還在用內部高速時鍾HSI,對於F4來說,HSI主頻是16MHz。
- 函數HAL_Init里面調用的HAL_MspInit一般在文件stm32f4xx_hal_msp.c里面做具體實現,主要用於底層初始化。當前此函數也在文件stm32f4xx_hal.c里面,只是做了弱定義。
函數參數:
- 返回值,返回HAL_ERROR表示參數錯誤,HAL_OK表示發送成功,HAL_BUSY表示忙,正在使用中。
注意事項:
- 必須在main函數里面優先調用此函數。
- 用戶務必保證每1ms一次滴答中斷。
- 關於優先級分組的設置可以看第xx章節(注:后面做到這個章節時補上)。
使用舉例:
此函數的使用比較簡單,上電后優先調用即可。
16.3.2 函數HAL_DeInit
函數原型:
HAL_StatusTypeDef HAL_DeInit(void) { /* 復位所有外設 */ __HAL_RCC_APB1_FORCE_RESET(); __HAL_RCC_APB1_RELEASE_RESET(); __HAL_RCC_APB2_FORCE_RESET(); __HAL_RCC_APB2_RELEASE_RESET(); __HAL_RCC_AHB1_FORCE_RESET(); __HAL_RCC_AHB1_RELEASE_RESET(); __HAL_RCC_AHB2_FORCE_RESET(); __HAL_RCC_AHB2_RELEASE_RESET(); __HAL_RCC_AHB3_FORCE_RESET(); __HAL_RCC_AHB3_RELEASE_RESET(); /* 復位底層硬件初始化 */ HAL_MspDeInit(); /* 返回值 */ return HAL_OK; }
函數描述:
此函數用於復位HAL庫和滴答時鍾。
- 復位了APB1,2的時鍾以及AHB1,2,3的時鍾。
- 函數HAL_DeInit里面調用的HAL_MspDeInit一般在文件stm32f4xx_hal_msp.c里面做具體實現,主要用於底層初始化,跟函數HAL_Init里面調用的HAL_MspInit是一對。當前此函數也在文件stm32f4xx_hal.c里面,只是做了弱定義。
使用舉例:
此函數的使用比較簡單,需要調用的時候直接調用即可。
16.3.3 函數HAL_InitTick
函數原型:
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) { /* Configure the SysTick to have interrupt in 1ms time basis*/ if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U) { return HAL_ERROR; } /* Configure the SysTick IRQ priority */ if (TickPriority < (1UL << __NVIC_PRIO_BITS)) { HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U); uwTickPrio = TickPriority; } else { return HAL_ERROR; } /* Return function status */ return HAL_OK; }
函數描述:
此函數用於初始化滴答時鍾,此函數相關問題如下:
- 此函數有個前綴__weak ,表示弱定義,用戶可以重定義。
- 此函數用於初始化滴答時鍾1ms中斷一次,並且為滴答中斷配置一個用戶指定的優先級。
- 此函數由HAL_Init調用,或者任何其它地方調用函數HAL_RCC_ClockConfig配置RCC的時候也會調用HAL_InitTick。
- 調用基於此函數實現的HAL_Delay要特別注意,因為這個函數的時間基准是基於滴答定時器或者其他通用定時器實現,實現方式是滴答定時器或者其他通用定時器里面做了個變量計數。如此一來,結果是顯而易見的,如果其他中斷服務程序調用了此函數,且中斷優先級高於滴答定時器,會導致滴答定時器中斷服務程序一直得不到執行,從而卡死在里面。所以滴答定時器的中斷優先級一定要比它們高。
函數參數:
- 形參TickPriority用於設置滴答定時器優先級。
- 返回值,返回HAL_ERROR表示參數錯誤,HAL_OK表示發送成功,HAL_BUSY表示忙,正在使用中。
使用舉例:
此函數由HAL_Init調用,無需用戶操作,除非需要重定義。
16.3.4 Systick的相關函數
調用了函數HAL_Init后,Systick相關的函數就可以使用了。這些函數如下:
函數原型:
__weak void HAL_IncTick(void) __weak uint32_t HAL_GetTick(void) uint32_t HAL_GetTickPrio(void) HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq) HAL_TickFreqTypeDef HAL_GetTickFreq(void) __weak void HAL_Delay(uint32_t Delay) __weak void HAL_SuspendTick(void) __weak void HAL_ResumeTick(void)
函數描述:
這些函數就比較簡單了,下面把這些函數實現的功能做個簡單的說明:
- 函數HAL_IncTick在滴答定時器中斷里面被調用,實現一個簡單的計數功能,因為一般滴答定時器中斷都是配置的1ms,所以計數全局變量uwTick每毫秒加1。
- 函數HAL_GetTick用於獲取全局變量uwTick當前的計數。
- 函數HAL_GetTickPrio用於獲取滴答時鍾優先級。
- 函數HAL_SetTickFreq和HAL_GetTickFreq是一對,前者用於設置滴答中斷頻率,后再用於獲取滴答中斷頻率。
- 函數HAL_Delay用於阻塞式延遲,默認單位是ms。
- 函數HAL_SuspendTick和HAL_ResumeTick是一對,前者用於掛起滴答定時器,后者用於恢復。
注意事項:
- 函數有個前綴__weak ,表示弱定義,用戶可以重定義。
使用舉例:
這些函數都比較簡單,這里就不舉例了。需要的時候,直接調用即可。
16.3.5 低功耗狀態下繼續使用調試功能
如果希望在睡眠,停機和待機的低功耗模式下繼續使用調試功能,調用下面的函數即可:
/* 睡眠模式下繼續使用調試功能 */ void HAL_DBGMCU_EnableDBGSleepMode(void) { SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); } /* 停機模式下繼續使用調試功能 */ void HAL_DBGMCU_EnableDBGStopMode(void) { SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP); } /* 待機模式下繼續使用調試功能 */ void HAL_DBGMCU_EnableDBGStandbyMode(void) { SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); }
16.4 源文件stm32f4xx_hal_rcc.c
這個文件主要是實現內部和外部時鍾(HSE、HSI、LSE、LSI、PLL、CSS、MCO)以及總線時鍾(SYSCLK、AHB1、AHB2、AHB3、APB1)的配置。
學習這個文件注意事項:
1、 系統上電復位后,通過內部高速時鍾HSI運行(主頻16MHz),Flash工作在0等待周期,所有外設除了SRAM、Flash、JTAG 和 PWR,時鍾都是關閉的。
- AHB和APB總線無分頻,所有掛載這兩類總線上的外設都是以HSI頻率運行。
- 所有的GPIO都是模擬模式,除了JTAG相關的幾個引腳。
2、 系統上電復位后,用戶需要完成以下工作:
- 選擇用於驅動系統時鍾的時鍾源。
- 配置系統時鍾頻率和Flash設置。
- 配置分頻器。
- 使能外設時鍾。
- 配置外設時鍾源,部分外設的時鍾可以不來自系統時鍾(I2S, RTC, ADC, USB OTG FS/SDIO/RNG)。
RCC局限性:
使能了外設時鍾后,不能立即操作對應的寄存器,要加延遲。不同外設延遲不同:
- 如果是AHB的外設,使能了時鍾后,需要等待2個AHB時鍾周期才可以操作這個外設的寄存器。
- 如果是APB的外設,使能了時鍾后,需要等待2個APB時鍾周期才可以操作這個外設的寄存器。
當前HAL庫的解決方案是在使能了外設時鍾后,再搞一個讀操作,算是當做延遲用。
比如下面使能GPIOA的時鍾:
#define __HAL_RCC_GPIOA_CLK_ENABLE() do { \ __IO uint32_t tmpreg = 0x00U; \ SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\ /* Delay after an RCC peripheral clock enabling */ \ tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\ UNUSED(tmpreg); \ } while(0U)
- 關於時鍾方面的知識點補充
1、正確理解PCLK1,2和HCLK對應哪些總線的時鍾,下面一張圖可以說明問題:
由上圖可以得出:
PCLK1、PC對應的是APB總線APB1,APB2時鍾。
HCLK對應的AHB總線。
2、內部和外部時鍾配置:
- HSI (high-speed internal)
高速內部RC振盪器,可以直接或者通過PLL倍頻后做系統時鍾源。缺點是精度差些,即使經過校准。
- LSI (low-speed internal)
低速內部時鍾,主要用於獨立看門狗和RTC的時鍾源。
- HSE (high-speed external)
高速外部晶振,可接4 - 26z的晶振,可以直接或者通過PLL倍頻后做系統時鍾源,也可以做RTC的是時鍾源。
- LSE (low-speed external)
低速外部晶振,主要用於RTC。
- CSS (Clock security system)
時鍾安全系統,一旦使能后,如果HSE啟動失敗(不管是直接作為系統時鍾源還是通過PLL輸出后做系統時鍾源),系統時鍾將切換到HSI。如果使能了中斷的話,將進入不可屏蔽中斷NMI。
- MCO1 (micro controller clock output)
可以在PA8引腳輸出SYSCLK、PLLI2SCLK、HSE和PLLCLK。
- MCO2 (micro controller clock output)
可以在PC9引腳輸出LSE、HSE、HSI和PLLCLK。
- PLL鎖相環,時鍾輸入來自HSI , HSE 或者CSI
16.4.1 函數HAL_RCC_DeInit
函數原型:
__weak HAL_StatusTypeDef HAL_RCC_DeInit(void) { return HAL_OK; }
函數描述:
文件stm32f4xx_hal_rcc.c里面的此函數是空的(做了__weak弱定義,方便用戶在其它文件里面重定義),ST將具體實現放在了stm32f4xx_hal_rcc_ex.c里面的此函數里面
此函數用於RCC復位函數,主要實現如下功能:
- HSI 打開作為系統時鍾。
- HSE和PLL關閉。
- AHB, APB1和APB2總線無分頻 。
- CSS, MCO1 和 MCO2 關閉。
- 所有中斷關閉。
注意事項:
- 此函數不會修改外設時鍾,LSI、LSE和RTC時鍾。
使用舉例:
此函數的使用比較簡單,需要調用的時候直接調用即可。
16.4.2 函數HAL_RCC_OscConfig
函數原型:
函數描述:
通過上面函數原型,我們可以一目了然的看出此函數的作用,配置了HSE、HSI、LSI、LSE和PLL。
函數參數:
- 函數的形參是RCC_OscInitTypeDef類型結構體變量,這個結構體的定義如下(主要是HSE、HSI、LSI、LSE和PLL的配置變量):
/** * @brief RCC Internal/External Oscillator (HSE, HSI, LSE and LSI) configuration structure definition */ typedef struct { uint32_t OscillatorType; uint32_t HSEState; uint32_t LSEState; uint32_t HSIState; uint32_t HSICalibrationValue; uint32_t LSIState; RCC_PLLInitTypeDef PLL; }RCC_OscInitTypeDef;
注意事項:
- LSE Bypass 切換到 LSE On 或者 LSE On切換到 LSE Bypass都不支持,用需要先關閉LSE,然后才可以切換到LSE Bypass 或者LSE On。
- HSE Bypass 切換到 HSE On 或者 LSE On切換到 LSE Bypass都不支持,用需要先關閉HSE,然后才可以切換到HSE Bypass 或者HSE On。
使用舉例:
RCC_OscInitTypeDef RCC_OscInitStruct; /* 使能HSE,並選擇HSE作為PLL時鍾源 */ 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 = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(__FILE__, __LINE__); }
16.4.3 函數HAL_RCC_ClockConfig
函數原型:
函數描述:
通過上面函數原型,我們可以一目了然的看出此函數的作用,配置了HCLK、SYSCLK、PLCK1和PLCK2。
函數參數:
- 第1個參數是RCC_ClkInitTypeDef類型的結構體變量。
- 第2個參數是Flash的延遲設置。
- 返回值,返回HAL_ERROR表示參數錯誤,HAL_OK表示發送成功,HAL_BUSY表示忙,正在使用中。
注意事項:
- 此函數會更新全局變量SystemCoreClock的主頻值,並且會再次調用函數HAL_InitTick更新系統滴答時鍾,這點要特別注意。
- 系統上電復位或者從停機、待機模式喚醒后,使用的是HSI作為系統時鍾。以防使用HSE直接或者通過PLL輸出后做系統時鍾時失敗(如果使能了CSS)。
- 目標時鍾就緒后才可以從當前的時鍾源往這個目標時鍾源切換,如果目標時鍾源沒有就緒,就會等待直到時鍾源就緒才可以切換。
- 根據設備的供電范圍,必須正確設置D1CPRE[3:0]位的范圍,防止超過允許的最大頻率。
使用舉例:
RCC_ClkInitTypeDef RCC_ClkInitStruct; HAL_StatusTypeDef ret = HAL_OK; /* 選擇PLL的輸出作為系統時鍾 HCLK = SYSCLK / 1 (AHB1Periph) PCLK2 = HCLK / 2 (APB2Periph) PCLK1 = HCLK / 4 (APB1Periph) */ 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; /* 此函數會更新SystemCoreClock,並重新配置HAL_InitTick */ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(__FILE__, __LINE__); }
16.4.4 函數HAL_RCC_MCOConfig
函數原型:
void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) { GPIO_InitTypeDef GPIO_InitStruct; /* Check the parameters */ assert_param(IS_RCC_MCO(RCC_MCOx)); assert_param(IS_RCC_MCODIV(RCC_MCODiv)); /* RCC_MCO1 */ if(RCC_MCOx == RCC_MCO1) { /* 省略未寫 */ } else { /* 省略未寫 */ } }
函數描述:
此函數的作用是配置MCO1(PA8引腳)和MCO2(PC9引腳)的時鍾輸出以及選擇的時鍾源,通過下面的截圖可以很好的說明此函數的作用:
函數參數:
1、 第1個形參用於選擇輸出的引腳,可選擇RCC_MCO1(PA8引腳)或者RCC_MCO2(PC9引腳)。
2、 第2個形參用於選擇輸出的時鍾源,MCO1可選擇的時鍾源如下:
- RCC_MCO1SOURCE_HSI
- RCC_MCO1SOURCE_LSE
- RCC_MCO1SOURCE_HSE
- RCC_MCO1SOURCE_PLLCLK
MCO2可選擇的時鍾源如下:
- RCC_MCO2SOURCE_SYSCLK
- RCC_MCO2SOURCE_PLLI2SCLK
- RCC_MCO2SOURCE_I2SCLK
- RCC_MCO2SOURCE_HSE
- RCC_MCO2SOURCE_PLLCLK
3、 第3個參數用於設置輸出分頻,范圍從RCC_MCODIV_1到RCC_MCODIV_4。
使用舉例:
此函數的使用比較簡單,需要在MCO引腳輸出時鍾的時候,直接調用即可。
16.4.5 RCC相關函數
函數原型:
void HAL_RCC_EnableCSS(void); void HAL_RCC_DisableCSS(void); uint32_t HAL_RCC_GetSysClockFreq(void); uint32_t HAL_RCC_GetHCLKFreq(void); uint32_t HAL_RCC_GetPCLK1Freq(void); uint32_t HAL_RCC_GetPCLK2Freq(void); void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct); void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency);
剩下的這些函數都比較簡單了,我們這里就不做講解了。
16.5 源文件stm3f4xx_hal_cortex.c
這個庫文件主要功能是NVIC,MPU和Systick的配置。此文件有個臃腫的地方,里面的API其實就是將ARM的CMSIS庫各種API重新封裝了一遍。這么做的好處是保證了HAL的API都是以字母HAL開頭。
更多NVIC相關知識需要大家看第xx章節(注:后面做到這個章節時補上)。
更多SysTick相關知識需要大家看第xx章節。
更多MPU相關知識需要大家看第xx章節。
16.5.1 NVIC相關函數
函數原型:
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup) void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority) void HAL_NVIC_EnableIRQ(IRQn_Type IRQn) void HAL_NVIC_DisableIRQ(IRQn_Type IRQn) void HAL_NVIC_SystemReset(void) uint32_t HAL_NVIC_GetPriorityGrouping(void) void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority) void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn) uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn) void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn) uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn)
這些函數的操作就比較容易了,這里就不做講解了,用到時調用即可。
16.5.2 SysTick相關函數
函數原型:
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb) void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource) void HAL_SYSTICK_IRQHandler(void) __weak void HAL_SYSTICK_Callback(void)
這些函數的操作就比較容易了,這里就不做講解了,用到時調用即可。
16.5.3 函數HAL_MPU_ConfigRegion
函數原型:
void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init) { /* 部分省略未寫 */ /* Set the Region number */ MPU->RNR = MPU_Init->Number; if ((MPU_Init->Enable) != RESET) { /* 部分省略未寫 */ MPU->RBAR = MPU_Init->BaseAddress; MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) | ((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) | ((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) | ((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) | ((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) | ((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) | ((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) | ((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) | ((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos); } else { MPU->RBAR = 0x00; MPU->RASR = 0x00; } }
此函數在本教程第xx章有專門的講解(注:后面做到這個章節時補上)。
16.6 總結
本章節就為大家講解這么多,對於一些常用的函數,望大家務必要掌握。