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


Keil MDK STM32系列

概述

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

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

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

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

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

外觀

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中創建項目

  1. Project -> New uVision Project, 選擇工作目錄 test001, 使用名稱test001, 保存
  2. 在彈出的對話框中, 選擇芯片型號, 選擇芯片型號STM32F407VE
  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
    • 注意, 這里是與F401不同的:添加 Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm\startup_stm32f40_41xxx.s 文件
  • User
    • 添加 user 目錄下的所有C文件

修改項目包含路徑

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

  1. 定位到c/c++標簽頁
  2. Define: 這個是編譯參數, 注意這里也與F401不同, 寫入 USE_STDPERIPH_DRIVER,STM32F40_41xxx
  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 ../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是一樣的


免責聲明!

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



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