STM32学习笔记

STM32能做什么?

STM32是一个微控制器,自带各种常用的通信接口

1、串口----USART

2、内部集成电路----I2C

3、串行通信接口 ----SPI

4、SDIO、FSMC的超级、I2S

手环、平衡车、扫地机器人

所需资料:原理图、参考手册、数据手册

不同的芯片

去keil官网下载不同芯片的芯片包,然后双击安装

仿真器下载

STM32学习笔记_第1张图片

然后将ST-Link线插上电脑USB端再进行下一步操作

STM32学习笔记_第2张图片

STM32学习笔记_第3张图片

选择falsh大小即可

ISP下载

烧写时boot模式设置

(运行)第一种模式boot0= 0,boot1=0或1(默认0),这种模式下,STM 32处于正常的读取芯片内部存储空间的程序即运行正常程序。

(烧写)第二中模式,boot0=1,boot1=0时,进入调试模式,可以通过烧录工具把修改好的代码所生成的HEX文件烧录到芯片里面,然后把boot0跳线跳回0,执行代码

第三种,boot0=1,boot1=1, 要注意的是,一般不使用内置SRAM启动(BOOT1=1 BOOT0=1),因为SRAM掉电后数据就丢失,多数情况SRAM只是在调试时使用,也可以做其他一些用途,如做故障的局部诊断,写一段小程序载到SRAM中诊断板的其他电路,或用方法读 写板的Flash或EEPROM等,可以通过种方法解除内部Flash的读写保护,当然解除读写保护的同时Flash的内容也被自动清除,以防恶意的软件拷贝。

引脚分类

电源

晶振IO

下载IO

BOOT IO 用于设置系统的启动方式

复位IO

------------------------------上面5部分IO组成的系统我们也叫最小系统

GPIO

参考手册(编程):

片上外设的功能说明和寄存器描述

数据手册:

        功能概览

        引脚说明

        内存映射

        封装特性

什么是寄存器?

给有特定功能的内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好的地址的有特定功能的内存单元取别名的过程就叫寄存器映射

什么叫存储器映射?

给存储器分配地址的过程叫存储器映射,再分配一个地址叫重映射

芯片架构简介图

STM32学习笔记_第4张图片

ICode总线

I指的是instruction,即指令,我们写好的程序编译之后都是一条条指令,存放在 FLASH中,内核要读取这些指令来执行程序就必须通过 ICode 总线,它几乎每时每刻都需要被使用,它是专门用来取指的

DCode总线

DCode 中的 D 表示 Data,即数据,那说明这条总线是用来取数的。我们在写程序的时候,数据有常量和变量两种,常量就是固定不变的,用 C 语言中的 const 关键字修饰,是放到内部的 FLASH当中的,变量是可变的,不管是全局变量还是局部变量都放在内部的 SRAM。因为数据可以被Dcode 总线和 DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来

仲裁,决定哪个总线在取数

系统总线

系统总线主要是访问外设的寄存器,我们通常说的寄存器编程,即读写寄存器都是通过这根系统总线来完成的。

DMA总线

DMA 总线也主要是用来传输数据,这个数据可以是在某个外设的数据寄存器,可以在 SRAM,可以在内部的 FLASH。因为数据可以被 Dcode 总线和 DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。

公式

清零公式

第八位清零 保证其他位不变

temp = temp & ~(0x1<<8) 清零公式

temp = temp | ~(0x1<<8) 置一公式

建工程(寄存器版本)

新建文件夹

STM32学习笔记_第5张图片

然后打开keil5新建工程

添加三个文件

1、将启动文件拷贝过来

STM32学习笔记_第6张图片

2、stmf10x.h 手动新建,用于存放寄存器映射的代码,暂时为空

3、main.c 手动新建,用于存放main函数,暂时为空

建工程(固件库版本)

1.新建文件夹,Smart_Lock > cmsis user > inc 、 src

2. 移植固件库

STM32学习笔记_第7张图片

STM32学习笔记_第8张图片

STM32学习笔记_第9张图片

STM32学习笔记_第10张图片

添加启动文件宏和头文件路径

STM32学习笔记_第11张图片

STM32学习笔记_第12张图片

野火新建工程

