stm32笔记2(不定更新 )

文章发布时间:

最后更新时间:

文章总字数:
5.3k

预计阅读时间:
20 分钟

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引脚类型

  1. 电源引脚(V开头)
  2. 晶振引脚(8、9,23、24)
  3. 复位引脚(25)
  4. 下载引脚
    下载接口分为三类:
    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输入
  5. BOOT引脚
  6. GPIO引脚

软件及驱动

安装MDK和器件支持包

安装步骤:

  1. 安装MDK
  2. 安装器件支持包
  3. 拷贝下载算法到Flash文件夹,如:C:\MDK5.34\ARM|Flash
  4. 购买授权并注册我选择破解

注:安装目录及路径不要汉字且越短越好,电脑系统名和用户名最好不要中文

安装仿真器驱动

安装CH340 USB虚拟串口驱动

打开exe直接点击安装即可,安装完成后,连接开发板,在设备管理器->端口可以找到对应设备

为什么要安装:可以使用通信协议

USB虚拟串口作用:

  1. 当串口使用
  2. 如果连接串口1,还可以用来下载程序
  3. 当USB供电口

STM32初体验

使用MDK5编译历程

部分编译和全局编译:时按两个效果相同,后续编译中,部分编译只编译当前文件

编译结果分析:

数据类型 占用Flash/SRAM 说明
Code Flash 代码
RO-Data Flash 只读数据,一般是指const修饰的数据
RW-Data Flash&SRAM 初值为非0的可读可写数据
ZI-Data SRAM 初值为0的可读可写数据

串口下载程序

下载须知

  1. M3、M4、M7支持串口下载程序但是ATK-XIPS.exe(正点研发的下载软件)只支持下载到内部Flash
  2. STM32的ISP下载常用串口1下载程序
  3. 使用USB虚拟串口需事先下载驱动

硬件连接

PC(USB)->USB/串口转换电路->TTL

ATK-XISP.exe下载工具配置

  1. 搜索选择CH340虚拟的串口,然后设置波特率
    注:不同芯片内部的波特率可能不同,下载不了时可以调整波特率
  2. 选择需要下载的hex文件
  3. 勾选“编程后运行”、“校验”、“编程前执行全片擦除”
  4. 选择“DTR低电平复位,RTS高电平进BootLoader”
  5. “开始编程”

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
2
3
4
#define LED(x) do{x?\
HAL_GPIO_WritePin(LED1_GPIO_PORT,LED_GPIO_PIN,GPIO_PIN_SET):\
HAL_GPIO_WritePin(LED1_GPIO_PORT,LED_GPIO_PIN,GPIO_PIN_RESET):\
}while(0)

建议使用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
2
3
4
5
6
7
struct GPIO_TypeDef
{
__IO uint32_t CRL;
__IO uint32_t CHR;

};
struct GPIO_TypeDef gpiox

使用typedef:

1
2
3
4
5
6
7
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CHR;

}GPIO_TypeDef;
GPIO_TypeDef gpiox

结构体

由若干基本数据类型集合组成的一种自定义数据类型,也叫聚合体

e.p.
定义:

1
2
3
4
5
6
7
8
struct student
{
char *name;
int num;
int age;
char group;
float score;
}stu1,st2;

应用:

1
2
3
struct student stu3,stu4;
stu3.name="Trump";
stu3.age=114;

指针

指针即内存的地址,指针变量就是保存了指针的变量

结构:类型名 *指针变量名

e.p.:char *p_str = "Test";

*p_str:取p_str变量的值
&p_str:取p_str变量的地址

指针使用的问题:

  1. 未分配(申请)内存就使用
  2. 越界使用

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
2
#define GPIOA_ODR   *(unsigned int*)(0x4001080C)
GPIOA_ODR = 0xFFFF;

寄存器描述解读

要点:

  1. 寄存器名字
  2. 偏移量及复位值
  3. 寄存器位表
  4. 位功能描述

寄存器地址计算

为方便编写代码及使用,我们将寄存器地址分为三部分

  1. 总线基地址(BUS_BASE_ADDR)
  2. 外设基于总线基地址的偏移量(PERIPH_OFFSET)
  3. 寄存器相对外设基地址的偏移量(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):

  1. 获取外设挂载在那个总线(查系统结构图)
  2. 获取总线基地址,APB2总线基地址:0x4001 0000
  3. 获取外设偏移量,GPIOA相对APB2总线偏移量:0x800
  4. 获取寄存器地址偏移量,ORD相对GPIOA外设基地址偏移量是0x0C

寄存器地址=BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
GPIOA_ODR=0X4001 0000 +0X800 + 0X0C = 0X4001 080C

利用结构体,我们可以很方便的完成对寄存器的映射

1
2
3
4
5
6
7
8
9
10
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
}GPIO_TypeDef;

注:GPIOA_BASE: 0x4001 0800

由上面内容知道,GPIOA内每个寄存器偏移量都是0x04,uint_32大小刚好为0x04,能很好适配,利用这种方法可以方便的一次性配置一整个GPIO口

1
#define GPIOA ((GPIO_TypeDef*)GPIOA_BASE)

通过这个代码就可以一次性配置完整个GPIOA

此时:
&GPIOA->CRL: 0x4001 0800
&GPIOA_CRH: 0x4001 0804
……

