• 首页
  • 中国
  • Keil MDK STM32系列(三) 基于标准外设库SPL的STM32F407开发

Keil MDK STM32系列(三) 基于标准外设库SPL的STM32F407开发

2023-11-01 73浏览
百检网是一家专业的第三方检测平台,汇聚众多拥有权威资质的第三方检测机构为你提供一站式的检测服务,做检测就上百检网。百检网让检测从此检测,一份报告全国通用,专业值得信赖。

概述

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

添加 DriversCMSISDeviceSTSTM32F4xxSourceTemplatessystem_stm32f4xx.c

StdPeriph_Driver

添加 DriversSTM32F4xx_StdPeriph_Driversrc 下面的所有c文件, 除了 stm32f4xx_fmc.c 和 stm32f4xx_fsmc.c

Startup

注意, 这里是与F401不同的:添加 DriversCMSISDeviceSTSTM32F4xxSourceTemplatesarmstartup_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: 这里是头文件的包含路径, 如果按上面的目录结构组织的项目, 可以直接复制下面的配置

.DriversCMSISInclude;.DriversCMSISDeviceSTSTM32F4xxInclude;.DriversSTM32F4xx_StdPeriph_Driverinc;.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 */


百检网秉承“客户至上,服务为先,精诚合作,以人为本”的经营理念,始终站在用户的角度解决问题,为客户提供“一站购物式”的新奇检测体验,打开网站,像挑选商品一样简单,方便。打破行业信息壁垒,建构消费和检测机构之间高效的沟通平台