新建文件夹------>

Doc

Libraries---->驱动库的源代码以及启动文件

STM32学习笔记_第13张图片

Project----->存放工程文件---->里面包含src(源文件)和inc(头文件)

User------>自己写的函数如main.c

新建工程在Project里--->选择芯片

stm32f10x_conf.h 这个文件还可配置是否使用“断言”编译选项

C/C++中的define USE_STDPERIPH_DRIVER,STM32F10X_HD

再include Paths 把全部.h文件的路径添加进去

GPIO简介

gpio是通用输入输出端口的简称,简单来说就是软件可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据的采集功能。

芯片一共 100 个引脚,其中 GPIO 就占了一大部分,所有的 GPIO引脚都有基本的输入输出功能。

STM32学习笔记_第14张图片

GPIO口分为四大模式

1.通用输出

1.1:输出推挽

即可输出高电平,又可以输出低电平。

1.2:输出开漏

只可以输出低电平,不可以输出高电平

如果要输出高电平要外接上拉电阻

注意: 当IO口配置为输出模式的时候,输入输出电路都打开。

上拉和下拉电阻:就是接了电源或者地的电阻,当IO口没有电流流过时,

可以将IO拉成高电平或者低电平,芯片内部的上拉下拉电阻一般直接禁止。

2.通用输入

1. 上拉输入

2. 下拉输入

3. 浮空输入

注意: (1)当IO口配置为开漏输出并且输出高电平的时候,与浮空输入没有任何区别。

(2)当IO配置为输入模式的时候,输出电路是关闭的。

3.复用功能------数据来自片上外设

1. 复用推挽

外设既可以发送“1”,也可以发“0”.

2. 复用开漏

外设只可以发“0”,不可以发“1”.

注意: (1)复用模式和通用模式的区别就在于IO口信号由外设驱动。

(2)复用模式对输出数据寄存器赋值,没有任何效果,但是对输入数据寄存器读值

依然可以获取IO的状态

4.模拟功能

1.输入输出电路都被关闭

2.对输入数据寄存器的读访问恒定为0

3.上下拉电阻强制被禁止

用在 AD和DA 模数和数模转换器里,一般在一些传感器用的较多。

STM32 对于IO分组是采样字母进行分组

GPIOx (x A~I) 每一个分组一共有16个IO口

0~15

PA0~PA15

PB0~PB15

总线空闲时的电平是高电平

当发送数据的时候,总线会被拉低

串口先发低位

GPIO输出初始化顺序

开时钟

清零IO口

配置IO口模式和速率

配置模式是使用端口配置低寄存器CRL和端口配置高寄存器CRH------每四个位控制一个GPIO

配置IO口数据

配置寄存器ODR

位带操作

包含了片上外设的全部寄存器

#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))

// 把一个地址转换成一个指针

#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))

// 把位带别名区地址转换成指针

#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

最终

#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出

简便方式:

define GPIO_ODR_Addr (GPIO_BASE+0x0C)

