CubeIDE Note 03: Lesson 1. Basic I/O Setting And Application for LL Library

Hsueh-Ju Wu 吳學儒
STM32CubeIDE
Published in
13 min readJun 2, 2021

教學

如何使用 CubeIDE 設定 GPIO (General Purpose Input/Output, GPIO)腳位及基本應用

環境

本文使用
OS: Windows x64
STM32CubeIDE Version: 1.6.1
開發板: NUCLEO-F334R8(STM32F334R8)
Low-Layer (LL) Library

教學文章列表

參考資料

UM2570. Description of STM32G4 HAL and low-layer drivers

https://www.st.com/resource/en/user_manual/dm00610707-description-of-stm32g4-hal-and-lowlayer-drivers--stmicroelectronics.pdf

RM0364. STM32F334xx advanced Arm®-based 32-bit MCUs

https://www.st.com/resource/en/reference_manual/dm00093941-stm32f334xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

UM1735. Discovery kit for STM32F3 series with STM32F334C8 MCU

https://www.st.com/resource/en/user_manual/dm00108524--discovery-kit-for-stm32f3-series-with-stm32f334c8-mcu-stmicroelectronics.pdf

General Purpose Input/Output (GPIO) — 成大資工wiki

http://wiki.csie.ncku.edu.tw/embedded/GPIO

STM32 BSRR寄存器和BRR寄存器 — CSDN

https://blog.csdn.net/m0_38139533/article/details/86606090

STM32 GPIO 配置之ODR, BSRR, BRR 详解-CSDN

https://blog.csdn.net/m0_38139533/article/details/86606090

Section 1. 基本題

使用以下三種方式來GPIO達成I/O腳位之高/低電位輸出。

Methods:

(i) LL Library Function
LL_GPIO_SetOutputPin(GPIO_TypeDef * GPIOx, uint32_t PinMask)
LL_GPIO_ResetOutputPin(GPIO_TypeDef * GPIOx, uint32_t PinMask)

(ii) LL Library Funciton
LL_GPIO_TogglePin(GPIO_TypeDef * GPIOx, uint32_t PinMask)

(iii) 直接寫入暫存器
GPIOx->BSRR
GPIOx->BRR

撰寫程式碼,量測GPIO PA4之訊號使其呈現以下數據。

(a) 使用(i)達成 Freq = 1kHz, Period =1ms
(b) 使用(ii)達成 Freq = 2kHz, Period = 500us
(c) 使用(iii)達成 Freq = 8kHz, Period = 125us

Section 1.1 CubeMX 設定

Step 1. 請先按照此篇教學(選對開發板)做好基礎設定

Step 2. 把需要的IO Pin腳設定好

在 Pinout & Configuration 分頁,切換到 Pinout View在MCU圖上找到 PA4
左鍵點選打開選單,將其設定為 GPIO_Output

Step 3. 可切到 GPIO 項目,確認 Pin 腳設定細項

筆者在 Step 2. 也順便將進階題所要使用的腳位設定好了

GPIO 項目,確認 Pin 腳設定細項

Step 4. 切換到Project Manager修改函數庫設定

預設皆為 HAL庫
GPIO改為 LL
RCC維持 HAL不變

Project Manager修改函數庫設定

參考資料:關於 ST 各種函數庫之介紹(推薦閱讀)

Step 5. 按下上方黃色齒輪,即可產生程式框架

依照設定自動產生好的程式框架

範例 ioc檔案備份 (適用 STM32F334R8):
https://drive.google.com/file/d/1BON_hNiUkZyQMjJUERwU7oUvq-ENjnOZ/view?usp=sharing

Appendix. GPIO設定程式碼解析

打開 main.c程式,找到 MX_GPIO_Init()原代碼

Section 1.2 暫存器介紹

A. GPIO port input data register (GPIOx_IDR)

GPIO輸入狀態暫存器,可讀

GPIOx_IDR(RM3046. p.150)

B. GPIO port output data register (GPIOx_ODR)

GPIO輸出狀態暫存器,可讀可寫
官方建議不要寫入,由 BSRR或 BRR來做會更好

GPIOx_ODR(RM3046. p.151)

C. GPIO port bit set/reset register (GPIOx_BSRR)

