---
# System prepended metadata

title: STM32 VSCode 開發環境建置
tags: [STM32]

---

# STM32 VSCode 開發環境建置

STM32是業界廣為人知，市佔率極高的微控制器，擁有完整的產品線，能夠找到適合的型號並應用在不同場景下的裝置中。雖說名聲遠播，但其開發流程較新手友善的Arduino平台複雜許多，較適合已經對微控制器有概念的人學習使用。本篇文章將使用強大的VSCode, MSYS2與神奇的STM32CubeMX，讓大家能夠建立起編譯、除錯與燒錄的環境，並開始撰寫第一支程式！

## 先下載幾樣東西

1. [Vistual Studio Code](https://code.visualstudio.com/Download)
相信有寫過程式的人都會知道大名鼎鼎的VSCode。
2. [MSYS2](https://www.msys2.org/)
MSYS2提供使用者一個類Linux的環境去安裝各種開發工具包或套件，本教學有許多的開發套件就是透過這套工具去完成的。
3. [STM32CubeMX](https://www.st.com/en/development-tools/stm32cubemx.html)
CubeMX是一套很神奇的軟體，他能夠為使用者建立最最最基本的STM32程式，並且能夠透過友善的介面去開啟或關閉某些硬體功能(UART, ADC, CAN等)，無須使用者去操作很多基本但是複雜的設定。
4. [STM32CubeProgrammer](https://www.st.com/en/development-tools/stm32cubeprog.html)
CubeMX是一個專門燒錄的程式，能夠將編譯出來的.hex檔等透過STLink燒錄進MCU中

## VSCode安裝

在你將VSCode安裝完後(這應該不用教吧🤌)，需要再VSCode內安裝額外的擴充功能，以利後續開發更順利！

在頁面的左邊欄目找到Extension的分頁，並且安裝以下有列出的延伸模組
![image](https://hackmd.io/_uploads/BykEmD0YC.png)

* 一定一定要安裝的延伸模組！！
    * 【Microsoft】C/C++
    * 【Microsoft】C/C++ Extenstion Pack
    * 【Microsoft】C/C++ Themes
    * 【Microsoft】Makefile Tools
    * 【Microsoft】IntelliCode
    * 【marus25】Cortex-debug
* 必須推坑你安裝的延伸模組
    * 【Liviu Schera】Noctis (超級讚讚的佈景主題)
* 有語言障礙的人一定要裝的延伸模組ouo
    * 【Microsoft】Chinese Traditional Language Pack

裝好之後大概會有這些
![image](https://hackmd.io/_uploads/rJZnLPCKC.png)
![image](https://hackmd.io/_uploads/rynewPAtC.png)
![image](https://hackmd.io/_uploads/ryNA8w0KA.png)
![image](https://hackmd.io/_uploads/Hy5yvvRtR.png)
![image](https://hackmd.io/_uploads/Byf7Dv0F0.png)

## MSYS2安裝

先照著官網的步驟將MSYS2安裝好，注意！只需要安裝完以下圖片內的步驟，更下面的就先不用。
![image](https://hackmd.io/_uploads/ryveuwCK0.png)

### 理解MSYS2的不同開發環境

在MSYS2安裝完後，你應該會在開始功能表看到許多的MSYS2選項。這些程式點進去的話你會發現，就是看似沒有不同的終端機，其實真的沒那麼簡單，~~我也是第二年重新撰寫這篇文章時才弄懂~~，這解釋起來真的很複雜，所以可以參考官網的[這篇文章](https://www.msys2.org/docs/environments/)去了解不同終端機之間的差異。
![image](https://hackmd.io/_uploads/rJjuOP0F0.png)

### 先來更新已經安裝的套件包

打開MSYS2 MINGW64的終端機，並輸入以下指令更新套件包。
```
$ pacman -Syu
```
![image](https://hackmd.io/_uploads/HJ3Onw0tC.png)

### 下載mingw套件包

```
$ pacman -S mingw-w64-x86_64-gcc
```
![image](https://hackmd.io/_uploads/By0oEugq0.png)

### 下載make套件包

以下兩者都需要
```
pacman -S mingw-w64-x86_64-make
pacman -S make
```
![image](https://hackmd.io/_uploads/B1O3Ede9C.png)

### 下載openocd套件包

```
pacman -S mingw-w64-x86_64-openocd
```
![image](https://hackmd.io/_uploads/By-6Ede5A.png)

### 下載arm-none-eabi套件包

```
pacman -S mingw-w64-x86_64-arm-none-eabi-gcc
```
![image](https://hackmd.io/_uploads/S16TE_g50.png)

### 下載gdb-multiarch套件包
:::info
gdb-multiarch套件包是為了取代原本arm-none-eabi套件包裡應該要有的arm-none-eabi-gdb.exe，不知道為什麼從MSYS2下載的arm-none-eabi套件包會少了它QQ。
:::

```
pacman -S mingw-w64-x86_64-gdb-multiarch
```
![image](https://hackmd.io/_uploads/B1L0V_xcA.png)


## 設定環境變數

這個步驟非常的重要，沒設定好後面都不用玩。
環境變數可以讓你不用cd一堆路徑到特定的資料夾就能執行裡頭的執行檔。

### 編輯環境變數

1. Windows+R並輸入sysdm.cpl開啟系統內容頁面

![image](https://hackmd.io/_uploads/r1_ly_Rt0.png)

2. 點選進階分頁再點選環境變數

![image](https://hackmd.io/_uploads/H17zyO0YR.png)

3. 編輯使用者變數裡的Path

![image](https://hackmd.io/_uploads/HJFBg_AK0.png)

4. 新增以下幾個環境變數並儲存就好囉
```
C:\msys64\mingw64\bin
C:\msys64\mingw64\include
C:\msys64\usr\bin
```
![image](https://hackmd.io/_uploads/ryNjg_AY0.png)

### 驗證環境變數

1. Windows+R並輸入PowerShell開啟PowerShell

![image](https://hackmd.io/_uploads/B1Na-O0YC.png)
![image](https://hackmd.io/_uploads/S1l1G_0YC.png)

2. 複製貼上以下指令到終端機並鍵入

```
gcc --version 
make --version
openocd --version
arm-none-eabi-gcc --version
```
應該要看到以下的畫面，但因為工具會隨著時間更新，所以版本編號可能會不一樣。如果都沒有出現任何錯誤的話，那環境變數的設定應該就沒問題了！整體編譯環境的安裝也大致上告一個段落了！！！👏🏼

![image](https://hackmd.io/_uploads/rydwMu0KC.png)

# 從0開始的第一個STM32專案

安裝完基本的開發工具後，我們可以建立一個新的專案來測試看看，環境是否都運作正常！

## 使用STM32CubeMX建立基本程式碼

STM32CubeMX是一個由ST官方提供的軟體，能夠用親民的圖形化介面去開關微控制器的各種功能，像GPIO, Timer, Interrupt, DAC, ADC等都可以，省去使用者要找到特定底層函式去開關功能。本教學將使用ST官方的開發版Nucleo L432KC做為示範。

1. 開啟STM32CubeMX並點擊Board Selector
:::info
本教學使用的是開發版，所以選擇BOARD SELECTOR，若讀者日後已經進階到能將微控制器直接焊接在自己設計的電路板上，那就能直接選擇MCU SELECTOR建立基本程式碼。
:::
![](https://i.imgur.com/NRXGCUM.png)


2. 搜尋欄打上L432KC並雙擊選取NUCLEO L432KC的開發版

![](https://i.imgur.com/ai9Da1F.png)

3. 點選Yes將開發版上的Peripherals設為預設值
:::info
這裡的Peripherals指的是像LED或STLink這種已經設計在開發版上方便讓使用者用的周邊裝置，點擊Yes就能幫你把這些東西進行基本的初始化。
:::

![](https://i.imgur.com/mBSp1Vd.png)

4. Pinout & Configuration分頁
在進到這個頁面後你能夠去設定許多的參數，~~這就讓你慢慢去摸索就好~~。前面提到，我們是使用開發版，剛剛也點擊了Yes，所以你可以看到畫面上PB3腳位已經設定為GPIO的輸出腳(有著別名LD3)，這支PB3腳位就是連接到開發版上的LED。接著我們就使用這顆LED進行測試，不再額外設定其他晶片的功能了。

![](https://i.imgur.com/8zTJNJd.png)

5. Project Manager分頁
最主要需要設定的東西都在Project Setting的區塊內。將Project Name更改為想要的專案名稱；Projejct Location改為專案要存放的地方；Toolchain/IDE設定為 **Makefile**。都設定好後就可以點擊靠近右上角的**GENERATE CODE**產生程式碼。

![](https://i.imgur.com/spTOfO0.png)

6. 開啟你剛剛設定的專案存放的資料夾，如果長的類似像這樣的話，那就沒問題囉！

![](https://i.imgur.com/ws5gNU4.png)

## 使用VSCode來進行開發！
接著可以利用VSCode來撰寫程式碼，**不過要先配置一些組態以利程式碼的撰寫**，最後就可以燒錄。
另外，燒錄程式進STM32裡主要有兩種方法：
1. 使用make編譯後使用CubeProgrammer燒錄
2. 使用cortex-debug與openocd進行**連線除錯**
:::info
連線除錯有很多優點，像是可以在過程中設定斷點監看變數或逐行執行，讓你更好的找到問題點，~~白話就是抓臭蟲在哪啦~~。還有，連線除錯在關閉後程式其實也持續留在微控制器上，所以我也把它歸類為一種燒錄方法
:::

### 配置C/C++環境組態
1. 打開VSCode並開啟專案所在的資料夾，並點開main.c。

![image](https://hackmd.io/_uploads/rJSQSYCtA.png)

2. 在專案的任何一個過程中，右下角若有來自makefile擴充功能的提示可以進行\--dry-run，務必要點選Yes。\--dry-run會將整份專案的細節傳送給IntelliSense，能夠協助你在寫程式的時候有更多的自動完成選項；不過最主要是IntelliSense能夠更好的辨認各函式在哪些地方，~~才不會出現一堆紅底線錯誤來騷擾你~~。

![image](https://hackmd.io/_uploads/Hy-SHOgcR.png)

3. 點擊視窗右下角的Win32方塊，這裡可以設定我們要用的C/C++環境組態。

![image](https://hackmd.io/_uploads/SJtciey9R.png)

4. 點擊Edit Configurations(UI)。

![image](https://hackmd.io/_uploads/SJdxne1qC.png)

5. 此時會看到一個設定頁面。

![image](https://hackmd.io/_uploads/ByiHngk50.png)

6. 在Configuration name裡新增一個Configuraiton "STM32"

![image](https://hackmd.io/_uploads/B105hxk5C.png)

7. 將Compiler path改為以下位置

```
C:\msys64\mingw64\bin\arm-none-eabi-gcc.exe (如果你安裝MSYS2的時候沒亂動😉)
```
![image](https://hackmd.io/_uploads/SyuM6lycR.png)

8. 將IntelliSense mode改為windows-gcc-arm

![image](https://hackmd.io/_uploads/Byz2pe1cA.png)

9. C/C++組態設定就大致完成囉，~~IntelliSense大概不會耍智障了~~。不過，順帶一提IncludePath的重要性，如果今天有些.c檔或.h檔IntelliSense找不到，可以在Include path裡新增檔案位置，讓系統去知道你東東放哪兒。

![image](https://hackmd.io/_uploads/By4BCx1q0.png)


### 利用make編譯後使用STM32CubeProgrammer燒錄
1. 打開VSCode並開啟專案所在的資料夾，並點開main.c。

![image](https://hackmd.io/_uploads/rJSQSYCtA.png)

2. 當完成程式的撰寫後，在專案資料夾內開啟終端機並輸入第一行指令進行編譯。假設你覺得編譯出來的東西有問題，或是想要強制的重新編譯，你也可以輸入第二行指令清除之前產生的編譯資料後，再重新執行第一行。
```
$ make -j 22
$ make clean
```
若編譯成功，應該會看到終端機有提示產生了 `.bin` `.elf` `.hex`。
![image](https://hackmd.io/_uploads/Sk168KRtC.png)
:::warning
make指令會根據makefile去將整個檔案編譯出來並產生可執行檔，若之後有新增.c與.h檔，務必要記得去makefile裡新增要被編譯的檔案。另外-j 22 是指定用22個核心去進行編譯，這對於大檔案會很有幫助，若電腦CPU核心/線程數較少，請修改合適的數值。
:::

3. 再次編譯完後檢查是否有產生可執行檔 `.bin` `.elf` `.hex`。
:::info
可執行檔會在build資料夾裡
:::
![image](https://hackmd.io/_uploads/B1DrDtCYC.png)


4. 接著打開STM32CubeProgrammer。

![image](https://hackmd.io/_uploads/H1cxHeyq0.png)

5. 點選靠近左上角的Open file分頁，並選擇剛剛編譯出來的三個檔案中的任一個(通常會選.hex)。

![image](https://hackmd.io/_uploads/B1sFrg1cR.png)

6. 將STM32開發版接上電腦，並點擊右上角的Connect連線到裝置(連線上的話會顯示Connected)。

:::warning
如果今天不是開發版，而是你自己設計的控制板，那記得3.3V電源要供應給STM32，不然會連不上。
:::
![image](https://hackmd.io/_uploads/BJkyDey9R.png)

7. 再次確認剛剛選的是正確的韌體後，就能夠按下Download將可執行檔燒錄進STM32裡。

![image](https://hackmd.io/_uploads/rkh2wgJcA.png)


### 使用cortex-debug與openocd抓臭蟲
1. 打開VSCode並開啟專案的資料夾。

![image](https://hackmd.io/_uploads/rkojuxy9A.png)

2. 接著在.vscode資料夾裡新增settings.json並在裡頭新增以下，指定gcc與gdb的位置。
:::info
這裡的gdbPath.windows與armToolchainPath.windows也可以再新增一個.linux的配置，讓雙平台同時開發時能吃到不同的設定路徑。
:::
```
{
    "cortex-debug.gdbPath.windows": "C:/msys64/mingw64/bin/gdb-multiarch.exe",
    "cortex-debug.armToolchainPath.windows": "C:/msys64/mingw64/bin/"
}
```
![image](https://hackmd.io/_uploads/SkTE6T1qC.png)

3. 接著一樣在.vscode資料夾裡新增launch.json並在裡頭新增以下除錯組態。
```
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Cortex Debug", //可以自訂除錯組態的名稱
            "cwd": "${workspaceFolder}",
            "executable": "${workspaceFolder}/build/executable.elf", //改為make後的.elf檔位置
            "request": "launch",
            "type": "cortex-debug",
            "servertype": "openocd",
            "device": "STM32L432KC", //更改為使用的晶片型號
            "windows":{
                "configFiles": [
                    "C:/msys64/mingw64/share/openocd/scripts/interface/stlink.cfg",
                    //因為使用STLink進行除錯，所以使用stlink.cfg檔
                    "C:/msys64/mingw64/share/openocd/scripts/target/stm32l4x.cfg",
                    //因為使用STM32L432KC的晶片，所以使用stm32l4x.cfg
                    //**需要根據需求修改成像：stm32f4x.cfg**
                ],
            },
            "preLaunchCommands": ["make -j 22"], //這行會讓除錯前重新在編譯一次
        }
    ]
}
```

4. 將開發版連接到電腦。如果是自己設計的電路板，那就是使用STLink把STM32連接到電腦。

![image](https://hackmd.io/_uploads/rkHnYBlq0.jpg)

5. 點擊左列有蟲的擴充功能符號切換到偵錯的分頁(Run and Debug)，並且再點擊播放鍵(Start Debugging)開始除錯。

![image](https://hackmd.io/_uploads/BJhIcSeq0.png)

6. 這時候應該會看到終端機出現下列資訊，並且開發版上的LED燈開始紅綠交替閃爍。

![image](https://hackmd.io/_uploads/ryDXhSe9R.png)
![image](https://hackmd.io/_uploads/rk8KhSg90.png)

7. 此時畫面中也可以看到以下功能方塊。

:::info
這個方塊就是用來控制程式的執行狀態，有重啟、暫停/繼續、不進入函式、逐行執行、結束的功能，能夠讓你知道程式是怎麼運行的又或是進一步分析錯誤出在哪。
:::
![image](https://hackmd.io/_uploads/Hy3Ahrx9R.png)

8. 此時程式也已經燒錄進去並且正以除錯模式執行，**除錯模式終止後在RESET一次裝置，程式就跟使用STM32CubeProgrammer燒錄進去的一樣能用**。

### 設定斷點讓程式自動暫停並監看變數

1. 在進到除錯模式後，我們可以在程式的任一行新增一個斷點。~~任一行有時候也不是那麼的任意~~

![image](https://hackmd.io/_uploads/HkjbWLlcR.png)


2. 接著你會發現程式會在執行到那裡的時候自動暫停，等著你去進行操作。黃色的那一行就是目前程式所在的位置，**而該行尚未被執行**。

![image](https://hackmd.io/_uploads/S1Png8lcC.png)


3. 此時你可以從畫面的左側了解目前暫停狀態下的全域與區域變數的狀態(它的數值)，並且也可以將重要的變數加進Live Watch裡，讓你更容易的找到你關注的資料。

![image](https://hackmd.io/_uploads/HyBjZ8lq0.png)

4. 剩餘的除錯細節就留給你慢慢摸索囉。

# 遇到問題嗎？
Author: William Lin
Mail：unrealin@gmail.com
GitHub：unrealin01

# 改版紀錄

| Version | Release Date | Comment                                            |
| ------- | ------------ | -------------------------------------------------- |
| v1.0    | 2022.05.30   | 首次學習STM32用以紀錄                                 |
| v2.0    | 2024.07.30   | 因應軟體包更新而修正教學與簡化安裝流程，並公開發表          |
| v2.1 Pre| 2025.11.24   | 相關細節待補充(發現相關Bug)                            |

###### tags: `STM32`