define PBout(n) *((unsigned int*)((GPIO_ODR_Addr & 0xF0000000)+0x02000000+((GPIO_ODR_Addr & 0x00FFFFFF)<<5)+(n<<2))

启动文件

汇编是上电后第一执行的文件

1、配置栈,变量(局部、全局),函数调用

2、配置堆,主要用于动态内存的分配malloc()

3、初始化中断向量表

4、编写复位程序 (最开始执行---初始化系统时钟)

5、编写中断服务函数

6、用户堆和栈的初始化

调用C库函数_main,去到C的世界

时钟树

STM32学习笔记_第15张图片

PCLK2 = HCLK = SYSCLK=PLLCLK = 72M

PCLK1=HCLK/2 = 36M 这个时钟配置也是库函数的标准配置

三种不同的时钟源可被用来驱动系统时钟

HSI振荡器时钟 一般不用,受温度条件影响较大

HSE振荡器时钟 常用

PLL时钟

配置时钟初始化函数时,要先把 RCC 外设初始化成复位状态

RCC_DeInit();

中断

NVIC 是嵌套向量中断控制器----内核的一个外设---专门用来管理中断的

两个重要库文件core_cm3.h 和 misc.h

core_cm3.h 中NVIC结构体定义

typedef struct {

__IO uint32_t ISER[8]; // 中断使能寄存器

uint32_t RESERVED0[24];

__IO uint32_t ICER[8]; // 中断清除寄存器

uint32_t RSERVED1[24];

__IO uint32_t ISPR[8]; // 中断使能悬起寄存器

uint32_t RESERVED2[24];

__IO uint32_t ICPR[8]; // 中断清除悬起寄存器

uint32_t RESERVED3[24];

__IO uint32_t IABR[8]; // 中断有效位寄存器

uint32_t RESERVED4[56];

__IO uint8_t IP[240]; // 中断优先级寄存器 (8Bit wide)

uint32_t RESERVED5[644];

__O uint32_t STIR; // 软件触发中断寄存器

} NVIC_Type;

配置终端的时候一般只用 ISER、ICER、IP 这三个寄存器

NVIC的固件库函数,不是放在core_cm3.c中 而是放在misc.c中

STM32学习笔记_第16张图片

优先级定义

在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级

先比较主优先级,再比较子优先级,都相同就比较硬件中断优先级(中断事件向量表)

优先级越高,数值越小

优先级分组

设置优先级分组可调用库函数 NVIC_PriorityGroupConfig() 实现,有关 NVIC 中断相关的库函数都在库文件 misc.c 和 misc.h 中。

中断优先级分组库函数NVIC_PriorityGroupConfig()

STM32学习笔记_第17张图片

中断编程

1、使能中断请求-----配置外设相应寄存器(小门)-----NVIC(大门)

2、配置终端优先级分组

3、配置NVIC寄存器,初始化NVIC_InitTypeDef 结构体

在misc.h中

有四个成员 1、中断源在stm32f10x IRQn_Type里面找

2、和3、根据中断优先级分组进行设值

4、 enable或者disable

4、编写中断服务函数 名称在启动文件中断向量表中找,函数写在stm32f10x_it.c里面

在配置中断的时候一般有3个编程要点

1、使能外设某个中断,这个具体由每个外设的相关中断使能位控制。比如串口有发送完成中

断,接收完成中断,这两个中断都由串口控制寄存器的相关中断使能位控制。

2、初始化NVIC_InitTypeDef 结构体,配置中断优先级分组,设置抢占优先级和子优先级,使

能中断请求。NVIC_InitTypeDef 结构体在固件库头文件 misc.h 中定义。

外部中断/事件控制器 EXTI

GPIO---->EXTI---->NVIC

STM32学习笔记_第18张图片

EXTI_InitTypeDef初始化

1-EXTI_Line:用于产生 中断/事件 线 和输入线没关系,为了确定下面那几个寄存器是哪位

2-EXTI_Mode: EXTI模式(中断/事件)

3-EXTI_Trigger:触发(上/下/上下)

4-EXTI_LineCmd: 使能或者失能( IMR/EMR)

确定哪根线,是从gpio.c中GPIO_EXTI

编程要点

1-初始化要连接到EXTI的GPIO

2-初始化EXTI用于产生中断/事件

GPIO_EXTILineConfig() 选择输入线

开输AFIO的时钟 因为配置EXTI信号源的时候需要用到AFIO的外部中断控制寄存器

初始化结构体 4个成员

3-初始化NVIC,用于处理中断

配置终端优先级分组

配置NVIC寄存器,初始化NVIC_InitTypeDef 结构体

4-编写中断服务函数

5-main函数

SysTick—系统定时器

24位,只能递减,存在于内核中

STM32学习笔记_第19张图片

SysTick控制及状态寄存器(CTRL)

STM32学习笔记_第20张图片

读取SysTick->CTRL寄存器的第十六位的值,就可以知道系统定时器计数是否为0

SysTick重装载数值寄存器(LOAD)

SysTick当前数值寄存器(VAL)

void SysTick_Delay_ms(uint32_t ms)

{

uint32_t i;

SysTick_Config(72000);

for(i=0; i

{

while( !((SysTick->CTRL) & (1<<16)) );

}

SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk; //关闭SysTick定时器

}

串口通信

物理层:

规定通信系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。其实就是硬件部分

协议层:

协议层主要规定通信逻辑,统一收发双方的数据打包、解包标准。其实就是软件部分

芯片出来的都是TTL电平

RS232转串口

主要用于工业设备之间通信

电平转换芯片一般有 MAX3232,SP3232

RS-232 与TTL电平区别

(+15 -15) (5v 0v)

USB转串口----USB->TTL

主要用于设备与电脑通信

芯片一般有 CH340、PL2303、CP2102、FT232

使用的时候电脑端需要安装电平转换芯片的驱动

原生的串口到串口----TTL->TTL

主要用于控制器和串口设备或者传感器通信,直接使用TTL电平通信

GPS模块、GSM模块、串口转WIFI模块、HC04蓝牙模块

STM32学习笔记_第21张图片

起始位:由1个逻辑 0 的数据位表示

结束位:由 0.5、 1、 1.5 或 2 个逻辑 1 的数据位表示

有效数据:在起始位后紧接着的就是有效数据,有效数据的长度常被约定为 5、 6、 7 或 8 位还有9位长

校验位:可选,为的是数据的抗干扰性。

校验方法分为:

1-奇校验(odd)、   2-偶校验(even)

3-0 校验(space)、 4-校验(mark)

5-无校验(noparity)

STM32 的 USART

通用同步异步收发器是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。

有别于 USART 还有一个 UART,它是在 USART 基础上裁剪掉了同步通信功能,只有异步

通信。我们平时用的串口通信基本都是 UART。

USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一个 USART

通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工

具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。

STM32学习笔记_第22张图片

STM32学习笔记_第23张图片

当发送的时候,发送完成的时候,TXE和TC会被置1

当接收的时候,输入寄存器有值的时候,RXNE会被置1

USART_GetFlagStatus(); 可以调用这个函数对标志位进行检测

编程要点

1) 使能 RX 和 TX 引脚 GPIO 时钟和 USART 时钟;

2) 初始化 GPIO,并将 GPIO 复用到 USART 上;

