【STM32】HAL庫點燈
- 一、探究目標
- 二、探究原理
- 2.1 ST開發庫
- 2.1.1 直接配置寄存器
- 2.1.2 標準外設庫
- 2.1.3 HAL庫
- 2.2 HAL開發
- 2.2.1 環境配置
- 2.2.2 時鐘配置
- 2.2.3 GPIO配置
- 2.2.4 工程創建
- 2.2.5 KEIL代碼
- 2.2.6 注意:加入核心文件stm32f10x_md.s
- 2.3 GPIO函數
- 三、代碼實現
- 3.1 實驗一
- 3.1.1 CubeMX配置
- 3.1.2 KEIL代碼
- 3.2 實驗二
- 3.2.1 CubeMX配置
- 3.2.2 KEIL代碼
- 3.3 KEIL仿真
- 四、探究總結
一、探究目標
-
了解并掌握HAL庫函數開發方法。安裝 stm32CubeMX,配合Keil,使用HAL庫方式完成下列任務:
1)重做上一個LED流水燈作業,用GPIO端口完成2只LED燈的周期閃爍。
2)接上,再用GPIO端某一管腳接2個開關(用杜邦線模擬代替)。采用中斷模式編程,當2分開關接高電平時,對應的兩個LED燈停止工作(即停止周期性閃爍),接低電平時,恢復工作。
-
在沒有示波器條件下,使用Keil的軟件仿真邏輯分析儀功能觀察LED管腳的時序波形,分析上面作業按鍵中斷時,LED燈的波形變化情況。
二、探究原理
2.1 ST開發庫
ST 為開發者提供了非常方便的開發庫,有標準外設庫(SPL庫)、HAL 庫(Hardware Abstraction Layer,硬件抽象層庫)、LL 庫(Low-Layer,底層庫)三種。前者是ST的老庫已經停更了,后兩者是ST現在主推的開發庫。
我們之前所使用的寄存器開發是最底層的開發方法,開發者可以參照ST公司的數據手冊迅速上手。HAL庫和LL
2.1.1 直接配置寄存器
我們之前所使用的寄存器開發是最底層的開發方法。在之前學習51的過程中,我們是通過匯編語言直接操作寄存器實現功能的,而這種方法到了STM32就不太容易行得通了,因為STM32的寄存器數量是51單片機的十數倍,如此多的寄存器根本無法全部記憶,開發時需要經常的翻查芯片的數據手冊,此時直接操作寄存器就變得非常的費力了。
但直接操作寄存器的方法更接近原理,而且適用性更廣泛,只要擁有數據手冊,什么芯片都可以直接上手。
2.1.2 標準外設庫
ST公司為每款芯片都編寫了一份庫文件,也就是工程文件里stm32F1xx…之類的。在使用過程中我們只需要配置結構體變量成員就可以修改外設的配置寄存器,從而選擇不同的功能。
標準庫同時也是目前最多人使用的方式,很多人的STM32啟蒙——江協科技也是用到標準庫教學的。
2.1.3 HAL庫
HAL(Hardware Abstraction Layer,抽象印象層)庫是ST公司目前主力推的開發方式。使用ST公司研發的STMcube軟件,可以通過圖形化的配置功能,直接生成整個使用HAL庫的工程文件,而無需像標準庫那樣配置文件,可以說是方便至極。
2.2 HAL開發
2.2.1 環境配置
環境配置可參考博客STM32_Cube MX配置及使用HAL庫
2.2.2 時鐘配置
在方框內輸入72,回車確認。
2.2.3 GPIO配置
由于我們LED所接引腳為PB9,因此我們需要將PB9引腳初始化為高電平輸出,即High。
2.2.4 工程創建
Generate后工程就創建成功啦,此時我們只需要open project就可以打開KEIL工程了。
2.2.5 KEIL代碼
在敲代碼的時候要注意,要把代碼卸載BEGIN和END之間,寫在外面的會在你操作cube生成代碼的時候被清理掉。
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
一個簡簡單單的LED燈閃爍就這樣寫好了。
2.2.6 注意:加入核心文件stm32f10x_md.s
我們可以將之前標準庫文件中的md.s文件復制粘貼到Drivers中,但是注意:如果更改cubeMX并generate文件都會把這個清除,需要重新添加。
2.3 GPIO函數
- HAL_GPIO_WritePin函數:寫入引腳高低電平
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{/* Check the parameters */assert_param(IS_GPIO_PIN(GPIO_Pin));assert_param(IS_GPIO_PIN_ACTION(PinState));if (PinState != GPIO_PIN_RESET){GPIOx->BSRR = GPIO_Pin;}else{GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;}
}
- HAL_GPIO_TogglePin函數:引腳電平翻轉
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{uint32_t odr;/* Check the parameters */assert_param(IS_GPIO_PIN(GPIO_Pin));/* get current Output Data Register value */odr = GPIOx->ODR;/* Set selected pins that were at low level, and reset ones that were high */GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
}
三、代碼實現
3.1 實驗一
用GPIO端口完成2只LED燈的周期閃爍。
這里用PB8、PB9輸出。
3.1.1 CubeMX配置
按照2.2的步驟操作配置好時鐘后,在GPIO選擇我們需要的引腳PB8、PB9。
初始化后我們可以觀察到,生成的gpio.c文件中,有如上代碼。
3.1.2 KEIL代碼
想要實現LED1、LED2周期閃爍,我們可以用翻轉電平操作。
由于初始LED1(PB9)高電平熄滅,LED2(LED8)低電平點亮。
加入延時函數,讓二者電平翻轉。
while (1){HAL_Delay(500);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}
3.2 實驗二
再用GPIO端某一管腳接2個開關(用杜邦線模擬代替)。采用中斷模式編程,當2分開關接高電平時,對應的兩個LED燈停止工作(即停止周期性閃爍),接低電平時,恢復工作。
3.2.1 CubeMX配置
配置輸入,假如兩個開關分別連引腳PA5\PA6。
將PA5、PA6選擇為GPIO_Input模式。
3.2.2 KEIL代碼
開關接高電平時LED滅,低電平時LED亮。
因此我們需要用到HAL_GPIO_ReadPin函數讀取開關的輸入電平。
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{GPIO_PinState bitstatus;/* Check the parameters */assert_param(IS_GPIO_PIN(GPIO_Pin));if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET){bitstatus = GPIO_PIN_SET;}else{bitstatus = GPIO_PIN_RESET;}return bitstatus;
}
因此主函數的代碼寫簡單幾句就能實現。
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define KEY1_State HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)
#define KEY2_State HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5)
/* USER CODE END PD */
/* USER CODE BEGIN WHILE */while (1){if(KEY1_State==GPIO_PIN_RESET){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);}if(KEY2_State==GPIO_PIN_SET){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);}/* USER CODE END WHILE */
3.3 KEIL仿真
四、探究總結
HAL庫開發只要熟悉函數,很容易就能進行開發。但是HAL庫的覆蓋程度有限,有些芯片并沒有HAL庫,因此掌握寄存器開發和標準庫開發還是很有必要的。
以上則是我本次探究的全部內容,如有錯漏請在評論區指正。