今日一言:
和你们这些少爷不同,
我们光是活着就已经竭尽全力了
——《银魂》
stm32(2):库函数点灯
本文主要记录新建库函数工程到点灯
手机看代码时可以左右滑动查看完整程序!
一、前期准备
- stm32单片机 x1
- stm32f10x固件库
- 自建文件夹
二、添加标准库文件
- 从标准库中解压如下两个文件夹到Lib文件夹
- 将CMSIS子目录的所有除.c和.h文件剪切到CMSIS目录下,再从startup文件夹中剪切需要的文件到CMSIS目录下,删除CMSIS所有已经多余的子目录。
对步骤2的操作详解
- (可选)删除全部多余的.html和.doc文件以及Documentation文件夹
- 前往CMSIS->CM3文件夹
- 将CoreSupport中的两个文件都剪切到CMSIS目录下
- (可选)删除空文件夹(CoreSupport)
- 前往CM3->DeviceSupport->ST->STM32F10x文件夹
- 从startup文件夹中剪切与自己的软件和硬件对应的启动文件到CMSIS目录下
- 我的是Keil-MDK, 以及STM32C8T6
- 选择的是:arm->startup_stm32f10x_md.s
- (可选)删除已经多余的startup文件夹
- 将STM32F10x目录下剩余的.c和.h文件剪切到CMSIS目录下
- (可选)删除已经多余的CM3文件夹
固件库的压缩包Project->STM32F10x_StdPeriph_Template解压三个文件到User文件夹
- 在User文件夹新建main.c文件
三、(可跳过)文件解析
1. CMSIS
CMSIS:Cortex微控制器软件接口标准(Cortex MicroController Software Interface Standard)
CMSIS的三个层级:
- 核内外设访问层(CPAL): 用于访问内核的寄存器和组件,如NVIC,调试系统等,必需。
/**************************************************************************//**
* @file core_cm3.c
* @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File
* @version V1.30
* @date 30. October 2009
******************************************************************************/
中间件访问层(MWAL):中间件的访问,暂无接触。
设备访问层(DPAL):用于定义一些硬件寄存器的地址和一些外设访问函数,必需。
/**
******************************************************************************
* @file system_stm32f10x.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
******************************************************************************
*/
注意system_stm32f10x.c的其它注释,可以发现startup文件会在main函数运行前调用SystemInit函数进行对系统时钟的初始化,故而startup_stm32f10x_xx.s 必需
/*1. This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
* factors, AHB/APBx prescalers and Flash settings).
* This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f10x_xx.s" file.
*/
startup_stm32f10x_xx.s也定义了很多中断函数,与stm32f10x_it.h和stm32f10x_it.c文件相对应:
; 这是startup_stm32f10x_xx.s部分代码...
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; ...
stm3210x_it.h部分代码:
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
STM32F10x_StdPeriph_Driver
该文件夹下放的都是stm32外设驱动,建议保留,若无需用到部分外设,可在User->stm32f10x_conf.h进行修改。足够自信的话,自己定制写也可以,但作为萌新(就是我),自然全部都要比较好。
四、新建工程和配置工程
1. 新建工程并添加组文件夹
组文件夹可以按照B站的野火/正点原子的教程新建,以下是我个人根据特立独行喜好创建的。
2. 添加.s和.c文件
.h文件不用添加,后面有另外的步骤
Keil不会因为文件夹下有什么文件就自动帮你导入工程的,故那些文件要自己导入,如果有看三、文件解析步骤的话,应该是知道为什么如此新建组文件夹,也知道什么文件需导入到哪里。如果自己不确定的话,可以按照B站的教程导入,也可以根据文件夹新建组文件夹,再对应文件夹导入文件。
3. 配置魔术棒
- 勾选Target->Usb MicroLIB
- (可选)指定Output->Select Folder for Objects…的目录
- (可选)指定Listing->Select Folder for Listings…的目录
- 添加C/C++ -> Define宏
- STM32F10X_XX(定义芯片类型)
- USE_STDPERIPH_DRIVER(使stm32f10x.h包含stm32f10x_conf.h)
- 添加C/C++ -> Include Paths
- 这里把工程可能用到的.h文件目录添加进来
- (可选)配置Debug -> Setting(右)
五、寄存器操作测试
这个是用来测试新建的工程有没有问题的。
参考《STM32中文参考手册_V10》
编写main.c
#include "stm32f10x.h"
#define RCC_AHB (unsigned int)0x40021000
#define _GPIOC (unsigned int)0x40011000
#define RCC_APB2ENR *(unsigned int*)(RCC_AHB + 0x18) // 0x18是偏移地址
#define GPIOC_CRH *(unsigned int*)(_GPIOC + 0x04 ) // 0x04是偏移地址
#define GPIOC_ODR *(unsigned int*)(_GPIOC + 0x0C ) // 0x0C是偏移地址
int main(void){
/* 打开GPIOC的时钟 */
RCC_APB2ENR |= 1<<4;
/* 配置GPIOC高寄存器 */
GPIOC_CRH &= ~(0x0F << (4*5));// 清空配置
GPIOC_CRH |= (0x01 << (4*5));// 配置推挽输出,最大速度10MHz
/* 拉低GPIO的第13脚 */
GPIOC_ODR &= ~( 1 << 13 );
}
编译结果:
六、库函数点灯(PC13)
参考《STM32固件库使用手册》
编写main.c
#include "stm32f10x.h"
int main(void){
/* GPIO_InitStruct*/
GPIO_InitTypeDef GPIO_Struct;
/* 打开GPIOC的时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
/* 配置GPIOC寄存器 */
GPIO_Struct.GPIO_Pin = GPIO_Pin_13;
GPIO_Struct.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Struct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_Init(GPIOC,&GPIO_Struct);
/* 拉低GPIO的第13脚 */
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
}
Light it up~