3) 配置 USART 参数;

4)串口中断优先级配置

5) 配置中断控制器并使能 USART 接收中断;

6) 使能 USART;

7) 在 USART 接收中断服务函数实现数据接收和发送。

DMA直接存储器访问

主要功能:把数据从一个地方搬到另一个地方,而且不占用CPU

不同的 DMA 控制器的通道对应着不同的外设请求,这决定了我们在软件上该怎么样编程

STM32学习笔记_第24张图片

每个通道都是独立的,每个通道都可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个,当同时收到多个请求的时候,就意味着有先后响应处理的顺序问题

仲裁器---根据寄存器中设置的优先级进行判断,如果软件优先级一样,则编号越低优先级越高,通道0优先于通道1 ,DMA1优先于DMA2

DMA存储器到存储器

编程要点

1) 使能 DMA 时钟;

2) 配置 DMA 数据参数;

3) 使能 DMA,进行传输; ----使能DMA之前先对DMA标志位进行清零操作

4) 等待传输完成,并对源数据和目标地址数据进行比较。

const 关键字将变量定义为常量类型,表示数据存储在FLASH中

一般变量---代码则存储在内部的SRAM中

DMA_GetFlagStatus(); //获取标志位

DMA存储器到外设

编程要点

编程要点

1) 配置 USART 通信功能;

2) 设置串口 DMA 工作参数;

3) 使能 DMA;

4) DMA 传输同时 CPU 可以运行其他任务。

I2C协议

物理层

STM32学习笔记_第25张图片

1、支持设备的总线-----支持多个主机与多个从机

2、使用两条总线,一条双向串行数据线(SDA),一条串行时钟线(SCL)

3、每个连接到总线的设备都有一个独立的地址,设备之间利用地址来访问

4、总线通过上拉电阻接到电源,设备空闲的时候,会输出高阻态

5、多主机同时使用总线时,通过仲裁方式防止数据冲突

6、具有三种传输模式,标准模式100kbit/s,快速模式为 400kbit/s ,高速模式下可达

3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。

7、连接到相同总线的IC数量受到总线的最大电容400pF限制

协议层

协议层规定了通讯的起始位和停止位、数据有效性、响应、仲裁、时钟同步和地址广播

