Keil MDK STM32系列(一) 基於標准外設庫SPL的STM32F103開發


Keil MDK STM32系列

概述

Windows下使用Keil MDK5進行stm32f103c8t6的開發和編譯, 配合ST-LINK工具進行燒錄, 使用標准外設庫SPL.

所需硬件

stm32f103系列開發板

stm32f103c8t6核心板

參數

  • ARM 32-bit Cortex-M3
  • 72 MHz maximum frequency
  • 20k ram, 64k flash 這是一個規格比較低的stm32芯片
  • LQFP封裝48pin

stm32f103vct6開發板

參數

  • ARM 32-bit Cortex-M3
  • 72 MHz maximum frequency
  • 48k ram, 256k flash
  • LQFP封裝100pin

st-link燒錄器

在燒錄程序到目標芯片以及Debug時需要使用, 自ST-Link V2以來的所有ST-LINK板都帶一個COMLED, 一般是紅綠兩色組合, 也有些是紅藍兩色, 兩色分別有常亮, 常滅, 閃爍等狀態. 不同狀態代表不同的含義:

  • 閃爍紅色: 正在PC上創建USB模擬器, 如果持續閃爍有可能驅動未安裝成功
  • 紅色: 在PC與ST-Link之間已經建立連接(USB模擬已完成)
  • 閃爍交替綠色和紅色: 目標芯片和PC之間正在交換數據
  • 綠色: ST-Link與目標芯片通信成功
  • 橙色(紅綠同時亮): ST-Link與目標芯片通信失敗。

USB2TTL轉接卡

在觀察串口輸出時需要使用.

安裝說明

文件准備

  • mdk525.exe
    不建議使用5.12等早期版本, 在更新時窗口容易卡, 且失敗總會彈出需要手工消除.
  • keygen2032
    大部分找到的keygen, 有效期都是2020年的, 沒法用, 必須要能生成2032有效期的版本
  • st-link驅動
    https://www.st.com/zh/development-tools/stsw-link004.html 不安裝沒法燒錄
  • st官方庫
    前往https://www.st.com/, 點擊Tools&Software > Embedded Software > MCU & MPU Embedded Software > STM32 Embedded Software > STM32 Standard Peripheral Libraries(鏈接), 下載F1和F4, 解壓備用.
    • 這里下載的F1的庫文件, Release notes發布日期是2011年, 年代比較久遠

安裝

  1. 運行mdk525, 安裝
  2. 安裝完成后Pack Installer會自動運行, 可以讓其自己更新
  3. 如果使用stlink下載器的, 還需要安裝驅動

注冊

  1. 以管理員身份運行Keil uVision5
    1. File->License Management, 復制Computer ID - CID的內容

安裝開發包

在Pack Installer中

  1. 在左側找到STMicroelectronics->STM32F1->STM32F103, 點擊
  2. 在右側會顯示對應的Packs, 在Device Specific中找到Keil::STM32F1xx_DFP, 點擊Install安裝
  3. 同理安裝STM32F401

名詞解釋

CMSIS

微控制器軟件接口標准(CMSIS:Cortex Microcontroller Software Interface Standard)是 Cortex-M 處理器系列的與供應商無關的硬件抽象層(A vendor-independent hardware abstraction layer for the Cortex-M processor series and defines generic tool interfaces). 使用CMSIS可以為處理器和外設實現一致且簡單的軟件接口, 從而簡化軟件的重用、縮短微控制器新開發人員的學習過程,並縮短新設備的上市時間

ld, md, hd, xl; cl, vl

  • ld(low density), md(medium density), hd(high density), xl(XL-Density) 對應同一個型號線上, 不同flash和ram大小的芯片.
  • vl(value line), cl(connectivity line) 指的是同一型號下, 不同的細分型號線

