stm32笔记2(不定更新 )
最后更新时间:
文章总字数:
预计阅读时间:
STM32学习笔记
这个笔记是基于HAL库的,跟随正中电子教程学习。
单片机简介
特点
体积小,功耗低,集成度高,使用方便,拓展灵活
Coetex-M
ARM公司
ARM只设计内核提供IP,不涉及芯片;
对比项 | Cortex-A | Cortex-B | Cortex-C |
---|---|---|---|
特点 | 高时钟频率,长流水线,高性能 | 较高时钟频率,较长的流水线,实时性强 | 时钟频率较低,通常较低的流水线,超低功耗 |
Cortex-M3/4/7 介绍
类别 | Cortex-M3 | Cortex-M4 | Cortex-M7 |
---|---|---|---|
核心版本 | ARMv7-M | ARMv7E-M | ARMv7E-M |
指令系统 | Thumb/Thumb2 | Thumb/Thumb2 | Thumb/Thumb2 |
DSP指令扩展 | 无 | 有 | 有 |
浮点单元 | 无 | 单精度浮点单元 | 可选单/双精度浮点单元 |
流水线 | 3级 | 3级+分支预测 | 6级+分支预测 |
中断 | NVIC,NMI+1~256个中断优先级 | NVIC,NMI+1~256个中断优先级 | NVIC,NMI+1~256个中断优先级 |
系统定时器 | 24位系统滴答定时器 | 24位系统滴答定时器 | 24位系统滴答定时器 |
睡眠模式 | 集成WFI和WFE指令及退出睡眠功能 | 集成WFI和WFE指令及退出睡眠功能 | 集成WFI和WFE指令及退出睡眠功能 |
调试 | 可选JTAG和SWD调试接口 | 可选JTAG和SWD调试接口 | 可选JTAG和SWD调试接口 |
内存保护 | 可选8个区域MPU | 可选8个区域MPU | 可选8/16个区域MPU |
DPIMS/Mhz | 1.25 | 1.25 | 2.14 |
CoreMark®Mhz | 3.34 | 3.43 | 5.01 |
初识STM32
STM32 ST指意法半导体,M指MCU/MPU,32指32位
STM32命名规则
以STM32F051R8T6xxx为例:
STM32:家族(32位MCU/MPU)
F:产品类型(基础型)
051:特定功能(3位数字)
R:引脚数(64&66)
8:闪存容量(64Kbytes)
T:封装:(QFP)
6:温度范围(-40~+85)
x:固件版税
xx:选项
STM引脚分布规则
小圆点放置左下角,圆点下第一个是1脚,逆时针依次为1.2.3……
芯片背面小三角对应的是小圆点的位置。
小圆点左侧从下向上依次是1-17,下侧左到右依次是A-Q,根据表可以找到对应内容
最小系统:保证MCU正常工作的最小电路组成单元
STM32复位引脚NRST保持低电平状态1~4.5ms即可复位(按键复位)
IO口微调:当IO不够用的时候,通用GPIO和特定外设·可能要公用IO口;为方便布线,可能要调整某些IO口的位置。
STM32引脚类型
- 电源引脚(V开头)
- 晶振引脚(8、9,23、24)
- 复位引脚(25)
- 下载引脚
下载接口分为三类:
1.JTAG(PA15、PA14、PA13、PB4、PB3、VDD、GND)
2.SWD(PA14、PA13、VDD、GND)(占的少,可调式,推荐)
3.串口(PA9、PA10、VDD、GND)(不可调试)
SWD:A13SWDIO输入/输出;A14SWCLK时钟
JTAG:A13JTMS模式选择;A14JTCK时钟;A15JTDI输入;B3JTDO输出;B4TNTRST输入 - BOOT引脚
- GPIO引脚
软件及驱动
安装MDK和器件支持包
安装步骤:
- 安装MDK
- 安装器件支持包
- 拷贝下载算法到Flash文件夹,如:C:\MDK5.34\ARM|Flash
- 购买授权并注册
我选择破解
注:安装目录及路径不要汉字且越短越好,电脑系统名和用户名最好不要中文
安装仿真器驱动
安装CH340 USB虚拟串口驱动
打开exe直接点击安装即可,安装完成后,连接开发板,在设备管理器->端口可以找到对应设备
为什么要安装:可以使用通信协议
USB虚拟串口作用:
- 当串口使用
- 如果连接串口1,还可以用来下载程序
- 当USB供电口
STM32初体验
使用MDK5编译历程
部分编译和全局编译:时按两个效果相同,后续编译中,部分编译只编译当前文件
编译结果分析:
数据类型 | 占用Flash/SRAM | 说明 |
---|---|---|
Code | Flash | 代码 |
RO-Data | Flash | 只读数据,一般是指const修饰的数据 |
RW-Data | Flash&SRAM | 初值为非0的可读可写数据 |
ZI-Data | SRAM | 初值为0的可读可写数据 |
串口下载程序
下载须知
- M3、M4、M7支持串口下载程序但是ATK-XIPS.exe(正点研发的下载软件)只支持下载到内部Flash
- STM32的ISP下载常用串口1下载程序
- 使用USB虚拟串口需事先下载驱动
硬件连接
PC(USB)->USB/串口转换电路->TTL
ATK-XISP.exe下载工具配置
- 搜索选择CH340虚拟的串口,然后设置波特率
注:不同芯片内部的波特率可能不同,下载不了时可以调整波特率 - 选择需要下载的hex文件
- 勾选“编程后运行”、“校验”、“编程前执行全片擦除”
- 选择“DTR低电平复位,RTS高电平进BootLoader”
- “开始编程”
STM32启动模式(M3和M4)
通过BOOT0和BOOT1引脚设置启动模式(M3和M4)
BOOT1:X,BOOT0:0 : 主闪存存储模式
BOOT1:0,BOOT0:1 : 系统存储器
BOOT1:1,BOOT0:1 : 内置SRAM
注:自举模式只支持引脚1(USART1)进行控制
ISP下载步骤:
1.BOOT0接高电平,BOOT1接低电平
2.按复位键
程序执行一般步骤:
1.BOOT0接低电平,BOOT1接任意
2.按复位
(分别对应上面系统储存和主闪存存储模式)
仿真调试依靠软件,这里暂不演示
C语言知识点补充
位操作
运算符 | 含义 |
---|---|
& | 按位与 |
^ | 按位异或(相同取0相异取1) |
~ | 按位取反 |
<< | 左移 |
>> | 右移 |
左移移除的部分不要,补充的部分写0;右移移除的部分不要,若为正数补充的部分补0,负数则补1
宏定义
例:#define LED1 0x01
1 |
|
建议使用do{…}while(0)来构造宏定义,这样不会受大括号分号运算优先级等的影响
条件编译
指令 | 作用 |
---|---|
#if | 编译预处理条件指令,类似if |
#ifdef | 判断某个宏是否被定义 |
#ifndef | 判断某个宏是否没有被定义 |
#elif | 若前面条件不满足则判断新的条件,类似于else if |
#else | 若前面条件不满足则执行后面的语句,类似于else |
#endif | #if,#ifdef,#ifndef的结束标志 |
extern声明
放在函数/变量前,可以在所有文件中找到并使用
类型别名(typedef)
为现有的数据类型创建一个新的名字
结构为; typedef 现有类型 新名字
e.p. typedef unsigned char uint8_t
类型别名应用(Struct)
正常情况下:
1 |
|
使用typedef:
1 |
|
结构体
由若干基本数据类型集合组成的一种自定义数据类型,也叫聚合体
e.p.
定义:
1 |
|
应用:
1 |
|
指针
指针即内存的地址,指针变量就是保存了指针的变量
结构:类型名 *指针变量名
e.p.:char *p_str = "Test";
*p_str:取p_str变量的值
&p_str:取p_str变量的地址
指针使用的问题:
- 未分配(申请)内存就使用
- 越界使用
STM基础知识
STM32系统框架
F1系统框架
4个主动单元+4个被动单元
主动单元 | 被动单元 |
---|---|
Cortex M3内核 DCode总线(D-Bus) | 内部FLASH |
Cortex M3内核 系统总线 (S-Bus) | 内部SRAM |
通用DMA1 | FSMC |
通用DMA2 | AHB到APB的桥,他链接所有APB外设 |
AHB:高级高性能总线
APB:高级外围总线
再互联型产品中有3个被动5个主动
STM32选址范围
STM32寻址大小:2^32=4G(字节)
STM32寻址范围:0x0000 0000~0xFFFF FFFF
存储器映射
存储器是可以存储数据的设备,本身无地址信息,对存储器分配地址的过程称为存储器映射
存储器功能划分(F1为例)
ST将4GB(2^32)地址空间分成8块
存储块 | 功能 | 地址范围 |
---|---|---|
Block0 | Code(FLASH) | 0x0000 0000 ~ 0x1FFF FFFF(512MB) |
Block1 | SRAM | 0x2000 0000 ~ 0x3FFF FFFF(512MB) |
Block2 | 片上外设 | 0x4000 0000 ~ 0x5FFF FFFF(512MB) |
Block3 | FSMC Blank1&2 | 0x6000 0000 ~ 0x7FFF FFFF(512MB) |
Block4 | FSMC Blanc3&4 | 0x8000 0000 ~ 0x9FFF FFFF(512MB) |
Block5 | FSMC寄存器 | 0xA000 0000 ~ 0xBFFF FFFF(512MB) |
Block6 | 没用到 | 0xC000 0000 ~ 0xDFFF FFFF(512MB) |
Block7 | Cortex M3内部外设 | 0xE000 0000 ~ 0xFFFF FFFF(512MB) |
Block0(FLASH)功能划分:
功能 | 地址范围 |
---|---|
FLASH或系统存储器别名区 | 0x0000 0000~0x0007 FFFF(512KB) |
保留 | 0x0008 0000~0x07FF FFFF |
用户FLASH,用于存储用户代码 | 0x0800 0000~0x0807 FFFF(521KB) |
保留 | 0x0808 0000~0x1FFF EFFF |
系统存储器,存储出厂Bootloader | 0x1FFF F000~0x1FFF F7FF(2KB) |
选项字节,配置读保护等 | 0x1FFF F800~0x1FFF F80F(16B) |
保留 | 0x1FFF F810~0x1FFF FFFF |
Block1(SRAM)功能划分
功能 | 地址范围 |
---|---|
SRAM | 0x2000 0000~0x2000 FFFF(64KB) |
保留 | 0x2001 0000~0x3FFF FFFF |
Block2(外设)功能划分
功能 | 地址范围 |
---|---|
APB1总线外设 | 0x4000 0000~0x4000 77FF |
保留 | 0x4000 7800~0x4000 FFFF |
APB2总线外设 | 0x4001 0000~0x4000 3FFF |
保留 | 0x4001 4000~0x4001 7FFF |
AHB总线外设 | 0x4001 8000~0x4002 33FF |
保留 | 0x4002 3400~0x5FFF FFFF |
寄存器
寄存器是单片机内部一种特殊的内存,可以实现对单片机各功能的控制
STM32寄存器分类
内核寄存器:内核相关寄存器,中断寄存器,Sys Tick寄存器,内存保护寄存器,调试系统寄存器
外设寄存器:UART、IIC、SPI等
寄存器映射
给寄存器命名的过程叫做寄存器映射
例:0x4001080C–映射–>GPIOA_ODR
直接映射:*(unsigned int*)(0x4001 080C) = 0xFFFF;
定义名字之后映射:
1 |
|
寄存器描述解读
要点:
- 寄存器名字
- 偏移量及复位值
- 寄存器位表
- 位功能描述
寄存器地址计算
为方便编写代码及使用,我们将寄存器地址分为三部分
- 总线基地址(BUS_BASE_ADDR)
- 外设基于总线基地址的偏移量(PERIPH_OFFSET)
- 寄存器相对外设基地址的偏移量(REG_OFFSET)
寄存器地址=BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
总线基地址
总线 | 基地址 | 偏移量 |
---|---|---|
APB1 | 0x4000 0000 | 0 |
APB2 | 0x4001 0000 | 0x1 0000 |
AHB | 0x4001 8000 | 0x1 8000 |
APB1总线的基地址也叫做外设基地址(PERIPH_BASE)
此表的偏移量是相对外设基地址来说的
GPIO基地址及偏移量
外设 | 基地址 | 偏移量 |
---|---|---|
GPIOA | 0x4001 0800 | 0x800 |
GPIOB | 0x4001 0C00 | 0xC00 |
GPIOC | 0x4001 1000 | 0x1000 |
GPIOD | 0x4001 1400 | 0x1400 |
GPIOE | 0x4001 1800 | 0x1800 |
GPIOF | 0x4001 1C00 | 0x1C00 |
GPIOG | 0x4001 2000 | 0x2000 |
此表的偏移量是相对与APB2外设基地址(APB2PERIPH_BASE)来说的
GPIOA外设基地址及偏移量
寄存器 | 地址 | 偏移量 |
---|---|---|
GPIOA_CRL | 0X4001 0800 | 0X00 |
GPIOA_CRH | 0X4001 0804 | 0X04 |
GPIOA_IDR | 0X4001 0808 | 0X08 |
GPIOA_ODR | 0X4001 080C | 0X0C |
GPIOA_BSRR | 0X4001 0810 | 0X10 |
GPIOA_BRR | 0X4001 0814 | 0X14 |
GPIOA_LCKR | 0X4001 0818 | 0X18 |
此表的偏移量是相对与GPIOA外设基地址(GPIO_BASE)来说的
寄存器地址计算举例(GPIOA_ODR):
- 获取外设挂载在那个总线(查系统结构图)
- 获取总线基地址,APB2总线基地址:0x4001 0000
- 获取外设偏移量,GPIOA相对APB2总线偏移量:0x800
- 获取寄存器地址偏移量,ORD相对GPIOA外设基地址偏移量是0x0C
寄存器地址=BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
GPIOA_ODR=0X4001 0000 +0X800 + 0X0C = 0X4001 080C
利用结构体,我们可以很方便的完成对寄存器的映射
1 |
|
注:GPIOA_BASE: 0x4001 0800
由上面内容知道,GPIOA内每个寄存器偏移量都是0x04,uint_32大小刚好为0x04,能很好适配,利用这种方法可以方便的一次性配置一整个GPIO口
1 |
|
通过这个代码就可以一次性配置完整个GPIOA
此时:
&GPIOA->CRL: 0x4001 0800
&GPIOA_CRH: 0x4001 0804
……
配置完之后实际应用只需要GPIOA->ODR = 0xFFFF
就完成对GPIOA下的ODR的写入
新建寄存器MDK版本
新建工程前的准备工作
- 下载相关STM32Cube官方固件包
- 搭建开发环境
新建寄存器版本MDK工程步骤
- 新建工程文件夹
D/M/O/P/U文件夹,5个文件夹 - 新建一个工程框架
工程命名,选芯片 - 添加文件
建分组,添加.s/.c - 魔术棒设置
T/O/L/D/C/U,6个选项卡 - 添加mian.c并编写代码
编写自己的代码
文件夹名称 | 作用 |
---|---|
Drivers | 存放和硬件相关的驱动层文件 |
Middlewares | 存放正点提供的中间层组件文件和第三方中间层文件 |
Output | 存放工程编译输出文件 |
Projects | 存放MDK文件 |
Users | 存放HAL库用户配置文件、mian.c、中断文件,以及分散加载文件 |
新建工程时要选择启动文件,其选择依据芯片类型,具体见下表
缩写 | 释义 | Flash容量 | 型号 |
---|---|---|---|
DL_VL | 小容量产品超值系列 | 16-32K | STM32F100 |
MD_VL | 中容量产品超值系列 | 64-128K | STM32F100 |
HD_VL | 大容量产品超值系列 | 256-512K | STM32F100 |
LD | 小容量产品 | 16-32K | STM32F101/102/103 |
MD | 中容量产品 | 64-128K | STM32F101/102/103 |
HL | 大容量产品 | 256-512K | STM32F101/102/103 |
XL | 加大容量产品 | 大于512K | STM32F101/102/103 |
CL | 互联型产品 | - | STM32F105/107 |
startup.stm32f103.s中有部分代码需要修改,按正点文件修改
魔术棒设置
- Target选项卡 设置使用的编译器版本、外部晶振频率
- Output选项卡 设置Objects输出文件夹、生成.hex文件、输出浏览信息
- Listing选项卡 设置Listing输出文件夹
- C/C++选项卡 设置全局宏定义、优化等级、C99 Mode、设置头文件包含路径
- Debug选项卡 设置使用的仿真器类型、选择下载接口等
- Utilities选项卡 设置下载功能、下载算法起始地址和算法等
- Linker选项卡(可选) 添加分散加载文件(北极星/MiniPro H750等)
认识HAL库
ST提供了三种库:标准外设库、HAL库、LL库
直接操作寄存器:执行效率高、时间成本高
标准库:只兼容F0/F1/F3/F4/L1,目前停止维护
HAL库:全系列兼容、ST主推的库、兼容性、易移植性、效率低
LL库:全系列兼容,与HAL库捆绑发布,轻量级、效率高,不匹配复杂外设
STM32固件包
Documentation | Drivers | Middleware | Project | Utilities | Lisence.md | package.xml | Readme.md | Release_Notes.html |
---|---|---|---|---|---|---|---|---|
说明文档 | 驱动源码 | 中间文件 | ST官方开发板案例教程 | 公共组件 | 软件版本信息 | 固件包版本信息 | 自述 | 补充或更新说明 |
如何使用HAL库
基于CMSIS应用的程序文件描述
STM32开发文件结构分布图
HAL库用户配置文件(stm32f1xx_hl_conf.h)
裁剪HAL库外设驱动源码(不进行编译)
- 仅包含使用到的文件
- 屏蔽不使用的宏的定义
设置外部高速晶振频率(根据实际情况)
设置外部低速晶振频率(根据实际情况)
HAL库使用注意事项
- 使用HAL库出现问题还得通过参考实验手册检查是否有硬件操作问题
- 尽量不通过修改库源码实现功能,这样不方便库更新
- HAL库可能会存在错误
- 有些HAL库API函数执行效率不高,我们可能会通过操作寄存器来直接替代
新建HAL库版本MDK工程
- 新建工程前的准备工作
- 新建HAL库版本MDK工程步骤
- 下载验证
新建HAL库版本MDK工程步骤步骤
- 新建工程文件夹
D/M/O/P/U文件夹,5个文件夹 - 新建一个工程框架
工程命名,选芯片 - 添加文件
建分组,添加.s/.c - 魔术棒设置
T/O/L/D/C/U,6个选项卡 - 添加mian.c并编写代码
编写自己的代码
新建工程文件夹
文件夹名称 | 作用 |
---|---|
Drivers | 存放和硬件相关的驱动层文件 |
Middlewares | 存放正点提供的中间层组件文件和第三方中间层文件 |
Output | 存放工程编译输出文件 |
Projects | 存放MDK文件 |
Users | 存放HAL库用户配置文件、mian.c、中断文件,以及分散加载文件 |
Drivers文件夹:
文件夹名称 | 作用 |
---|---|
BSP | 存放开发板级支持包驱动代码,如各种外设驱动 |
CMSIS | 存放CMSIS底层代码,如启动文件(.s文件)等 |
SYSTEM | 存放正点原子系统级核心驱动代码,如sys.c、delay.c和usart.c等 |
STM32F1xx_HAL_Drivers | 存放ST提供的F1系列HAL库驱动代码 |
新建一个工程框架
- 新建工程
- 保存工程
- 选择主控型号
- 删除文件夹
文件夹 | 作用 |
---|---|
DebugConfig | 用于存放调试设置的信息文件(.debconf),不可删除 |
Listings | 用于存放编译过程产生的链接列表等文件 |
Objects | 用于存放编译过程产生的调试信息、.hex、预览、.lib文件等 |
添加文件
- 设置工程名和分组名
- 添加启动文件
- 添加User源码
- 添加SYSTEM源码
- 添加STM32F1xx_HAL_Driver源码
魔术棒设置
- Target选项卡 设置使用的编译器版本、外部晶振频率
- Output选项卡 设置Objects输出文件夹、生成.hex文件、输出浏览信息
- Listing选项卡 设置Listing输出文件夹
- C/C++选项卡 设置全局宏定义、优化等级、C99 Mode、设置头文件包含路径
- Debug选项卡 设置使用的仿真器类型、选择下载接口等
- Utilities选项卡 设置下载功能、下载算法起始地址和算法等
- Linker选项卡(可选) 添加分散加载文件(北极星/MiniPro H750等)
MAP文件浅析
MAP文件浅析
文件类型 | 简介 |
---|---|
.o | 可重定向对象文件,每个.c/.s文件都对应一个.o文件 |
.axf | 可执行对象文件,由.o文件连接成,仿真时需要用到此文件 |
.hex | INTEL Hex格式文件,用于下载到MCU运行,由.axf转换而来 |
.map | 连接器生成的列表文件,对分析程序存储占用情况非常有用 |
其他 | .ctf/.d/.dep/.lnp/.lst/.build_log.thml等一般用不到的 |
MAP文件是MDK编译代码后,产生的集程序、数据及IO空间的一种映射列表文件简单说就是包括了:各种.c文件、函数、符号等的地址、大小、引用关系等信息分析各.c文件占用FLASH 和 RAM的大小,方便优化代码
MAP文件组成:
组成部分 | 简介 |
---|---|
程序段交叉引用关系 | 描述各文件之间函数调用关系 |
删除映像未使用的程序段 | 描述工程中未使用到而被删除的冗余程序段 |
映像符号表 | 描述各符号(程序段/数据)在存储器中的地址、类型、大小等 |
映像内存分布图 | 描述各个程序段(函数)在存储器中的地址及占用大小 |
映像组件大小 | 给出整个映像代码(.o)占用空间汇总信息 |
STM32启动模式
STM32启动模式(也称自举模式)
M3/M4/M7等内核复位之后做的第一件事:
- 从地址0x0000 0000处去除堆栈指针MSP的初始值,该值就是栈顶地址
- 从地址0x0000 0004处去除程序计数器指针PC的初始值,该值是复位向量
F1
在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存
无法下载程序解决方案:BOOT0接3.3V,按复位,然后在下载
F4
在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存
如果要使用FSMC重映射到外部的SRAM,可以通过配置SYSCFG_MEMRMP寄存器
无法下载程序解决方案:BOOT0接3.3V,按复位,然后在下载
F7
在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存
H7
在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存
STM32启动过程(内部Flash启动为例)
启动文件介绍
- 初始化MSP 从0x0800 0000获取
- 初始化PC 从0x0800 0004获取
- 设置堆栈大小 Heap_Size(堆)、Stack_Size(栈)
- 初始化中断向量表 __Vectors定义
- 调用初始化函数 可选,如调用:SysTeminitg函数
- 调用__main 标准C库函数,执行一系列设置,最后调用main函数
Reset_Handler函数介绍
1 |
|
EXPORT:标明全局属性,可被外部调用
IMPORT:申明来自外部文件,类extern
PROC:定义子程序
ENDP:表示子程序结束
WEAK:弱定义
堆栈简介
栈(Stack) : 编译器自带分配和释放,存放函数参数、局部变量等
堆(Heap) : 程序员分配和释放,如malloc、calloc、realloc等