IIC通讯过程的基本结构

主机写数据到从机

STM32学习笔记_第26张图片

主机由从机中读数据

STM32学习笔记_第27张图片

通讯复合格式

STM32学习笔记_第28张图片

STM32学习笔记_第29张图片

通讯的起始信号和停止信号

STM32学习笔记_第30张图片

数据的有效性

STM32学习笔记_第31张图片

地址及数据方向

总线上的每个设备都有自己的独立地址,地址可以是 7 位或 10 位,紧跟设备地址的一个数据位用来表示数据传输方向,

数据位为1的时候表示主机由从机 读数据

数据位为0的时候表示主机由从机 写数据

响应

当设备接收到I2C传输的一个字节数据或地址后,

若希望对方继续发数据,则需要向对方发送一个应答(ACK)信号,

希望结束数据传输则向对方发送一个(NACK),发送方接收到该信号后会接着发送一个停止信号,结束信号传输

SDA为高电平,表示NACK

低电平,表示ACK

硬件I2C

初始化结构体

STM32学习笔记_第32张图片

初始化I2C

使能I2C

软件I2C

通过IO口输出模拟总线的SDA信号和CLK信号

I2C-----读写EEPROM

EEPROM是一种掉电后数据不丢失的存储器,常用来配置一些配置信息,以便系统重新上电的时候加载出来

在EEPROM的

编程要点

(1) 初始化GPIO,配置通讯使用的目标引脚为开漏模式;

(2) 使能 I2C 外设的时钟;

(3) 配置 I2C 外设的模式、地址、速率等参数并使能 I2C 外设;

(4) 编写基本 I2C 按字节收发的函数;

(5) 编写读写 EEPROM 存储内容的函数;

(6) 编写测试程序,对读写数据进行校验。

SPI协议

STM32学习笔记_第33张图片

spi使用三条总线以及先选线

SCK

MOSI(Master Output, Slave Input,)

MISO(Master Input,, Slave Output)

SS 也称 CS 片选信号线

SPI通信协议

STM32学习笔记_第34张图片

NSS由高电平变低电平的时候开始通信,低到高结束通信

什么时候采样,什么时候触发由CPOL/CPHA决定

共有4种通讯模式

STM32学习笔记_第35张图片

STM32学习笔记_第36张图片

STM32学习笔记_第37张图片

编程要点

(1) 初始化通讯使用的目标引脚及端口时钟;

(2) 使能 SPI 外设的时钟;

(3) 配置 SPI 外设的模式、地址、速率等参数并使能 SPI 外设;

(4) 编写基本 SPI 按字节收发的函数;

(5) 编写对 FLASH 擦除及读写操作的的函数;

(6) 编写测试程序,对读写数据进行校验。

ADC

STM32f103 系列有 3 个 ADC,精度为 12 位,每个 ADC 最多有 16 个外部通道,2个内部通道。

规则顺序

规则顺序寄存器SQR有三个

STM32学习笔记_第38张图片

注入顺序寄存器JSQR只有一个

数据寄存器

规则数据寄存器ADC_DR只有一个,是32位的,低16位保存ADC1的数据,高16位保存ADC2的数据,但是由于ADC的精度是12位的,所以还要设置是右对齐还是左对齐

中断

数据转换之后,可以产生中断,中断分为三种:

规则通道转换结束中断,注入转换通道转换结束中断,模拟看门狗中断

DMA请求

规则和注入通道转换结束后,除了产生中断外,还可以产生 DMA 请求,把转换好的数据直接存储在内存里面。要注意的是只有 ADC1 和 ADC3 可以产生 DMA 请求。

中断读取ADC的值 编程要点

1) 初始 ADC 用到的 GPIO;

2) 设置 ADC 的工作参数并初始化;

3) 设置 ADC 工作时钟频率;

4) 设置 ADC 转换通道顺序及采样时间;

5) 配置使能 ADC 转换完成中断,在中断内读取转换完数据;

6) 使能 ADC;

7) 使能软件触发 ADC 转换。

ADC 转换结果数据使用中断方式读取,这里没有使用 DMA 进行数据传输。

DMA读取ADC数据 编程要点

1) 初始化 ADC GPIO;