GPIO 輸出 set /reset暫存器,可寫
寫 1才動作,寫 0 無動作(保持原樣)
Set (BS)優先權高於 Reset (BR)

D. GPIO port bit reset register (GPIOx_BRR) (x = A to D and F)

GPIO輸出 Reset暫存器,可寫
寫 1才動作,寫 0 無動作(保持原樣)

Section 1.3 程式碼撰寫

Step 1. 結構介紹

主程式通常都是寫在main.c的 int main(void)區塊中
初次撰寫有以下三點要注意:

A. 自己撰寫的程式碼,只有放在
/* USER CODE BEGIN x*/ 與 /* USER CODE END x*/
之間區塊,才不會在Generate Code時被覆寫掉

寫之前最好先確認清楚 Begin與 End之位置

B. /* USER CODE BEGIN x*/ 與 /* USER CODE END x*/ 標記無法自行新增

C. 只有放在while(1)區塊中的程式碼會無限執行

Step 2. 範例程式

LL_GPIO_WriteOutputPort 是對一個 GPIOx 全部 Pin 一起寫入 0 / 1

(a) 使用(i)達成 Freq = 1kHz, Period =1ms

(b) 使用(ii)達成 Freq = 2kHz, Period = 500us

(c) 使用(iii)達成 Freq = 8kHz, Period = 125us

PA4其實是第 5個 pin(從 PA0開始)

其實 LL函數庫的函數,就是把直接操作暫存器的步驟經過一層函數包裝

Step 3. 到此就可以把程式燒進去了

有用過 CodeComposer的同學,應該就可以發現接下來操作與其非常類似

A. 接上開發板,按下綠色蟲蟲

B. 然後就會看到這個錯誤提示視窗

C. 這是因為還沒設定 Debug 模式,按下Debug Configurations來設定

D. 只要選好 CubeIDE 預設好的 Debug 設定,按下 Debug 即可

STM32 Cortex-M C/ C++ Application 展開 選 “專案名 Debug”

E. 新板子的ST-Link 韌體可能是舊版,所以需要更新

按 OK

按下 Open in update mode

按下 Upgrade

等待跑完,視窗消失即可

F. 重新按下綠色蟲蟲,就可以看到熟悉的 Debug 介面
可以按上方的綠色執行鍵,讓程式開始 Run 了

如果遇到這個錯誤,只要拔掉板子重新接上即可

Step 4. 使用HAL_Delay()做delay

如果我們直接把上述程式燒進去開發板測試,
會發現週期完全不對,多1000倍出來,
這是因為HAL庫之HAL_Delay()函數,
在72M主頻且CubeMX自動產生的設定下,
HAL_Delay(1)為延時1ms,
我們要修正設定,將HAL_Delay(1)修改為1us

在 main.c 裡面的 int main()區塊裡找到這位置加上以下程式即可

Section 1.4 實驗結果

實際上測量出來的結果都跟我們預想的差了一點,
主因是Delay的精度問題

(a) 使用(i)達成 Freq = 1kHz, Period =1ms

(b) 使用(ii)達成 Freq = 2kHz, Period = 500us

(c) 使用(iii)達成 Freq = 8kHz, Period = 125us

Section 2. 進階題

將 PA4~PA7 等4腳位接LED燈,使用 PB10 作 Input,使用以下提示方法,完成本題目

可用Methods:

(i) LL Library Function
LL_GPIO_ReadInputPort(GPIO_TypeDef * GPIOx)

(ii) LL Library Funciton
LL_GPIO_IsInputPinSet(GPIO_TypeDef * GPIOx, uint32_t PinMask)

(iii) 直接讀取暫存器
GPIOx->IDR

當 PB10 接收低電位(0V)時,
4顆LED燈左右來回閃爍(跑馬燈),完成來回一次閃爍之時間為1秒;
當 PB10 接收高電位(3.3V)時,
4顆LED燈交替閃爍,每交替之時間間隔為0.5秒。

Section 2.1 程式碼撰寫

筆者提供比較簡短的寫法,不熟悉的同學也可以使用暴力解

如果是做完第一題接著做第二題的同學,記得註解掉以下代碼
不然會看到所有LED燈一起發光喔

Section 2.2 實驗結果

在影片中可看到將PB10拉高或拉低電位,可讓LED出現不同動作

--

--