基于STM32标准库建立Keil-MDK工程模板(STM32F407ZG)

一、前言

最近由于项目需要使用标准库,标准库是很刚入门stm32那会学习的东西,忘得一干二净,所以编写一篇文章来记录一下建立工程模板的步骤,以便尽快熟悉标准库的架构和API。

我使用的开发板是正点原子探索者开发板,MCU为STM32F407ZGT6。

二、STM32标准外设库

STM32标准库(官方网站)是ST在早期为STM32F0到F4系列主流芯片提供的库,使开发者不需要直接操作寄存器,而是调用库提供的API即可完成对某个片内外设的操作,所以也称为标准外设库,或者固件库。

本文中我使用的是 STM32F4xx_DSP_StdPeriph_Lib_V1.8.0,可以从官网下载(下载地址):

解压之后,标准外设库中每个文件夹的说明如图:

三、建立Keil-MDK模板工程

1. 创建文件夹

创建一个模板工程的文件夹,如图:

  • doc:存放文档
  • libraries:存放标准外设库
  • project:存放工程文件
  • user:存放用户文件

在project文件下新建MDK文件夹,方便支持不同的编译器:

2. 复制标准库

将标准库中的Libraires文件夹中的内容复制到刚刚建立的文件夹中:

3. 创建工程

打开Keil-MDK,在刚刚创建的 project/MDK 下建立一个新的工程,设计如下分组:

3.1. 添加启动文件

启动文件在标准库中的CMSIS\Device\ST\STM32F4xx\Source\Templates目录下:

这里我们使用的是MDK,所以选择arm文件夹下的启动文件,如图:

在Startup分组中添加该启动文件:

3.2. 添加系统初始化文件

系统初始化文件在 CMSIS\Device\ST\STM32F4xx\Source\Templates目录下:

在CMSIS分组中添加该文件:

3.3. 添加标准外设库文件

标准外设库所有文件都在STM32F4xx_StdPeriph_Driver\src目录中,全部添加到 STM32F4xx_StdPeriph_Driver 分组中:

STM32F407系列中没有FMC外设,要去掉该驱动文件:

3.4. 添加用户文件

① 中断处理程序文件stm32f4xx_it.c

中断处理程序文件在标准外设库中的示例工程中,复制到自己创建的user文件夹下:

编辑stm32f4xx_it.c文件,去掉包含main.h的代码:

再去掉Systick中断中的内容:

② 标准外设库配置文件stm32f4xx_conf.h

③ 新建一个 main.c 文件:

④ 将user下的.c都添加到User分组下面:

3.5. 添加头文件路径

3.6. 添加宏定义

添加两个宏定义:

  • USE_STDPERIPH_DRIVER:表示工程使用标准外设库;
  • STM32F40_41xxx:表示工程对应的MCU型号;

如图:

3.7. 编写main.c

/**********************************************************
 * @brief
 * @author  Mculover666
 * @date    
 * @note
**********************************************************/

#include "stm32f4xx.h"

int main()
{

    /* Main Loop */
    while (1) {
    
    }
}

3.8. 额外的设置

① 该标准外设库不支持armcc6编译器,所以设置为默认的armcc5编译器:

② 标准库提供的文件上都有一把小黄锁,原因是这些文件都是只读文件,在libraries文件夹上右击,修改所有文件的只读属性即可:

3.9. 编译测试

至此,工程创建完成,编译通过:

四、修改时钟树配置

本文中所使用的时钟初始化配置文件``是从标准外设库中复制过来的,从其注释中可以看出该配置使用的HSE为25Mhz,如图:

而本文所使用的正点原子探索者开发板所使用的外部晶振为8Mhz(这就离谱!):

为了保证主频为168Mhz,需要对该配置进行修改。

① 修改HSE宏定义的值为8000000,在stm32f4xx.h中,如图:

② 修改PLL分频系数为8:

至此,时钟树配置完成。

五、如何使用模板工程

这里我以LED闪烁为例,演示如何使用该模板工程。

1. 复制一份模板工程

2. 添加LED驱动

在user文件夹下新建led文件夹及文件,用于存放led驱动:

将 bsp_led.c 添加到工程中:

将 bsp_led.h添加到头文件路径:

3. 编写LED驱动

编写 bsp_led.h 文件:

#ifndef _BSP_LED_H_
#define _BSP_LED_H_

#include "stm32f4xx.h"

#define LED_PORT    GPIOF
#define LED_PIN     GPIO_Pin_9

typedef enum led_status_en {
    LED_OFF = 0,
    LED_ON  = 1
} led_state_t;

void led_init(void);
void led_control(led_state_t status);

#endif /* _BSP_LED_H_ */

编写 bsp_led.c 文件:

#include "bsp_led.h"

void led_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    /* 1. Enable Clock */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    
    /* 2. Config GPIO Structure*/
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Pin   = LED_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Low_Speed;
    GPIO_Init(LED_PORT, &GPIO_InitStructure);
}

void led_control(led_state_t status)
{
    if (status == LED_ON) {
        GPIO_ResetBits(LED_PORT, LED_PIN);
    } else {
        GPIO_SetBits(LED_PORT, LED_PIN);
    }
}

4. 编写业务逻辑

在main.c中编写LED闪烁的代码:

/**********************************************************
 * @brief   LED blink
 * @author  Mculover666
 * @date    2020/1/20
 * @note
**********************************************************/

#include "stm32f4xx.h"
#include "bsp_led.h"

void delay(__IO uint32_t n)
{
	for(; n != 0; n--);
}

int main()
{
    /* Init LED */
    led_init();
    
    /* Main Loop */
    while (1) {
        led_control(LED_ON);
        delay(0xFFFFF);
        led_control(LED_OFF);
        delay(0xFFFFF);
    }
}

编译、下载,可以看到板载LED0闪烁。

Mculover666 CSDN认证博客专家 嵌入式软件开发 IoT全栈开发
CSDN博客专家,微信公众号mculover666,凭借与生俱来的热爱专注于嵌入式领域,在自己折腾的同时,以文字的方式分享所玩、所思、所想、所悟,作为一个技术人,我们一起前进~
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页