2) 初始化 ADC 工作参数;

3) 配置 DMA 工作参数;

4) 读取 ADC 采集的数据;

ADC 转换结果数据使用 DMA 方式传输至指定的存储区,这样取代单通道实验使用中断服务的

读取方法。实际上,多通道 ADC 采集一般使用 DMA 数据传输方式更加高效方便

定时器

STM32学习笔记_第39张图片

基本定时器

基本定时器的功能框图:

STM32学习笔记_第40张图片

计数器时钟CK_INT

时钟源可以看RCC时钟树那张图

STM32学习笔记_第41张图片

时基

基本定时器的核心是时基,不仅基本定时器有,通用定时器和高级定时器也有。

定时时间的计算

定时器的定时时间等于计数器的中断周期乘以中断的次数。

计数器在 CK_CNT 的驱动下

计一个数的时间 则是 CK_CLK 的倒数,等于: 1/(TIMxCLK/(PSC+1))

产生一次中断的时间 则等于:1/(CK_CLK * ARR)

编程要点

(1) 开定时器时钟 TIMx_CLK, x[6,7];

(2) 初始化时基初始化结构体;

(3) 使能 TIMx, x[6,7] update 中断;

(4) 打开定时器;

(5) 编写中断服务程序

通用定时器和高级定时器的定时编程要点跟基本定时器差不多,只是还要再选择下计数器的计数模式,是向上还是向下。因为基本定时器只能向上计数,且没有配置计数模式的寄存器,默认是向上。

高级定时器

高级控制定时器 (TIM1 和 TIM8) 和通用定时器在基本定时器的基础上引入了外部引脚,可以实现输入捕获和输出比较功能。

高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车 (断路) 功能,这些功能都是针对工业电机控制方面。

高级定时器时钟源有4个

1、内部时钟源CK_INT 最常用

2、外部时钟模式 1:外部输入引脚 TIx(x=1,2,3,4)

3、 外部时钟模式 2:外部触发输入 ETR

4、内部触发输入(ITRx)

时基单元

STM32学习笔记_第42张图片

其中重复计数器RCR是高级定时器独有

输入捕获

输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输入信号的脉宽和测量 PWM 输入信号的频率和占空比这两种。

输入捕获的大概的原理就是,当捕获到信号的跳变沿的时候,把计数器 CNT 的值锁存到捕获寄存器 CCR 中,把前后两次捕获到的 CCR 寄存器中的值相减,就可以算出脉宽或者频率。如果捕获的脉宽的时间长度超过你的捕获定时器的周期,就会发生溢出,这个我们需要做额外的处理。

输入通道

需要被测量的信号从定时器的外部引脚 TIMx_CH1/2/3/4 进入

输入滤波器和边沿检测器

当输入的信号存在高频干扰的时候,我们需要对输入信号进行滤波,即进行重新采样。

边沿检测器用来设置信号在捕获的时候是什么边沿有效,可以是上升沿,下降沿,或者是双边沿,

捕获通道

当发生捕获的时候,计数器 CNT 的值就会被锁存到捕获寄存器中。

这里我们要搞清楚输入通道和捕获通道的区别,输入通道是用来输入信号的,捕获通道是用来捕

获输入信号的通道,一个输入通道的信号可以同时输入给两个捕获通道。

预分频器

ICx 的输出信号会经过一个预分频器,用于决定发生多少个事件时进行一次捕获。具体的由寄存

器 CCMRx 的位 ICxPSC 配置,如果希望捕获信号的每一个边沿,则不分频。

捕获寄存器

经过预分频器的信号 ICxPS 是最终被捕获的信号,当发生捕获时(第一次),计数器 CNT 的值会

被锁存到捕获寄存器 CCR 中,还会产生 CCxI 中断,相应的中断位 CCxIF(在 SR 寄存器中)会

被置位,通过软件或者读取 CCR 中的值可以将 CCxIF 清 0。如果发生第二次捕获(即重复捕获:

CCR 寄存器中已捕获到计数器值且 CCxIF 标志已置 1),则捕获溢出标志位 CCxOF(在 SR 寄存

器中)会被置位, CCxOF 只能通过软件清零

输出比较

