Keil MDK STM32系列
- Keil MDK STM32系列(一) 基於標准外設庫SPL的STM32F103開發
- Keil MDK STM32系列(二) 基於標准外設庫SPL的STM32F401開發
- Keil MDK STM32系列(三) 基於標准外設庫SPL的STM32F407開發
- Keil MDK STM32系列(四) 基於抽象外設庫HAL的STM32F401開發
- Keil MDK STM32系列(五) 使用STM32CubeMX創建項目基礎結構
- Keil MDK STM32系列(六) 基於HAL的ADC模數轉換
- Keil MDK STM32系列(七) 基於HAL的PWM和定時器
- Keil MDK STM32系列(八) 基於HAL的PWM和定時器輸出音頻
- Keil MDK STM32系列(九) 基於HAL和FatFs的FAT格式SD卡TF卡讀寫
概述
Windows下使用Keil MDK5進行 STM32F407VET6 的開發和編譯, 配合ST-LINK工具進行燒錄, 使用標准外設庫SPL.
STM32F407硬件環境
主要參數
- STM32F407VET6 Arm Cortex-M4
- 168MHz Max Clock Speed
- 512k flash
- 192k ram
- LQFP 100 pins
- Backup SRAM 4k
STM32F407VET6 Black Board 開發板
具體說明可以查看 https://stm32-base.org/boards/STM32F407VET6-STM32-F4VE-V2.0.html
ST-Link 編程器
使用普通的4線 ST-Link V2, 也可以使用增加了串口的V2.1
ST-Link 與 stm32核心板的連接需要4根線, 連接關系為
G -- GND
CLK -- SWCLK
IO -- SWDIO
V3 -- 3.3V
燒錄時, 如果開發板已經外接了電源, 那么st-link的3.3V不要接到開發板.
外觀

連接ST-Link

USB2TTL 轉接卡
在觀察串口輸出時需要使用.
STM32F4 官方標准外設庫 Standard Peripheral Libraries
參考STM32F401的說明, 與STM32F401相同
按步驟手工創建項目
先組織好庫文件和目錄, 然后創建項目
創建目錄並填充文件
參考STM32F401的說明, 與STM32F401相同, 完成后的目錄結構是這樣的
test001>
├─Drivers
│ ├─CMSIS
│ │ ├─Device
│ │ │ └─ST
│ │ │ └─STM32F4xx
│ │ │ ├─Include
│ │ │ └─Source
│ │ └─Include
│ └─STM32F4xx_StdPeriph_Driver
│ ├─inc
│ └─src
└─User
在Keil uVision5中創建項目
Project -> New uVision Project, 選擇工作目錄 test001, 使用名稱test001, 保存- 在彈出的對話框中, 選擇芯片型號, 選擇芯片型號STM32F407VE
- 在后續的 Manage Run-Time Enviroment 對話框中什么都不選, 因為會在項目里自己管理庫文件
配置項目
在上面的步驟完成后, Keil MDK中就會顯示一個項目的初始結構, 目錄為 Project:test001, 以及一個 Target1
修改 Target 名稱以及添加源文件
在菜單中點擊 Project -> Manage -> Project Items, 或者直接在圖標欄中點擊紅黃綠品字形的圖標, 在彈出的對話框中
- 修改 project targets 名稱為 test001, 這個可以隨便改
- 編輯並添加 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
- 注意, 這里是與F401不同的:添加 Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f40_41xxx.s 文件
- User
- 添加 user 目錄下的所有C文件
修改項目包含路徑
在菜單中點擊Project -> Options for Target 'test001', 或者直接在圖標欄中點擊configure target option圖標, 在彈出的對話框中
- 定位到c/c++標簽頁
- Define: 這個是編譯參數, 注意這里也與F401不同, 寫入 USE_STDPERIPH_DRIVER,STM32F40_41xxx
- 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 ../libraries/CMSIS/Include -I ../libraries/CMSIS/Device/ST/STM32F4xx/Include -I ../libraries/STM32F4xx_StdPeriph_Driver/inc -I ../user
-I./RTE/_stm32f407test01
-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" -DSTM32F407xx -DUSE_STDPERIPH_DRIVER -DSTM32F40_41xxx
-o .\Objects\*.o --omf_browse .\Objects\*.crf --depend .\Objects\*.d
STM32F407 Black Board 示例代碼
下面的例子, 使用開發板自帶的led燈(A6, A7)實現交替亮滅的效果.
在User目錄下創建 main.h 和 main.c, 注意通過Keil MDK創建的時候, 要注意文件位置, 默認是放到項目根目錄的, 這里要改到User目錄下.
main.c
#include "main.h"
#define GPIO_LED GPIOA
#define GPIO_PIN_LED0 GPIO_Pin_6
#define GPIO_PIN_LED1 GPIO_Pin_7
static u8 fac_us=0;//us延時倍乘數
static u16 fac_ms=0;//ms延時倍乘數,在ucos下,代表每個節拍的ms數
void delay_init(u8 SYSCLK)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SYSCLK/8; //不論是否使用ucos,fac_us都需要使用
fac_ms=(u16)fac_us*1000;//非ucos下,代表每個ms需要的systick時鍾數
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //時間加載
SysTick->VAL=0x00; //清空計數器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數
do
{
temp=SysTick->CTRL;
}
while((temp&0x01)&&!(temp&(1<<16)));//等待時間到達
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器
SysTick->VAL =0X00; //清空計數器
}
//延時nms
//注意nms的范圍
//SysTick->LOAD為24位寄存器,所以,最大延時為:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK單位為Hz,nms單位為ms
//對168M條件下,nms<=798ms
void delay_xms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;//時間加載(SysTick->LOAD為24bit)
SysTick->VAL =0x00; //清空計數器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數
do
{
temp=SysTick->CTRL;
}
while((temp&0x01)&&!(temp&(1<<16)));//等待時間到達
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器
SysTick->VAL =0X00; //清空計數器
}
//延時nms
//nms:0~65535
void delay_ms(u16 nms)
{
u8 repeat=nms/540; //這里用540,是考慮到某些客戶可能超頻使用,
//比如超頻到248M的時候,delay_xms最大只能延時541ms左右了
u16 remain=nms%540;
while(repeat)
{
delay_xms(540);
repeat--;
}
if(remain)delay_xms(remain);
}
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA時鍾
//GPIOF9,F10初始化設置
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_LED0 | GPIO_PIN_LED1;//LED0和LED1對應IO口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通輸出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIO_LED, &GPIO_InitStructure);//初始化GPIO
GPIO_SetBits(GPIO_LED,GPIO_PIN_LED0 | GPIO_PIN_LED1);//設置高,燈滅
}
int main(void)
{
delay_init(168); //初始化延時函數
LED_Init(); //初始化LED端口
/**下面是通過直接操作庫函數的方式實現IO控制**/
while(1)
{
GPIO_ResetBits(GPIO_LED,GPIO_PIN_LED0);
GPIO_SetBits(GPIO_LED,GPIO_PIN_LED1);
delay_ms(500);
GPIO_SetBits(GPIO_LED,GPIO_PIN_LED0);
GPIO_ResetBits(GPIO_LED,GPIO_PIN_LED1);
delay_ms(500);
}
}
main.h
#ifndef __MAIN_H
#define __MAIN_H
#include "stm32f4xx.h"
#endif /* __MAIN_H */
編譯燒錄
編譯和燒錄和F401是一樣的
