為了使工程更加有條理,我們把 LED 燈控制相關的代碼獨立分開存儲,方便以后移植。
在“工程模板”之上新建“ bsp_led.c”及“ bsp_led.h”文件,其中的“ bsp”即 Board
Support Packet 的縮寫(板級支持包),這些文件也可根據您的喜好命名,這些文件不屬於
STM32 標准庫的內容,是由我們自己根據應用需要編寫的。
在學習過程中,經常看到有人問這樣一個問題,為什么下面的時鍾初始化可以用按位或(|)的方式。其實這里就是在於ST底層庫的實現,需要我們靈活運用C語言。
void LED_GPIO_Config(void) { /*定義一個GPIO_InitTypeDef類型的結構體*/ GPIO_InitTypeDef GPIO_InitStructure; /*開啟LED相關的GPIO外設時鍾*/ RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK| LED2_GPIO_CLK| LED3_GPIO_CLK, ENABLE); //這里可以用 | 的方式,因為底層庫寄存器配置是個uint32_t的寄存器,可以多位同時操作 /*選擇要控制的GPIO引腳*/ GPIO_InitStructure.GPIO_Pin = LED1_PIN; /*設置引腳模式為輸出模式*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; /*設置引腳的輸出類型為推挽輸出*/ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /*設置引腳為上拉模式*/ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; /*設置引腳速率為2MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; /*調用庫函數,使用上面配置的GPIO_InitStructure初始化GPIO*/ GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure); //有了上面的 | 配置思路之后,我們在想,下面這樣復用的代碼能否可以也通過 | 的方式呢?
//答案是否定的,這里的寄存器配置是個GPIO_TypeDef*的類型,用 | 操作已然不合適。 /*選擇要控制的GPIO引腳*/ GPIO_InitStructure.GPIO_Pin = LED2_PIN; GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure); /*選擇要控制的GPIO引腳*/ GPIO_InitStructure.GPIO_Pin = LED3_PIN; GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure); /*關閉RGB燈*/ LED_RGBOFF; }
或許還有疑問就是為什么后面的LED2,3不用再配置模式那些,這其實還是屬於c語言問題,在我們三個IO口都是相同模式選擇的情況下,我們可以只改變結構體中控制引腳的部分,其他部分保留,但是如果有引腳的對應模式需要改變,那就不能這樣了。
STM32 標准庫補充知識
1. SystemInit 函數去哪了?
在前幾章我們自己建工程的時候需要定義一個 SystemInit 空函數,但是在這
STM32 標准庫的工程卻沒有這樣做, SystemInit 函數去哪了呢?
這個函數在 STM32 標准庫的“ system_stm32f4xx.c”文件中定義了,而我們
經包含該文件。標准庫中的 SystemInit 函數把 STM32 芯片的系統時鍾設置成了
即此時 AHB1 時鍾頻率為 180MHz, APB2 為 90MHz, APB1 為 45MHz。當 ST
電后,執行啟動文件中的指令后,會調用該函數,設置系統時鍾為以上狀態 。
2.斷言
斷言一般用在調試程序的時候使用,ST雖然在庫函數中有斷言,但是默認是沒有開啟的,需要定義一個宏。
除了啟用這個宏之外,我們還要在外部定義一個asset_failed函數,因為這個函數在這里只有聲明。這些都在conf.h頭文件中。FILE LINE這種,是預處理宏,不需要頭文件支持,是c編譯器具備的。
3.防止重復包含