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


Keil MDK STM32系列

概述

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

STM32F4系列MCU介紹

STM32F4系列基於Cortex M4內核, 於2011年發布, 上市已經十年了. 相對於基於Cortex M3的產品, STM32F4最大的優勢是新增了硬件FPU單元以及DSP指令, 同時主頻也提高到了168Mhz(可獲得210DMIPS的處理能力), 這使得STM32F4適用於需要浮點運算或DSP處理的應用.

STM32F4相對於STM32F1,主要優勢如下

  1. 采用Cortex M4內核, 帶FPU和DSP指令集, 而STM32F1采用的是Cortex M3內核, 不帶FPU和DSP指令集
  2. 更多的資源, STM32F4有 192KB 片內SRAM, 帶攝像頭接口(DCMI), 加密處理器(CRYP), USB高速OTG, 真隨機數發生器, OTP存儲器等
  3. 增強的外設功能. 對於相同的外設部分, STM32F4具有更快的模數轉換速度、更低的ADC/DAC工作電壓, 32位定時器, 帶日歷功能的實時時鍾(RTC), IO復用功能大大增強, 4K字節的電池備份SRAM以及更快的USART和SPI通信速度
  4. 更高的性能. STM32F4最高運行頻率可達168Mhz, 而STM32F1只能到72Mhz, STM32F4擁有ART自適應實時加速器, 可以達到相當於FLASH零等待周期的性能, STM32F1則需要等待周期, STM32F4的FSMC采用32位多重AHB總線矩陣, 相比STM32F1總線訪問速度明顯提高
  5. 更低的功耗, STM32F40x的功耗為 238uA/Mhz, 其中低功耗版本的STM32F401更是低到 140uA/Mhz, 而STM32F1則為 421uA/Mhz

STM32F401硬件環境

主要參數

  • ARM 32-bit Cortex-M4 with FPU
  • 80 MHz maximum frequency
  • 256k flash
  • 64k ram
  • UFQFPN 封裝48pin

STM32F401CCU6與STM32F103C8T6相比, 引腳基本兼容, 但是需要注意一個引腳PB11, PB11引腳不能當GPIO使用, 同時必須外接2.2UF電容, 因此USART3也不復存在, 在STM32F401中換成了USART6. 下面的開發板PB口就沒有PB11.

市面上常見的開發板有兩種, 一種黑色的俗稱Black Pill, 另一種是綠色的

Black Pill 開發板

芯片有兩種, STM32F401和STM32F411, 開發板的具體說明可以查看 https://stm32-base.org/boards/STM32F401CCU6-WeAct-Black-Pill-V1.2

Black Pill的特點是背面有sop8 flash焊盤, 可以自己加焊flash

Mini F401 開發板

芯片是STM32F401CCU6 和 STM32F401CDU6, 后者flash是384K, 在開發時要選STM32F401CE而不是CC.
開發板的具體說明可以查看 https://stm32-base.org/boards/STM32F401CCU6-STM32-Mini-F401

外觀

電路圖(不完全一致)

使用普通的4線 ST-Link V2, 也可以使用增加了串口的V2.1

ST-Link 與 stm32核心板的連接需要4根線, 連接關系為

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

燒錄時, 如果開發板已經外接了電源, 那么st-link的3.3V不要接到開發板.

USB2TTL TTL轉接卡

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

Keil MDK安裝說明

STM32F4 官方標准外設庫 Standard Peripheral Libraries

ST官方庫下載:

  1. 前往https://www.st.com/,
  2. 點擊Tools&Software > Embedded Software > MCU & MPU Embedded Software > STM32 Embedded Software > STM32 Standard Peripheral Libraries
  3. (鏈接),
  4. 下載F4, 解壓備用

標准庫版本只到1.8.0版本, 已經停止更新. 好處就是現在使用標准庫的項目基本上都不用擔心庫版本的兼容問題.

ST標准外設庫結構說明

STM32F4xx_DSP_StdPeriph_Lib_V1.8.0 目錄結構

├─Libraries
│  ├─CMSIS
│  │  ├─Device
│  │  │  └─ST
│  │  │      └─STM32F4xx
│  │  │          ├─Include                # 需要
│  │  │          └─Source
│  │  │              └─Templates
│  │  │                  ├─arm            # startup文件, 需要
│  │  │                  ├─gcc_ride7
│  │  │                  ├─iar
│  │  │                  ├─SW4STM32
│  │  │                  ├─TASKING
│  │  │                  └─TrueSTUDIO
│  │  ├─Documentation
│  │  ├─DSP_Lib
│  │  ├─Include                           # 需要
│  │  ├─Lib
│  │  │  ├─ARM
│  │  │  └─GCC
│  │  └─RTOS
│  │      └─Template
│  └─STM32F4xx_StdPeriph_Driver           # 需要. 注意里面的xx_fmc.c和xx_fsmc.c不要包含, 因為這兩個
                                          # 用到的變量在F401里面沒有, 只在少數幾個F4xx型號里有.