對於stm32f1x, 各名詞的對應關系為

  • Low-density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers where the Flash memory density ranges between 16 and 32 Kbytes.
  • Medium-density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers where the Flash memory density ranges between 64 and 128 Kbytes.
  • High-density devices are STM32F101xx and STM32F103xx microcontrollers where the Flash memory density ranges between 256 and 512 Kbytes.
  • XL-density devices are STM32F101xx and STM32F103xx microcontrollers where the Flash memory density ranges between 768 Kbytes and 1 Mbyte.
  • Connectivity line devices are STM32F105xx and STM32F107xx microcontrollers.

ST官方庫結構說明

STM32F10x_StdPeriph_Lib_V3.5.0

目錄結構及說明

├─Libraries
│  ├─CMSIS
│  │  ├─CM3
│  │  │  ├─CoreSupport                 # CMSIS核心外設訪問層代碼
│  │  │  └─DeviceSupport
│  │  │      └─ST
│  │  │          └─STM32F10x           # stm32f10x相關代碼
│  │  │              └─startup
│  │  │                  ├─arm         # startup_stm32f10x_ld/md/hd/xl.s文件, 
                                       # stm32f103c8t66規格為64k flash, 對應md
│  │  │                  ├─gcc_ride7
│  │  │                  ├─iar
│  │  │                  └─TrueSTUDIO
│  │  └─Documentation
│  └─STM32F10x_StdPeriph_Driver        # 對應stm32f10x的外設代碼
│      ├─inc
│      └─src
├─Project
│  ├─STM32F10x_StdPeriph_Examples      # 代碼示例
│  └─STM32F10x_StdPeriph_Template      # 代碼模板, 需要用到stm32f10x_conf.h, stm32f10x_it.c, stm32f10x_it.h這三個文件(直接復制到新項目的USER目錄)
│      ├─EWARM
│      ├─HiTOP
│      ├─MDK-ARM
│      ├─RIDE
│      └─TrueSTUDIO
├─Utilities
└─_htmresc

開發說明

創建項目

創建目錄並填充文件

以stm32f103為例, 對於項目test001, 創建工作目錄test001, 在工作目錄下創建MDK-ARM, USER這兩個目錄

  1. 復制開發包下的Libraries整個目錄到當前項目目錄下
    • 這個目錄中包含了CMSIS核心外設訪問層代碼
    • stm32的外設庫文件
  2. mdk-arm
    用於放置Keil MDK項目文件, 以及項目開發過程中生成的臨時文件
  3. hardware
    用於放置自定義的外設, 例如rfid, esp8266等
  4. user
    • 復制 STM32F10x_StdPeriph_Template下面的stm32f10x_conf.h, stm32f10x_it.c, stm32f10x_it.h三個文件到這個目錄
    • 用於放置用戶編寫的代碼

ld,md,hd的選擇
md hd ld 根據芯片FLASH容量決定

  • 16K < FLASH < 32K ld
  • 64K < FLASH < 128K md
  • 256K < FLASH < 512K hd

在Keil uVision5中創建項目

  1. Project -> New uVision Project, 選擇前面的MDK-ARM目錄, 使用名稱test001, 保存
  2. 選擇對應的芯片型號

配置項目

點擊Manage Project Items

  1. 修改project targets名稱
  2. 添加groups
    1. CMSIS
    2. StdPeriph_Driver
    3. Hardware
    4. Startup
    5. User

對每個group, 添加的文件為

  • CMSIS
    • core_cm3.c
    • system_stm32f10x.c
  • StdPeriph_Driver
    • 添加 libraries/STM32F10x_StdPeriph_Driver/src 下面的所有c文件
  • Hardware
    • 添加 hardware目錄下的c文件
  • Startup
    • 添加 libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm 下面對應的s文件
  • User
    • 添加 user 目錄下的所有c文件

點擊configure target options , 定位到c/c++

  1. Define: 寫入 USE_STDPERIPH_DRIVER
    • 不需要填STM32F10X_MD, STM32F10X_HD 這些配置, 這個變量在前面選擇芯片型號的時候就自動定義了, 不確定的話可以觀察產生的Compiler Control String
  2. Include Paths: 如果是按上面的目錄結構組織的項目, 可以直接復制下面的配置
..\Libraries\CMSIS\CM3\CoreSupport;..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x;..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm;..\Libraries\STM32F10x_StdPeriph_Driver\inc;..\hardware;..\user

