[LibOpenCM3 × STM32教學-1] 用LibOpenCM3來開發STM32-LED閃爍範例

系列:LibOpenCM3 × STM32教學 Posted on 2021-11-26

我在 2022 年 9 月重新寫了與本文內容相近的文章,建議可以觀看新文章:

前言

LibOpenCM3 是一個 Open-Source(LGPL) 的 ARM Cortex-M3 微控制器底層硬體函式庫,支援包含 STM32、NXP LPC1000、Atmel SAM3U 等各種微控制器。

本篇文章將會示範如何以 LibOpenCM3 寫出可以在 STM32 上執行的 LED 閃爍程式。本文的程式也有一併放在 GitHub 上:ziteh/stm32-examples

正文

環境與專案

我使用的 IDE 為 PlatformIO IDE for VSCode(Visual Studio Code),並安裝了 ST STM32 Ver 15.0.0 平臺。有關 PlatformIO 的介紹可以看我寫的另一篇文章:[STM32學習記錄-6] 在VS Code與PlatformIO上開發STM32

安裝完相關軟體後就可以建立一個 PlatformIO 專案。我示範使用的開發板為「ST Nucleo-F103RB(STM32F103RB)」,並選擇「Framework」為「libopencm3」。

程式全文

在「src」資料夾中新增檔案「main.c」,並在加入以下的程式:

 1/**
 2 * @file   main.c
 3 * @brief  Blinking LED example.
 4 */
 5 
 6#include <libopencm3/stm32/rcc.h>
 7#include <libopencm3/stm32/gpio.h>
 8
 9#define RCC_LED_PORT (RCC_GPIOA)
10#define LED_PORT     (GPIOA)
11#define LED_PIN      (GPIO5)
12
13void delay(unsigned int value)
14{
15  while(value--)
16  {
17    __asm__("nop"); /* Do nothing. */
18  }
19}
20
21int main(void)
22{
23  /* Enable clock. */
24  rcc_periph_clock_enable(RCC_LED_PORT);
25
26  /* Configure GPIO as push-pull output and maximum speed of 2 MHz. */
27  gpio_set_mode(LED_PORT,
28                GPIO_MODE_OUTPUT_2_MHZ,
29                GPIO_CNF_OUTPUT_PUSHPULL,
30                LED_PIN);
31
32  /* Start blinking. */
33  while (1)
34  {
35    gpio_toggle(LED_PORT, LED_PIN); /* LED on/off. */
36    delay(500000);                  /* Wait a bit. */
37  }
38
39  return 0;
40}

程式說明

接下來會依序介紹各部分程式。

引入函式庫

1#include <libopencm3/stm32/rcc.h>
2#include <libopencm3/stm32/gpio.h>

就如同其它程式一樣,首先要做的是引入要用的 LibOpenCM3 函式庫。在本範例中需要用到 rcc.hgpio.h 這兩個檔案,因此將其引入。

其中 rcc.h 的「RCC」是「Reset and Clock Controller」的意思,基本上所有 STM32 的功能都與它有關,通常一定會用到。而 gpio.h 的「GPIO」當然就是「General-Purpose Input/Output」的意思,要控制 IO 接腳的話就會需要。

PlatformIO 在建立專案的時候就會依照設定來準備好 LibOpenCM3 的相關檔案了,因此不用另外下載和設定,直接打 #include 就可以了。

設定接腳

1#define RCC_LED_PORT (RCC_GPIOA)
2#define LED_PORT     (GPIOA)
3#define LED_PIN      (GPIO5)

因為每個開發板的板載 LED 腳位可能不同,因此透過 #define 的方式宣告要使用的腳位,這樣要修改腳位的話只要修改一個地方,會比較方便且不易出錯。

我使用的 Nucleo-F103RB 的板載 LED 位於「PA5」,因此需要設定 Port 與 Pin 為 GPIOAGPIO5。另外 RCC 也會需要 Port 的設定,因為一併設定一個 RCC_GPIOA

Delay 函數 delay()

1void delay(unsigned int value)
2{
3  while(value--)
4  {
5    __asm__("nop"); /* Do nothing. */
6  }
7}

這是一個最簡單的 Delay 函數,雖然它基本上無精準可言,但以本範例來說也不需要精確的定時。

其中 __asm__("nop") 代表的是嵌入組合語言「nop」指令,也就是無操作(No Operation)。

如果想要把 Delay 函數放在主程式 main() 之後,記得要宣告函數原型或使用標頭檔。

主程式 main()

 1int main(void)
 2{
 3  /* Enable clock. */
 4  rcc_periph_clock_enable(RCC_LED_PORT);
 5
 6  /* Configure GPIO as push-pull output and maximum speed of 2 MHz. */
 7  gpio_set_mode(LED_PORT,
 8                GPIO_MODE_OUTPUT_2_MHZ,
 9                GPIO_CNF_OUTPUT_PUSHPULL,
10                LED_PIN);
11
12  /* Start blinking. */
13  while (1)
14  {
15    gpio_toggle(LED_PORT, LED_PIN); /* LED on/off. */
16    delay(500000);                  /* Wait a bit. */
17  }
18
19  return 0;
20}
  • rcc_periph_clock_enable() 會致能特定功能的 Clock。在這裡我們啟用的是 RCC_LED_PORT,也就是先前用 #define 所設定的 LED 所在腳位的 Port(Port-A)的Clock。
  • gpio_set_mode() 會對指定的 GPIO 進行設定。
    • LED_PORT 是先前用 #define 所設定的 LED 所在腳位的 Port,也就是 Port-A。
    • GPIO_MODE_OUTPUT_2_MHZ 代表設定為輸出模式,且最高速度為 2 MHz。
    • GPIO_CNF_OUTPUT_PUSHPULL 代表使用推輓式(Push-Pull)輸出。關於推輓式的介紹可以看我之前的文章
    • LED_PIN 是先前用 #define 所設定的 LED 所在腳位的 Pin,也就是 Pin-5。可以使用 | 來同時選擇多個 Pin。
  • gpio_toggle() 會反轉指定的 GPIO 輸出,如果目前是輸出 High 的話就變成輸出 Low;如果現在是 Low 的話就變成 High。

結語

本次文章內介紹的程式我也有放在 GitHub 上,可以直接載下來並使用 PlatformIO 開始專案。

各位也可以參考 PlatformIO 所提供的範例

相關文章



留言可能不會立即顯示。若過了幾天仍未出現,請 Email 聯繫:)

comments powered by Disqus