ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Keil MDK STM32系列(四) 基于抽象外设库HAL的STM32F401开发

2021-09-14 15:02:58  阅读:258  来源: 互联网

标签:MDK HAL Keil Drivers STM32 GPIO CMSIS STM32F4xx RCC


概述

Windows下使用Keil MDK5进行 STM32F401 的开发和编译, 配合ST-LINK工具进行烧录, 使用硬件抽象库HAL.

STM32F401硬件环境和连接

略, 与SPL环境相同

STM32F4 硬件抽象库 STM32F4xx_HAL_Driver

直接下载 STM32CubeF4 MCU 固件开发包

  1. 前往 https://github.com/STMicroelectronics/STM32CubeF4
  2. 点击Code -> Download ZIP
  3. 文件比较大, 有接近300M, 解压备用

当前版本是v1.26.2, 还在继续更新.

ST硬件抽象库HAL结构说明

STM32CubeF4\Drivers 目录结构

├─BSP
├─CMSIS
│  ├─Core
│  │  ├─Include
│  │  └─Template
│  ├─Core_A
│  │  ├─Include
│  │  └─Source
│  ├─Device                    # 设备文件, 需要
│  │  └─ST
│  │      └─STM32F4xx
│  │          ├─Include
│  │          ├─Source
│  │          │  └─Templates
│  │          │      ├─arm
│  │          │      ├─gcc
│  │          │      └─iar
│  │          └─_htmresc
│  ├─docs
│  ├─DSP
│  ├─Include                   # 头文件, 需要
│  ├─Lib
│  │  ├─ARM
│  │  ├─GCC
│  │  └─IAR
│  ├─NN
│  ├─RTOS
│  └─RTOS2
└─STM32F4xx_HAL_Driver         # 外设库, 需要
    ├─Inc
    │  └─Legacy
    ├─Src
    │  └─Legacy
    └─_htmresc

按步骤手工创建项目

先组织好库文件和目录, 然后创建项目

创建目录并填充文件

以下以名称为test001的项目为例

  1. 创建工作目录 test001
  2. 在工作目录下创建 Drivers, User 2个目录
  3. 从解压后的标准外设库中, 复制 Drivers\CMSIS 目录到 Drivers, CMSIS 这个目录下只需要保留 Device 和 Include 这两个目录, 其他目录不需要
  4. 复制 Drivers\STM32F4xx_HAL_Driver 整个目录到 Drivers
  5. User
    • 复制 Projects\STM32F401-Discovery\Templates\Src 下面的 stm32f4xx_hal_msp.c stm32f4xx_it.c 到这个目录
    • 复制 Projects\STM32F401-Discovery\Templates\Inc 下面的 stm32f4xx_hal_conf.h stm32f4xx_it.h 到这个目录
    • 添加用户代码

完成后的目录结构是这样的

test001>
├─Drivers
│  ├─CMSIS
│  │  ├─Device
│  │  │  └─ST
│  │  │      └─STM32F4xx
│  │  │          ├─Include
│  │  │          ├─Source
│  │  │          │  └─Templates
│  │  │          └─_htmresc
│  │  └─Include
│  └─STM32F4xx_HAL_Driver
│      ├─Inc
│      ├─Src
│      └─_htmresc
└─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_HAL_Driver\src 下面的所有C文件, 除了以 _template.c 结尾的那几个
  • Startup
    • (F401CCU6)添加 Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm 下面的 startup_stm32f401xc.s 文件
    • (F401CDU6)添加 Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\arm 下面的 startup_stm32f401xe.s 文件
    • (F407VET6)添加的是 startup_stm32f407xx.s
  • User
    • 添加下面的C文件

修改项目包含路径

在菜单中点击Project -> Options for Target 'test001', 或者直接在图标栏中点击configure target option图标, 在弹出的对话框中

  1. 定位到c/c++标签页
  2. Define: 这个是编译参数, 写入 USE_HAL_DRIVER 这里不需要指定 STM32F401xC/STM32F401xE , 从下面的编译命令中可以看到MDK已经自动指定了
  3. Include Paths: 这里是头文件的包含路径, 如果按上面的目录结构组织的项目, 可以直接复制下面的配置
.\Drivers\CMSIS\Include;.\Drivers\CMSIS\Device\ST\STM32F4xx\Include;.\Drivers\STM32F4xx_HAL_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_HAL_Driver/Inc -I ./User
-I./RTE/_stm32f401hal001
-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_HAL_DRIVER
-o .\Objects\*.o --omf_browse .\Objects\*.crf --depend .\Objects\*.d

STM32F401CCU6/STM32F401CDU6 示例代码

下面的例子, 使用开发板自带的led灯(PC13)实现间隔1秒的亮灭效果.
在User目录下创建 main.h 和 main.c, 注意通过Keil MDK创建的时候, 要注意文件位置, 默认是放到项目根目录的, 这里要改到User目录下.

main.c

#include "main.h"

#define LED_PIN                        GPIO_PIN_13  // 指定PIN
#define LED_GPIO_PORT                  GPIOC        // 指定IO
#define LED_GPIO_CLK_ENABLE()          __HAL_RCC_GPIOC_CLK_ENABLE() // 指定启用时钟的IO

void LED_Init(void);
static void SystemClock_Config(void);
static void Error_Handler(void);

int main(void)
{
  HAL_Init();

  /* Configure the System clock to have a frequency of 84 MHz */
  //SystemClock_Config();
  LED_Init();
  while (1)
  {
    HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN);
    HAL_Delay(1000);
  }
}

void LED_Init(void) {
  LED_GPIO_CLK_ENABLE();
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = LED_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
}

static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /* The voltage scaling allows optimizing the power consumption when the device is 
     clocked below the maximum system frequency, to update the voltage scaling value 
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);


  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
 
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }  
}

static void Error_Handler(void)
{
  /* User may add here some code to deal with this error */
  while(1)
  {
  }
}

#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t* file, uint32_t line)
{ 
  while (1)
  {
  }
}
#endif

main.h

#ifndef __MAIN_H
#define __MAIN_H

#include "stm32f4xx_hal.h"

#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, 进行烧录

其他

  • 如果不能从丝印判断自己开发板芯片的型号, 可以用STM32 ST-LINK Utility连上查看
  • 开发包中的例子. 在官方库的压缩包里, 包含着这个版本各个外设功能的代码例子, 可以直接参考.

标签:MDK,HAL,Keil,Drivers,STM32,GPIO,CMSIS,STM32F4xx,RCC
来源: https://www.cnblogs.com/milton/p/15267548.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有