STM32视频笔记-1

 视频链接:

https://www.bilibili.com/video/BV1bv4y1R7dp/?spm_id_from=333.999.0.0&vd_source=270df07e19daab36f36e1863f3440455

 单片机(SCM),就是微型计算机。CISC:复杂指令集计算机。RISC:精简指令集计算机。CISC目的是便于编程,且提高存储器的利用效率,RISC的目的是提高处理器的运行速度。CISC有:8051、X86;RISC有:ARM、MIPS、RISC-V。两种结构以及优缺点如下:

image-20230329161725412

Cortex-M介绍

 STM32是基于ARM架构。Cortex-M是ARM内核的型号。Cortex-A主打高性能(手机等),Cortex-R主打实时性(军工),Cortex-M主打低功耗(智能设备)。

STM32介绍

 STM32命名规则:

image-20230329170254825

 STM32ZET6引脚图:

image-20230329172103776

 包括电源引脚(V开头),晶振引脚(8、9、23、24,提供稳定时钟信号),复位引脚(25),下载引脚,Boot引脚(48、138),GPIO引脚(P开头,通用性引脚)。

 下载引脚如下,其中串口不能进行调试,建议使用SWD接口,因为其占用引脚少,且可以调试:

image-20230329172405895

 正点原子开发板如下:

image-20230329174014783

 其中最小系统指的是:STM32F103、以及打对勾的电路,这些是可以保证MCU正常工作的最小电路组成单元。

 STM32常用开发环境:

1
2
3
1. 集成开发环境IDE:MDK
2. 仿真器:DAP、STLINK
3. 串口调试助手:XCOM

为什么要安装CH340 USB 虚拟串口驱动?

image-20230329194704126

 因为开发板STM32是CH340C协议,所以电脑上也要安装相应的CH340协议才能够解析相关信息。

 USB虚拟串口的作用:(1)USB口可以当串口来使用。(2)如果USB连接的是串口1,那么可以下载程序到开发板上。(3)可以当供电口。

 一些数据存储的位置:(1)Flash(闪存):作为单片机运行程序存储的地方。(2)SRAM:存储单片机运行过程中,产生的临时数据。

 在MDK写好程序后,使用flymcu软件(也叫做串口下载上位机),使用串口1来将程序下载到单片机:

image-20230329203930170

 上述下载使用的是ISP下载(使用串口1),如下图所示:

image-20230329204232443

 就是使用ARM厂商的BootLoader程序来进行程序下载。注:串口1又叫做USART1。上述表格第二条是下载,第一条是程序运行。

 之后是程序调试环节,是用正点原子的DAP调试器来完成的,具体配置看:

https://www.bilibili.com/video/BV1bv4y1R7dp/?p=10&spm_id_from=333.880.my_history.page.click&vd_source=270df07e19daab36f36e1863f3440455

JTAG/SWD调试原理

 Cortex-M内核含有硬件调试模块,该模块可在取指(指令断点)或访问数据(数据断点)时停止。内核停止时,可以查询内核的内部状态和系统的外部状态。完成查询后,可恢复程序执行。

MDK使用与调试

 讲解软件如何使用,非常简单。注意:(1)调试停止在断点处时,只是内核停止,外设会继续运行。(2)断点的设置要有时间观念,考虑是否会打断正常通信。

 程序编译时,Code、RO-Data、RW-Data占用Flash,而RW-Data、ZI-Data占用SRAM。

 几个程序中的窗口:

1
2
3
4
Call Stack 窗口:查看函数调用关系&局部变量
Watch窗口:(1)查看函数首地址&变量值;(2)设置全局变量在被读或写后自动停止运行
Memory窗口: 内存查看窗口
Peripheral窗口: 查看寄存器的值

几种小tricks

1
2
3
4
5
TAB:选中代码段+shift+TAB,左移;选中代码段+TAB,右移。
快速定位函数被定义的地方:先编译,选中函数+右键+Go to Definition of "xx"
快速注释:选中代码段+上述//图标
打开头文件:选中+右键+Open document
窗口视图恢复默认状态方法:window -> reset view to defaults -> reset

C语言复习

stdint.h中定义了int8_tint16_t等数据类型。

宏定义

 宏定义可以:提高效率、可读性、易改性,核心是替换(简单粗暴的替换)。

1
#define 标识符 字符串(可以是常数、字符串等)

 带参数的宏定义:

 例如,如下代码为:

1
2
#define foo(x) bar(x); baz(x)
foo(wolf)

 这将被宏扩展为:

1
bar(wolf); baz(wolf);

 另外一个例子:

1
2
3
4
#define LED1(x) do{ x?\
HAL_GPIO_WritePin(LED1_GPIO_PORT,LED1_GPIO_PIN, GPIO_PIN_SET): \
HAL_GPIO_WritePin(LED1_GPIO_PORT,LED1_GPIO_PIN,GPIO_PIN_RESET);
} while(0)

 意思就是LED1(x)是一个函数,函数内容为:

