STM32 学习笔记_3 程序编写和下载介绍

文章介绍了STM32程序开发的基本流程,包括从官方网站下载STM32CUBE固件包,关注CMSIS中的关键文件夹和文件,如DEVICE和INCLUDE。讨论了编译选项,如Keil中的部分编译和全编译,以及编译后的链接过程和内存占用情况。文章还对比了基于寄存器、库函数和HAL库的不同编程方式,并详细讲解了如何配置启动文件和使用库函数进行GPIO控制。最后提到了启动文件的选择和启动程序的执行原理。

程序编写和下载

固件包

可以从官网下载 STM32 CUBE 包。

image-20230414153113286

image-20230414153753564

CMSIS 里我们比较关注的文件夹是:DEVICE (包含微控制器的专用文件,启动文件),INCLUDE(M 内核,DSP 编译器相关文件)

device 文件夹挑几个自己的用就行。

文件名称描述
stm32f10x.h是所有F1系列的顶层头文件,通过条件编译来包含某个芯片的头文件,定义通用的枚举类型,定义通用的宏定义
stm32f103xe.h包含:中断编号定义、外设寄存器结构体类型定义、寄存器映射、寄存器位定义、外设判定
system_stm32f1xx.c system_stm32f1xx.h定义了系统初始化函数 SystemInit和系统时钟更新函数 SystemCoreClockUpdate
startup_stm32f103xe.s大容量F103系列芯片的启动文件

Include 里的关键文件:cmsis_armcc.h、cmsis_armclang.h、cmsis_compiler.h、cmsis_version.h、core_cm3.h 、 mpu_armv7.h

精简版的固件包 CMSIS 一般就只包括上面这些文件即可。但是这11个,一个也不能少。

Keil 编译例程

编译两个按钮,一个向下是部分编译,两个向下箭头是全部编译。对于未编译文件两个按钮等效。

点击编译后,linking 是链接,结果里面的几个数据的意义代表大小:

数据类型占用Flash or SRAM说明
CodeFlash代码 (占用 FLASH 的大小)
RO-DataFlash只读数据,一般是指 const 修饰的数据
RW-DataFlash and SRAM初值为非0的可读可写数据
ZI-DataSRAM初值为0 的可读可写数据

前三项加起来是 FLASH 占用,后两个是 SRAM 占用。

双击项目名,会打开一个 .map 的文件,文件末尾也显示了上面各项的大小和 FLASH SRAM 占用大小。

基于寄存器的方式:和51单片机一样方法,程序直接控制寄存器,底层方法。但是 STM32 寄存器太多,不宜用此方法。

基于库函数:STM32 自己封装好的库函数。有利于提高开发效率。

基于 HAL 库的方式:可以通过图形化界面开发。但是隐藏了底层逻辑。

基于寄存器

我们用和 51单片机一样的方法新建工程文件后,是不能直接使用的。需要添加启动文件。

在 MDK 里新建工程,新建到 MDK_ARM 里。

arm启动文件:下载官网标准外设库-STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm.

外设和系统(主要时钟)启动文件:STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 里的三个 .c .h 文件,system 是系统的,没有 system 的是外设的。

内核启动文件:STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\CMSIS\CM3\CoreSupport。

上面的启动文件都复制到项目新建的 startup 文件夹中。103c8t6 的话,.s 文件只留一个 _md.s 即可!

image-20230417183106577

添加好启动文件和头文件后,新建 User 文件夹,代码模板如下:

#include "stm32f10x.h"                  // Device header
int main(){
	while(1){
		
	}
}

Configration 中编码设置为 UTF-8 防止中文乱码。

魔术棒-Debug-Use 改为 STLink 下载方式。右侧 Setting-Flash Download- 勾选 Reset and Run,这样每次下载后都会重新自动复位运行。

STLINK 接上对应线后应该是电源灯常亮,测试灯闪烁。

debugger 里设置 stlink debugger,并设置 reset and run,然后插上板子点击 load,应该是只有电源指示灯常亮,板子上的测试灯应该不闪烁了。因为程序中目前什么也没有。

下面尝试点亮灯。需要三个寄存器。

  1. RCC 寄存器。RCC 外设时钟使能寄存器翻阅手册可知是 APB2 的外设,在 RCC_APB2ENR 中配置。
image-20230131151014485

4 IOPC EN 使能即打开 GPIOC 时钟。即赋值:0000 0000 0001 0000=0x00000010

  1. PC13 口。MODE13 就是配置 PC13 口的。

CNF13 要设置为推挽输出模式,即00. MODE 要配置为输出模式,最大速度 50MHZ 11。所以寄存器赋值 0x0030 0000

image-20230131151852829
  1. 端口输出寄存器写入数据。13 号口设置为低电平点亮。即:0x00000000. 0x0000 2000 就会熄灭。
image-20230131152925336
#include "stm32f10x.h"                  // Device header

int main(){
	RCC->APB2ENR=0X00000010;
	GPIOC->CRH=0X00300000;
	GPIOC->ODR=0X00000000;
	while(1){
		
	}
}

可以看出,基于寄存器的程序编写非常麻烦!要不断的查手册,而且我们还不能影响到其他位,不能这样直接赋值,要通过 & | 确保其他位不受影响。

基于库函数

新建工程套路:

  1. 新建 project,选择对应芯片型号。
  2. 新建 start library 文件夹,复制相关配置文件(启动文件,固件库里的 conf 和两个 it 文件,librarys 里的所有文件,以及要 define 的这个信息,在 stm32f10x 里image-20230418210343137image-20230131154446413)。
  3. 工程里新建对应的文件夹,添加相应配置文件。
  4. include relevant path 头文件。有钥匙标志的是只读文件。
  5. define 内定义 USE_STDPERIPH_DRIVER
  6. debug 中选择对应调试器(STLINK),settings-flash download-reset and run 勾选。

当然以后也可以建立自己风格的项目。

#include "stm32f10x.h"                  // Device header

int main(){
	//查询函数的通用方法:右键-转到定义查看,如果详细信息在注释里,复制注释关键词 crtl f 搜索。
	//enable clk
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//第一个参数:外设;第二个参数:新的状态。
	//set PC13 pin
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽输出
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	//set e level of PC13
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//high level,灭
	//GPIO_ResetBits(GPIOC,GPIO_Pin_13);//low level,亮
	while(1){
		
	}
}

寄存器部分自己查找引脚写的内容在库函数中被封装,我们只需要查询使用。

启动文件具体选择哪个?STM32F100 是超值系列,选择带 VL 的启动文件,再根据 FLASH 大小选择 LD MD HD。

image-20230131202710800

启动程序的原理:

image-20230131203440962

复位中断:程序入口。复位时启动,会调用 system_xx.c (我们的程序中是 init)和 main.c,然后就结束了。

其他中断也在其中被初始化。定义在 stm32f10x_it.c 中。自己如果想定义中断系统建议写在 stm32f10x.c 中的 PPP_IRQHandler 处。

init 设置微控制器的启动,初始化闪存接口等,仅在复位后需要调用。

然后自己写的用户文件也在紫色部分初始化。有利于程序模块化。

右侧是被动执行的资源。右上角:外设、内核外设。右下角:封装的库函数文件。conf 头文件包含了所有头文件,又被 stm32f10x.h 所包含(我们要 define USE_STDPERIPH_DRIVER 才能用)。

所以整体来看我们只需要 include stm32f10x.h 。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰海宽松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值