输出比较就是通过定时器的外部引脚对外输出控制信号,有冻结、将通道 X(x=1,2,3,4)设置为

匹配时输出有效电平、将通道 X 设置为匹配时输出无效电平、翻转、强制变为无效电平、强制变

为有效电平、 PWM1 和 PWM2 这八种模式,具体使用哪种模式由寄存器 CCMRx 的位 OCxM[2:0]

配置。其中 PWM 模式是输出比较中的特例,使用的也最多。

比较寄存器

当计数器 CNT 的值跟比较寄存器 CCR 的值相等的时候,输出参考信号 OCxREF 的信号的极性

就会改变,其中 OCxREF=1(高电平)称之为有效电平, OCxREF=0(低电平)称之为无效电平,

并且会产生比较中断 CCxI,相应的标志位 CCxIF(SR 寄存器中)会置位。然后 OCxREF 再经过

一系列的控制之后就成为真正的输出信号 OCx/OCxN。

死区发生器

在生成的参考波形 OCxREF 的基础上,可以插入死区时间,用于生成两路互补的输出信号 OCx

和 OCxN,死区时间的大小具体由 BDTR 寄存器的位 DTG[7:0] 配置。死区时间的大小必须根据与

输出信号相连接的器件及其特性来调整。

STM32学习笔记_第43张图片

输出控制

STM32学习笔记_第44张图片

输入捕获应用

输入捕获一般应用在两个方面,一方面是脉冲跳变沿时间测量,另一方面是PWM输入检测

1.1测量频率

1.2测量脉宽

PWM输入模式

测量脉宽和频率还有一个更简便的方法就是使用 PWM 输入模式,该模式是输入捕获的特例,只

能使用通道 1 和通道 2,通道 3 和通道 4 使用不了。与上面那种只使用一个捕获寄存器测量脉宽

和频率的方法相比, PWM 输入模式需要占用两个捕获寄存器。

STM32学习笔记_第45张图片

当使用 PWM 输入模式的时候,因为一个输入通道 (TIx) 会占用两个捕获通道 (ICx),所以一个定

时器在使用 PWM 输入的时候最多只能使用两个输入通道 (TIx)。

PWM 信号由输入通道 TI1 进入,因为是 PWM 输入模式的缘故,信号会被分为两路,一路是

TI1FP1,另外一路是 TI2FP2。其中一路是周期,另一路是占空比,具体哪一路信号对应周期还

是占空比,得从程序上设置哪一路信号作为触发输入,作为触发输入的哪一路信号对应的就是

周期,另一路就是对应占空比。作为触发输入的那一路信号还需要设置极性,是上升沿还是下降

沿捕获,一旦设置好触发输入的极性,另外一路硬件就会自动配置为相反的极性捕获,无需软件

配置。一句话概括就是:选定输入通道,确定触发信号,然后设置触发信号的极性即可,因为是

PWM 输入的缘故,另一路信号则由硬件配置,无需软件配置。当使用 PWM 输入模式的时候必须将从模式控制器配置为复位模式

STM32学习笔记_第46张图片

输出比较应用

输出比较模式总共8种,最常用的就是PWM模式

PWM输出模式

pwm输出就是对外输出脉宽(占空比)可调的方波信号,信号频率由自动装载寄存器ARR的值决定,占空比由比较寄存器CCR的值决定。

PWM 模式分为两种, PWM1 和 PWM2,总得来说是差不多,就看你怎么用而已,具体的区别见

表格 PWM1 与 PWM2 模式的区别 。

STM32学习笔记_第47张图片

以计数器 CNT 计数的方向不同还分为边沿对齐模式和中心对齐模式。

pwm边缘对齐模式

在递增计数模式下,计数器从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0

开始计数并生成计数器上溢事件

STM32学习笔记_第48张图片

在边沿对齐模式下,计数器 CNT 只工作在一种模式,递增或者递减模式。这里我们以 CNT 工作

在递增模式为例,在中, ARR=8, CCR=4, CNT 从 0 开始计数,当 CNT

为有效的高电平,于此同时,比较中断寄存器 CCxIF 置位。当 CCR=

为无效的低电平。然后 CNT 又从 0 开始计数并生成计数器上溢事件,以此循环往复。