在c/c++下能看到完整的編譯Compile control string

-c --cpu Cortex-M3 -D__MICROLIB -g -O0 --apcs=interwork --split_sections -I ../Libraries/CMSIS/CM3/CoreSupport -I ../Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x -I ../Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm -I ../Libraries/STM32F10x_StdPeriph_Driver/inc -I ../Libraries/ STM32F10x_StdPeriph_Driver/src -I ../hardware -I ../user
-I./RTE/_test001
-IC:/Keil_v5/ARM/PACK/Keil/STM32F1xx_DFP/2.3.0/Device/Include
-IC:/Keil_v5/ARM/CMSIS/Include
-D__UVISION_VERSION="525" -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER
-o .\Obj\*.o --omf_browse .\Obj\*.crf --depend .\Obj\*.d

燒錄

stlink與stm32f103c8t6核心板

連接需要4根線, 連接關系為

G   -- GND
CLK -- SWCLK
IO  -- SWDIO
V3  -- 3.3V

stlink與stm32f103vct6開發板

有些開發板沒有單獨的SWC/SWD接口, 只能連接到JTAG接口, 連接方式為:

  1. 從PCB板上方俯視, 將JTAG接口座缺口朝上
  2. PIN1-PIN20為從上至下, 從右至左
  3. 最右側為PIN1(上), PIN2(下), 都可以接stlink的3.3V
  4. 從右往左數第4個為PIN7, 接SWDIO, 第5個為PIN9, 接SWCLK
  5. 最左下角為PIN20, 接GND

在Keil uvision5中

  1. 點擊configure target options , 定位到Debug, Use選擇ST-Link Debuger, 點擊Settings
  2. 如果Debug Adapter里時空白沒有顯示ST-LINK/V2, 去windows設備管理器看下設備是否正常
  3. 切換到Flash Download標簽, 勾選Reset and Run
  4. 點擊Download按鈕, 或者按F8, 進行燒錄

Debug調試說明

在F7編譯完代碼, F8將程序通過ST-Link燒錄至開發板后, 就可以對程序進行調試

快捷鍵匯總

  • 進入/跳出Debug模式: Ctrl + F5
  • 繼續運行 F5
  • 逐步運行 F10
  • 單步執行(會跳入) F11
  • 從函數內跳出運行 Ctrl + F11
  • 運行到光標所在處 Ctrl + F10
  • 插入/移除斷點 F9
  • 移除所有斷點Ctrl + Shift + F9

調試要點

  1. 點擊Start/Stop Debug SessionCtrl+F5進入Debug模式, 在進入Debug模式后, 會重啟程序, 並暫停程序運行
  2. 這時候可以按F5往下執行, 或者按F10F11一步一步執行, 或者Ctrl + F10跳到光標指定的行
  3. 通過Reset按鈕, 可以將程序恢復到初始的暫停狀態
  4. 常用的調試小窗口
    1. Watch窗口: 選中變量 -> 右鍵 -> Add xxx to ->Watch1
    2. System Viewer窗口: 可以實時查看外設寄存器值, 通過View->System View -> 指定外設 打開.

stm32開發說明

代碼結構

項目的目錄結構比較自由, 只要包含的C文件正確, 包含的頭文件路徑正確, 再加上正確的編譯變量如USE_STDPERIPH_DRIVER, 編譯就沒問題. 但是在項目中還是需要注意目錄結構, 建議將平時不需改動的代碼, 需要頻繁修改的代碼, 以及IDE相關的文件, 編譯中間產生的文件, 都按目錄分隔開.

在項目中最終采的代碼結構