│      ├─inc
│      └─src
├─Project
│  ├─STM32F4xx_StdPeriph_Examples         # 官方的代碼例子
│  └─STM32F4xx_StdPeriph_Templates        # 需要stm32f4xx_conf.h, stm32f4xx_it.c, stm32f4xx_it.h
│      ├─EWARM
│      ├─MDK-ARM
│      ├─SW4STM32
│      └─TrueSTUDIO
├─Utilities
│  ├─Media
│  ├─ST
│  │  └─STemWin
│  │      └─Software
│  ├─STM32_EVAL
│  │  ├─Common
│  │  ├─STM3240_41_G_EVAL
│  │  ├─STM324x7I_EVAL
│  │  └─STM324x9I_EVAL
│  └─Third_Party
└─_htmresc

按步驟手工創建項目

先組織好庫文件和目錄, 然后創建項目

創建目錄並填充文件

以下以名稱為test001的項目為例

  1. 創建工作目錄 test001
  2. 在工作目錄下創建 Drivers, User 2個目錄
  3. 從解壓后的標准外設庫中, 復制 Libraries\CMSIS 目錄到 Drivers, CMSIS 這個目錄下只需要保留 Device 和 Include 這兩個目錄, 其他目錄不需要
  4. 復制 Libraries\STM32F4xx_StdPeriph_Driver 整個目錄到 Drivers
  5. User
    • 復制 Project\STM32F4xx_StdPeriph_Templates 下面的stm32f4xx_conf.h, stm32f4xx_it.c, stm32f4xx_it.h三個文件到這個目錄
    • 用於放置用戶編寫的代碼

完成后的目錄結構是這樣的

test001>
├─Drivers
│  ├─CMSIS
│  │  ├─Device
│  │  │  └─ST
│  │  │      └─STM32F4xx
│  │  │          ├─Include
│  │  │          └─Source
│  │  └─Include
│  └─STM32F4xx_StdPeriph_Driver
│      ├─inc
│      └─src
└─User

在Keil uVision5中創建項目

  1. Project -> New uVision Project, 選擇工作目錄 test001, 使用名稱test001, 保存
  2. 在彈出的對話框中, 選擇芯片型號, STM32F401CCU6 選擇芯片型號STM32F401CCUx, STM32F401CDU6 選擇 STM32F401CDUx
  3. 在后續的 Manage Run-Time Enviroment 對話框中什么都不選, 因為會在項目里自己管理庫文件

配置項目

在上面的步驟完成后, Keil MDK中就會顯示一個項目的初始結構, 目錄為 Project:test001, 以及一個 Target1

修改 Target 名稱以及添加源文件

在菜單中點擊 Project -> Manage -> Project Items, 或者直接在圖標欄中點擊紅黃綠品字形的圖標, 在彈出的對話框中

  1. 修改 project targets 名稱為 test001, 這個可以隨便改
  2. 編輯並添加 Groups, 最終會有以下 Groups
    • CMSIS
    • StdPeriph_Driver
    • Startup
    • User

對每個group, 添加的文件為

  • CMSIS
    • 添加 Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c
  • StdPeriph_Driver
    • 添加 Drivers\STM32F4xx_StdPeriph_Driver\src 下面的所有c文件, 除了 stm32f4xx_fmc.c 和 stm32f4xx_fsmc.c
  • Startup
    • (F401CCU6)添加 Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm 下面的 startup_stm32f401xx.s 文件
    • (F407VET6)添加的是 startup_stm32f40_41xxx.s
  • User
    • 添加 user 目錄下的所有C文件

修改項目包含路徑

在菜單中點擊Project -> Options for Target 'test001', 或者直接在圖標欄中點擊configure target option圖標, 在彈出的對話框中

  1. 定位到c/c++標簽頁
  2. Define: 這個是編譯參數, 寫入 USE_STDPERIPH_DRIVER, STM32F401xx 因為MDK自動添加的參數是STM32F401xC, 而SPL需要指定的參數是STM32F401xx, 和MDK給的不一致, 所以這里要自行指定
  3. Include Paths: 這里是頭文件的包含路徑, 如果按上面的目錄結構組織的項目, 可以直接復制下面的配置
.\Drivers\CMSIS\Include;.\Drivers\CMSIS\Device\ST\STM32F4xx\Include;.\Drivers\STM32F4xx_StdPeriph_Driver\inc;.\User

在下面的 compiler control string 中可以查看完整的命令行