1
2
3
4
do{ x?\
HAL_GPIO_WritePin(LED1_GPIO_PORT,LED1_GPIO_PIN, GPIO_PIN_SET): \
HAL_GPIO_WritePin(LED1_GPIO_PORT,LED1_GPIO_PIN,GPIO_PIN_RESET);
} while(0)

条件编译

1
2
3
4
5
6
#if -> 编译预处理条件指令,类似if
#ifdef -> 判断某个宏是否已被定义
#ifndef -> 判断某个宏是否未被定义
#elif -> 若前面的条件不满足,则判定新的条件,类似else if
#else -> 若前面的条件不满足,则执行后面的语句,类似else
#endif -> #if,#ifdef,#ifndef的结束标志

举例如下:

image-20230412121210497

Extern声明

 放在函数/变量前,表示此函数/变量在其他文件定义,以便本文件引用。举例如下:

1
2
extern uint16_t g_usart_rx_sta;
extern void delay_us(uin t32_t nus);

类型别名(typedef)

 为现有数据类型创建一个新的名字,用来简化变量的定义。举例如下:

1
2
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;

image-20230412122054144

命名规则(不必须)

 全局变量命名一般用g_开头,全局指针命名一般用p_开头。

STM32基础知识

 MCU(单片机)厂商,经ARM公司授权,添加不同的外设=各种XX32芯片。

F1系统框架

image-20230412124058772

image-20230412124502703

存储器映射

 STM32寻址范围:2^32=4GB0x00000000-0xFFFFFFFF

1
2
1. 32位的单片机可以有32根地址线 (每根地址线有两种状态:导通或不导通)
2. 单片机内存地址访问的存储单元是按字节编址的 (而不是bit)

 ST公司将4GB划分为8个块,如下所示:(主要是前三个Block,最主要的就是Block2 片上外设,与APB1、APB2有关)

image-20230412134637126

image-20230412134929905

image-20230412135049397

寄存器映射

 寄存器是4G内存的一个地址。

 GPIO端口:GPIO(General Purpose Input/Output,通用输入输出)端口在单片机中是一种非常重要的资源。GPIO端口可以被配置为输入或输出模式,用于与外部电路、传感器、执行器等进行通信和控制。

image-20230412135609021

 举例如下,给出下面的信息:(地址偏移为0xc)

image-20230412140628561

 那么,GPIOA_ODR=0x4001080C。如果:

1
*(unsigned int *)(0x4001080C)=0xFFFF

 那么,就等于设置PA0->PA15=1

 还可以这样写:

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

image-20230412141454724

 APB1总线的基地址,也叫外设基地址 (PERIPH_BASE);此表的偏移量是相对外设基地址(PERIPH_BASE) 来说的。

image-20230412141749996

image-20230412141916620

使用结构体,完成对寄存器的映射(以GPIO为例):

image-20230412142537211

 注:FSMC全称为Flexible Static Memory Controller,是指在一些高级单片机中,用于控制片内静态存储器(比如NOR Flash、SRAM、PSRAM等)和外部静态存储器(比如SRAM、PSRAM等)的模块。

新建寄存器版本MDK工程

 简要步骤如下:

image-20230412144107646

  • 新建工程文件夹。

image-20230412144331469

image-20230412144822686

 Projects文件夹用于存放编译器 (MDK、 IAR 等)工程文件,我们主要用 MDK,为了方便区分我们在该文件夹下新建: MDK-ARM 文件夹,用于存放 MDK 的工程文件。

  • 新建工程框架。使用软件新建,保存到MDK-ARM 文件夹中。会生成以下文件夹:

image-20230412150554960

 之后可以将Listings与Objects文件夹放到之前新建的Output文件夹中去。

  • 添加文件。

image-20230412150958377

 其次,在startup组中加入启动文件(放在.\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates\arm中),如下图所示:

image-20230412151200406

 之后,修改startup_stm32f103xe.s

image-20230412151456485

 之后,向Drivers/SYSTEM文件夹中添加文件(放在.\Drivers\SYSTEM中),如下图所示:

image-20230412151814705

  • 魔术棒设置。

image-20230412152219025

 Target选项设置:

image-20230412152346786

 Output选项设置:

image-20230412152716164

 Listing选项设置:

image-20230412152939470

 C/C++选项设置(头文件包含路径在.\Drivers\CMSIS\Device\ST\STM32F1xx\Include):

image-20230412152959277

image-20230412153418214

 Debug选项设置:

image-20230412153022774

 Utilities选项设置:

image-20230412153054049

  • 添加main.c。新建main.c并保存到User文件夹里,并添加到User分组中。并对代码进行编译,并点击下载。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"