pwm中心对齐模式

在中心对齐模式下,计数器 CNT 是工作做递增/递减模式下。开始的时候,计数器 CNT 从 0 开始

计数到自动重载值减 1(ARR-1),生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从 0 开始重新计数

STM32学习笔记_第49张图片

图 PWM1 模式的中心对齐波形 是 PWM1 模式的中心对齐波形, ARR=8, CCR=4。第一阶段计数

器 CNT 工作在递增模式下,从 0 开始计数,当 CNT

CCR=

的值开始递减,当 CNT>CCR 时, OCxREF 为无效的低电平,当 CCR=>CNT>=1 时, OCxREF 为

有效的高电平。

在波形图上我们把波形分为两个阶段,第一个阶段是计数器 CNT 工作在递增模式的波形,这个

阶段我们又分为 ① 和 ② 两个阶段,第二个阶段是计数器 CNT 工作在递减模式的波形,这个阶段

我们又分为 ③ 和 ④ 两个阶段。要说中心对齐模式下的波形有什么特征的话,那就是 ① 和 ③ 阶

段的时间相等, ② 和 ④ 阶段的时间相等。

中心对齐模式又分为中心对齐模式 1/2/3 三种,具体由寄存器 CR1 位 CMS[1:0] 配置。具体的区

别就是比较中断中断标志位 CCxIF 在何时置 1:中心模式 1 在 CNT 递减计数的时候置 1,中心对

齐模式 2 在 CNT 递增计数时置 1,中心模式 3 在 CNT 递增和递减计数时都置 1。

4个结构体

1、定时器基本初始化结构体

1 typedef struct {

2 uint16_t TIM_Prescaler; // 预分频器

3 uint16_t TIM_CounterMode; // 计数模式

4 uint32_t TIM_Period; // 定时器周期

5 uint16_t TIM_ClockDivision; // 时钟分频

6 uint8_t TIM_RepetitionCounter; // 重复计算器

7 } TIM_TimeBaseInitTypeDef;

2、输出比较结构体

1 typedef struct {

2 uint16_t TIM_OCMode; // 比较输出模式

3 uint16_t TIM_OutputState; // 比较输出使能

4 uint16_t TIM_OutputNState; // 比较互补输出使能

5 uint32_t TIM_Pulse; // 脉冲宽度

6 uint16_t TIM_OCPolarity; // 输出极性

7 uint16_t TIM_OCNPolarity; // 互补输出极性

8 uint16_t TIM_OCIdleState; // 空闲状态下比较输出状态

9 uint16_t TIM_OCNIdleState; // 空闲状态下比较互补输出状态

10 } TIM_OCInitTypeDef;

3、输入比较结构体

1 typedef struct {

2 uint16_t TIM_Channel; // 输入通道选择

3 uint16_t TIM_ICPolarity; // 输入捕获触发选择

4 uint16_t TIM_ICSelection; // 输入捕获选择

5 uint16_t TIM_ICPrescaler; // 输入捕获预分频器

6 uint16_t TIM_ICFilter; // 输入捕获滤波器

7 } TIM_ICInitTypeDef;

4、断路和死区结构体

1 typedef struct {

2 uint16_t TIM_OSSRState; // 运行模式下的关闭状态选择

3 uint16_t TIM_OSSIState; // 空闲模式下的关闭状态选择

4 uint16_t TIM_LOCKLevel; // 锁定配置

5 uint16_t TIM_DeadTime; // 死区时间

6 uint16_t TIM_Break; // 断路输入使能控制

7 uint16_t TIM_BreakPolarity; // 断路输入极性

8 uint16_t TIM_AutomaticOutput; // 自动输出使能

9 } TIM_BDTRInitTypeDef;

PWM互补输出实验

编程要点

(1) 定时器用到的 GPIO 初始化

(2) 定时器时基结构体 TIM_TimeBaseInitTypeDef 初始化

(3) 定时器输出比较结构体 TIM_OCInitTypeDef 初始化

(4) 定时器刹车和死区结构体 TIM_BDTRInitTypeDef 初始化

你可能感兴趣的:(stm32,学习,单片机,嵌入式硬件,物联网)