--c99 --gnu -c --cpu Cortex-M4.fp -g -O0 --apcs=interwork --split_sections -I ./Drivers/CMSIS/Include -I ./Drivers/CMSIS/Device/ST/STM32F4xx/Include -I ./Drivers/STM32F4xx_StdPeriph_Driver/inc -I ./User
-I./RTE/_test001
-IC:/Keil_v5/ARM/PACK/Keil/STM32F4xx_DFP/2.15.0/Drivers/CMSIS/Device/ST/STM32F4xx/Include
-IC:/Keil_v5/ARM/CMSIS/Include
-D__UVISION_VERSION="525" -DSTM32F401xC -DUSE_STDPERIPH_DRIVER -DSTM32F401xx
-o .\Objects\*.o --omf_browse .\Objects\*.crf --depend .\Objects\*.d

STM32F401CCU6示例代碼

下面的例子, 使用開發板自帶的led燈(PC13)實現間隔1秒的亮滅效果.
在User目錄下創建 main.h 和 main.c, 注意通過Keil MDK創建的時候, 要注意文件位置, 默認是放到項目根目錄的, 這里要改到User目錄下.

main.c

#include "main.h"

static __IO uint32_t uwTimingDelay;
RCC_ClocksTypeDef RCC_Clocks;

static void Delay(__IO uint32_t nTime);

void LED_Init(void)
{
	GPIO_InitTypeDef  aaa;
	// 使能指定的GPIO模塊時鍾--默認復位后開機時鍾不會全部提供給各個模塊 使用時需要自己開啟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);	
	// 初始化引腳
	aaa.GPIO_Pin = GPIO_Pin_13;    // 引腳號選擇 PC13: RCC_AHB1Periph_GPIOC, GPIOC, GPIO_Pin_13
	aaa.GPIO_Mode = GPIO_Mode_OUT; // 輸出模式
	aaa.GPIO_OType =  GPIO_OType_PP;  // 推挽輸出
	aaa.GPIO_Speed = GPIO_High_Speed; // 高速
	GPIO_Init(GPIOC, &aaa);
}

void TIM2_init(void)
{
	TIM_TimeBaseInitTypeDef  aaa;
	// 使能對應模塊的時鍾 TIM2
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	// 初始化定時器
	aaa.TIM_Prescaler = 8400;  // 通過prescaler將84MHz降為10KHz
	aaa.TIM_Period    = 10000; // 再通過period設置計時器間隔為上面頻率的10K個周期, 即1s
	aaa.TIM_CounterMode = TIM_CounterMode_Up; // 選擇遞增模式
	aaa.TIM_ClockDivision = TIM_CKD_DIV1;     // 1分頻 1  2  4
	TIM_TimeBaseInit(TIM2, &aaa);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能TIM2的更新中斷
	TIM_Cmd(TIM2, ENABLE); // 使能TIM2
}

void NVIC_INIT(void)
{
	NVIC_InitTypeDef  ccc;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷優先級分組  2分組
	ccc.NVIC_IRQChannel = TIM2_IRQn;
	ccc.NVIC_IRQChannelCmd = ENABLE;
	ccc.NVIC_IRQChannelPreemptionPriority = 0;
	ccc.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&ccc);
}

void TIM2_IRQHandler(void) 
{
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除溢出中斷標志位
	GPIO_ToggleBits(GPIOC, GPIO_Pin_13);        // 觸發值交替變化
}

int main(void)
{
  LED_Init();//初始化LED
	GPIO_WriteBit(GPIOC, GPIO_Pin_13, 0);
	TIM2_init();
	NVIC_INIT();
	while(1)//卡住
	{
	}
}

/**
  * @brief  Inserts a delay time.
  * @param  nTime: specifies the delay time length, in milliseconds.
  * @retval None
  */
void Delay(__IO uint32_t nTime)
{ 
  uwTimingDelay = nTime;

  while(uwTimingDelay != 0);
}

/**
  * @brief  Decrements the TimingDelay variable.
  * @param  None
  * @retval None
  */
void TimingDelay_Decrement(void)
{
  if (uwTimingDelay != 0x00)
  { 
    uwTimingDelay--;
  }
}

#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

main.h

#ifndef __MAIN_H
#define __MAIN_H

#include "stm32f4xx.h"

void TimingDelay_Decrement(void);

#endif /* __MAIN_H */

編譯

按F7執行編譯

燒錄

在菜單中點擊Project -> Options for Target 'test001', 或者直接在圖標欄中點擊configure target option圖標, 在彈出的對話框中

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

開發包中的例子

在官方庫的壓縮包里, 包含着這個版本各個外設功能的代碼例子, 可以直接參考.


免責聲明!

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



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