配置完之后实际应用只需要GPIOA->ODR = 0xFFFF就完成对GPIOA下的ODR的写入

新建寄存器MDK版本

新建工程前的准备工作

  1. 下载相关STM32Cube官方固件包
  2. 搭建开发环境

新建寄存器版本MDK工程步骤

  1. 新建工程文件夹
    D/M/O/P/U文件夹,5个文件夹
  2. 新建一个工程框架
    工程命名,选芯片
  3. 添加文件
    建分组,添加.s/.c
  4. 魔术棒设置
    T/O/L/D/C/U,6个选项卡
  5. 添加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中有部分代码需要修改,按正点文件修改

魔术棒设置

  1. Target选项卡 设置使用的编译器版本、外部晶振频率
  2. Output选项卡 设置Objects输出文件夹、生成.hex文件、输出浏览信息
  3. Listing选项卡 设置Listing输出文件夹
  4. C/C++选项卡 设置全局宏定义、优化等级、C99 Mode、设置头文件包含路径
  5. Debug选项卡 设置使用的仿真器类型、选择下载接口等
  6. Utilities选项卡 设置下载功能、下载算法起始地址和算法等
  7. 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应用的程序文件描述

基于CMSIS应用的程序文件描述

STM32开发文件结构分布图

STM32开发文件结构分布

HAL库用户配置文件(stm32f1xx_hl_conf.h)

  1. 裁剪HAL库外设驱动源码(不进行编译)

    1. 仅包含使用到的文件
    2. 屏蔽不使用的宏的定义
  2. 设置外部高速晶振频率(根据实际情况)

  3. 设置外部低速晶振频率(根据实际情况)

HAL库使用注意事项

  1. 使用HAL库出现问题还得通过参考实验手册检查是否有硬件操作问题
  2. 尽量不通过修改库源码实现功能,这样不方便库更新
  3. HAL库可能会存在错误
  4. 有些HAL库API函数执行效率不高,我们可能会通过操作寄存器来直接替代

新建HAL库版本MDK工程

  1. 新建工程前的准备工作
  2. 新建HAL库版本MDK工程步骤
  3. 下载验证

新建HAL库版本MDK工程步骤步骤

  1. 新建工程文件夹
    D/M/O/P/U文件夹,5个文件夹
  2. 新建一个工程框架
    工程命名,选芯片
  3. 添加文件
    建分组,添加.s/.c
  4. 魔术棒设置
    T/O/L/D/C/U,6个选项卡
  5. 添加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库驱动代码
新建一个工程框架
  1. 新建工程
  2. 保存工程
  3. 选择主控型号
  4. 删除文件夹
文件夹 作用
DebugConfig 用于存放调试设置的信息文件(.debconf),不可删除
Listings 用于存放编译过程产生的链接列表等文件
Objects 用于存放编译过程产生的调试信息、.hex、预览、.lib文件等
添加文件
  1. 设置工程名和分组名
  2. 添加启动文件
  3. 添加User源码
  4. 添加SYSTEM源码
  5. 添加STM32F1xx_HAL_Driver源码
魔术棒设置
  1. Target选项卡 设置使用的编译器版本、外部晶振频率
  2. Output选项卡 设置Objects输出文件夹、生成.hex文件、输出浏览信息
  3. Listing选项卡 设置Listing输出文件夹
  4. C/C++选项卡 设置全局宏定义、优化等级、C99 Mode、设置头文件包含路径
  5. Debug选项卡 设置使用的仿真器类型、选择下载接口等
  6. Utilities选项卡 设置下载功能、下载算法起始地址和算法等
  7. 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等内核复位之后做的第一件事:

  1. 从地址0x0000 0000处去除堆栈指针MSP的初始值,该值就是栈顶地址
  2. 从地址0x0000 0004处去除程序计数器指针PC的初始值,该值是复位向量
F1

在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存

F1

无法下载程序解决方案:BOOT0接3.3V,按复位,然后在下载

F4

在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存

F4

如果要使用FSMC重映射到外部的SRAM,可以通过配置SYSCFG_MEMRMP寄存器
无法下载程序解决方案:BOOT0接3.3V,按复位,然后在下载

F7

在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存

F7

H7

在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存

H7

STM32启动过程(内部Flash启动为例)
启动文件介绍
  1. 初始化MSP 从0x0800 0000获取
  2. 初始化PC 从0x0800 0004获取
  3. 设置堆栈大小 Heap_Size(堆)、Stack_Size(栈)
  4. 初始化中断向量表 __Vectors定义
  5. 调用初始化函数 可选,如调用:SysTeminitg函数
  6. 调用__main 标准C库函数,执行一系列设置,最后调用main函数
Reset_Handler函数介绍
1
2
3
4
5
6
7
8
9
Reset_Handler   PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP

EXPORT:标明全局属性,可被外部调用
IMPORT:申明来自外部文件,类extern
PROC:定义子程序
ENDP:表示子程序结束
WEAK:弱定义

堆栈简介

栈(Stack) : 编译器自带分配和释放,存放函数参数、局部变量等
堆(Heap) : 程序员分配和释放,如malloc、calloc、realloc等

STM32启动过程图解

STM32启动过程图解

给穷逼一点钱吧!
支付宝(AliPay)
微信(WeiChat)