int main(void)
{
uint8_t t = 0;
sys_stm32_clock_init(9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(72, 115200); /* 串口初始化 */

while (1)
{
printf("t:%d\r\n", t);
delay_ms(500);
t++;
}
}

  • 打开XCOM V2.7,需要用type-C线连接到电脑上(主要是能进行printf显示,DAP是进行调试的,两者不一样)。分别点击下列红框:

image-20230412155235136

 在板子上点击Reset,就会重新从t:0开始。

HAL库&STM32Cube固件包解析

什么是CMSIS?

 CMSIS (微控制器软件接口标准:Cortex Microcontroller Software Interface Standard),是由ARM和与其合作的芯片厂商共同制定的标准。 相当于用户代码与硬件之间的一个中间层,HAL库属于CMSIS中的一种。

什么是HAL?

 ST 为了方便用户开发 STM32芯片开发提供了三种库:(1)标准外设库(Standard Peripheral Libraries);(2)HAL库(硬件抽象层:Hardware Abstraction Layer)(兼容性高,效率低);(3)LL库(Low Layer)(兼容性高,轻量级,效率高,但是不匹配复杂外设,例如USB)。

STM32Cube固件包解析

 它包括HAL库。

image-20230412161230225

image-20230412161345027

image-20230412161558385

 CMSIS文件夹下的重要文件:

image-20230412161652399

image-20230412162008227

HAL库框架结构

image-20230412162843448

 HAL重要文件的介绍:

image-20230412163931352

 HAL中函数与变量命名规则如下(大多数情况下成立):

image-20230412164306129

image-20230412164427565

 HAL库对寄存器位操作的相关宏定义:

image-20230412165731792

  HAL回调函数:

image-20230412170158509

HAL库使用

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

image-20230412170533924

image-20230412171429940

 Stm32f1xx_hal.c中的HAL_Init函数:

image-20230412172145407

新建HAL库版本MDK工程

 与新建寄存器版本的MDK工程类似。具体看正点给出的HAL工程示例。

 视频链接如下:

https://www.bilibili.com/video/BV1bv4y1R7dp/?p=29&spm_id_from=pageDriver&vd_source=270df07e19daab36f36e1863f3440455

STM启动过程浅析

MAP文件浅析

 MDK编译会产生中间文件,如下:

image-20230412184255690

 map文件包含了各种.c文件、函数、符号等的地址、大小、引用关系等信息。用于分析各.c文件占用FLASH和 RAM的大小,方便优化代码。Map文件组成如下:

image-20230412184801787

STM32启动模式(自举模式)

  M3/M4/M7等内核复位后,做的第一件事:

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

 厂商能够更改这两个值(0x000000000x00000004),也就引出了不同的启动模式。

image-20230412190536670

STM32启动过程(以内部FLASH启动为例)

image-20230412191136454

 启动文件介绍:

image-20230412195323073

 Reset_Handler函数介绍:

image-20230412195548522

 STM32启动过程图解:

image-20230412200334923

STM32CubeMX入门

 它是图形配置工具,它可以通过配置自动生成初始化代码。其搭配不同系列的STM32Cube固件包,即可支持不同系列的STM32芯片。

新建STM32CubeMX工程

 建立步骤如下:

image-20230412203331475

 具体配置见视频:

https://www.bilibili.com/video/BV1bv4y1R7dp/?p=35&spm_id_from=pageDriver&vd_source=270df07e19daab36f36e1863f3440455

STM32时钟系统

时钟树

 时钟clk,是具有周期性的脉冲信号。

image-20230412205759588

 其简图如下:

image-20230412210942792

 相关函数与宏:

1
2
3
1. 时钟源、锁相环: HAL_RCC_OscConfig(),HSE、HSI、LSI、LSE等
2. 系统时钟、总线: HAL_RCC_ClockConfig()
3. 使能外设时钟: HAL_RCC_PPP_CLK_ENABLE(),默认外设都是关闭时钟的

 上图中,OSC_OUT与OSC_IN是外部高速晶振,OSC32_IN与OSC32_OUT是外部低速晶振。

image-20230412210024243

1
H:high; L:low; S:speed; I:internal; E:external

配置系统时钟

image-20230412214504610

3+4+5=sys_stm32_clock_init()

如果要使用某个外设,必须先使能外设时钟!!

1
2
HAL库使能某个外设时钟的方法,如:HAL RCC_GPIOA CLK ENABLE()
HAL库禁止某个外设时钟的方法,如:HAL RCC_GPIOA CLK DISABLE()

两个时钟函数

  • HAL_RCC_OscConfig()函数:配置时钟源

image-20230412215014693

  • HAL_RCC_ClockConfig()函数:配置HCLK相关参数

    image-20230412215525183

留言

2023-03-28

© 2024 wd-z711

⬆︎TOP