├─Libraries
│  ├─CMSIS
│  ├─Hardware
│  └─STM32F10x_StdPeriph_Driver
├─MDK-ARM
└─User
  • 其中Libraries直接用開發庫的原始文件結構, CMSIS和STM32F10x_StdPeriph_Driver是開發中不需要修改的
  • 將自定義的外設代碼都放在單獨的Hardware目錄中, 這個目錄可以放在Libraries下, 也可以放在最外層與Libraries平級
    • 外設代碼的頭文件中, 不應當包含全局頭文件include.h, 而是包含stm32f10x.h, 以及其他需要用到的Hardware頭文件.
  • 項目相關的代碼, 例如main.c都放在User目錄下
    • 創建一個include.h, 用於包含整體的項目頭文件, stm32f10x.h以及用到的Hardware頭文件, 在main.c中引用include.h
    • 創建一個config.h, 用於放置環境相關的變量, 在main.c以及需要用到的hardware中引用, 這個文件要加到.gitignore
  • IDE相關以及編譯中間產生的文件, 都放在MDK-ARM目錄下, 這個目錄需要添加到.gitignore

代碼邏輯

STM32F10x是基於ARM Cortex-M3 的32位內核, F4是基於M4的內核, M3跟M4比就是不帶FPU和DSP指令集. 在STM32上的開發思路, 和一般的軟件項目開發思路不太一樣. STM32上跑的程序, 基本上就是圍繞着它的外設進行的, 主要的外設包括 DMA, ETH, GPIO, TIM, U(S)ART, SPI, I2C, ADC等.
代碼的套路一般是這樣的

  1. 初始化需要的外設, 包括內建的定時器, GPIO, UART, SPI, I2C, 中斷以及自定義的外設, 例如RFID, ESP8266等
    1. 對於自定義的外設, 需要自己編寫外設驅動, 處理與STM32內建外設之間的通信
  2. 做一個while(1)循環, 在循環中完成業務邏輯
  3. 主體單進程, 在進程中通過各種中斷, 觸發和處理外設之間的通信

需要注意的地方

  1. 每個外設, 都有對應的總線, 對應的編號, 以及對應的PIN腳, 這些會直接體現到代碼中
  2. 要根據總線頻率, 自己控制時間, 定時和延遲都是自己控制的
  3. 傳輸是以byte為單位的, 一個中斷可能只產生1個byte的數據
  4. 外設的初始化, 中斷位的判斷和清除, 都是固定用法
  5. 內存是有限的, 對每個byte都要計算精確, 不能浪費

內存管理

stm32f103c8t6的flash為64k, ram為20k, 容量都很小. 編譯結果中的信息

Program Size: Code=8788 RO-data=424 RW-data=72 ZI-data=2328  

與這兩部分相關聯的關系為

  • FLASH占用 = Code + RO Data + RW Data
  • RAM占用 = RW Data + ZI Data + Stack_Size + Heap_Size

實際測試發現, 不論RW Data + ZI Data多大, 運行中可以通過malloc+memset申請的內存只有500個字節, 只要申請的內存超過這個數量, 運行就會卡住.
在代碼中, 盡量不要用malloc, 而應該直接聲明為固定長度的數組, 這樣聲明的內存, 可以觀察到會增長到ZI Data中去, 這種方式能使用的空間比500字節大得多.

問題排查

當遇到問題時, 例如引腳不工作, 不輸出, 輸出不正確, 需要通過各種手段檢查和排查

  • 引腳不工作, 要檢查對應的模塊是否正確初始化, 是否使能. STM32中GPIO, UART, NVIC這些模塊的啟動基本上都是固定套路
    • 對於串口等外設語句上需要檢查, AHB1, APB1, APB2 與外設對應關系是否正確, 是否錯誤使用RCC_APB1去啟用RCC_APB2了
    • 是否在main中調用初始化方法了
  • 串口輸出和輸入的問題排查
    • 首先是在debug界面, 查看串口外設的寄存器值, 看看有沒有初始化成功
    • 通過USB2TTL轉接卡, 將信號輸入輸出轉移到putty/xshell中進行檢查
    • 排除連線斷路的問題
  • 字符串輸入輸出. 因為有\r, \n等格式符號的存在, 會導致輸出字符顯示較亂, 當需要嚴格對照時, 需要將每個字符打印成雙位16進制輸出%02X
  • 程序執行卡住, 有可能是變量申請的內存過大超出了內存限制

參考代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM