STM32F1笔记
STM32F1笔记
中断
NVIC(嵌套向量中断控制器)
| NVIC相关寄存器 | 位数 | 寄存器个数 | 备注 |
|---|---|---|---|
| ISER(Set Enable, 中断使能寄存器) | 32 | 8 | 每个位控制一个中断 |
| ICER(Clear Enable, 中断除能寄存器) | 32 | 8 | 每个位控制一个中断 |
| AIRCR(应用程序中断及复位控制寄存器) | 32 | 1 | 位[10:8]控制优先级分组 |
| IPR(中断优先级寄存器) | 8 | 240 | 8个位对应一个中断,而STM32只使用高4位 |
中断优先级
-
抢占优先级(pre):高抢占优先级可以打断正在执行的低抢占优先级中断
-
响应优先级(sub):当抢占优先级相同时,响应优先级高的先执行,但是不能相互打断
抢占和响应都相同的情况下,自然优先级(
中断向量表中的优先级)越高的,先执行数值越小,优先级越高
中断优先级分组
| 优先级分组 | AIRCR[10:8] | IPRx bit[7:4]分配 | 分配结果 |
|---|---|---|---|
| 0 | 111 | None : [7:4] | 0位抢占优先级,4位响应优先级 |
| 1 | 110 | [7] : [6:4] | 1位抢占优先级,3位响应优先级 |
| 2 | 101 | [7:6] : [5:4] | 2位抢占优先级,2位响应优先级 |
| …… | …… | …… | …… |
一个工程中,一般只设置一次中断优先级分组
EXTI(外部(扩展)中断事件控制器)
EXTI(F1)包含20个产生事件/中断请求的边沿检测器,即总共20条EXTI线
中断与事件区别:
- 中断:要进入NVIC,有相应的中断服务函数,需要CPU处理
- 事件:不进入NVIC,仅用于内部硬件自动控制的,如:TIM、DMA、ADC
STM32仅有:7个外部中断服务函数
- EXTI0~4:5个
- EXTI9_5:共用一个
- EXTI15_10:共用一个
串口
比特率:每秒传输的比特数,单位bit/s
波特率:每秒传输的码元(一个码元就是一个脉冲信号)数,单位Baud
比特率:波特率 * \(\log_2^m\),M(进制数)表示每个码元承载的信息
RS-232电平与COMS/TLL电平对比
| 逻辑1 | 逻辑0 | |
|---|---|---|
| RS232电平 | -15V~3V | +3V~+15V |
| COMS电平(3.3V) | 3.3V | 0V |
| TTL电平(5V) | 5V | 0V |
RS-232异步通信协议
- 启动位:必须占1位,保持逻辑0电平
- 有效数据位:可选5~9个位长,LSB(最低有效位)在前,MSB在后
- 校验位:可选占1位长,也可以没有该位
- 停止位:必须有,可选0.5、1、1.5、2个位长,保持逻辑1电平
USART框图

波特率计算公式
通用公式推演过程:\(baud = \frac{f_{ck}}{16 * USARTDIV} \Rightarrow USARTDIV = \frac{f_{ck}}{16 * baud}\)
写入波特率寄存器:\(USART1\to BRR = USARTDIV * 16 + 0.5 = \frac{f_{ck}}{16 * baud} *16 + 0.5 = \frac{f_{ck}}{baud} + \frac{1}{2}\) (四舍五入)
HAL库USART中断回调机制
USART/UART异步通信配置步骤
- 配置串口工作参数:HAL_UART_Init()
- 串口底层初始化: HAL_UART_MspInit() 配置GPIO、NVIC、CLOCK等
- 开启串口异步接收中断:HAL_UART_Receive_IT()
- 设置中断优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
- 编写中断服务函数:USARTx_IRQHandler()、UARTx_IRQHandler()
- 串口数据发送:USART_DR、HAL_UART_Transmit()
IWDG
IWDG(Indepndent watchdog):独立看门狗,能产生系统复位信号的计数器 ,主要应用在一些需要高稳定性的产品中,并且对时间精度要求比较低(因为时钟来自RC振荡器)的场合。
特性
-
递减计数器
-
时钟由独立的RC振荡器提供(可在待机和停止模式下运行)
-
看门狗被激活后,当递减计数器计数到0x000时产生复位
-
喂狗:在计数器到0之前,重装载计数器的值,防止复位
作用
异常概念:外界电磁干扰或者自身系统(硬件或软件)异常,造成程序跑飞,如:陷入某个不正常的循环,打断正常程序运行
主要用于检测外界电磁干扰,或者硬件异常造成的程序跑飞
独立看门狗时异常处理的最后手段,不可依赖,应当在设计时尽量避免异常的发生
框图
IWDG溢出时间计算
- \(T_{out}\):看门狗溢出时间
- \(f_{IWDG}\):看门狗的时钟源频率
- \(psc\):看门狗预分配系数
- \(rlr\):看门狗重装载值
配置步骤
- 取消PR(预分频系数寄存器)/RLR(重装载值寄存器)写保护,设置IWDG预分频系数和重装载值,启动IWDG:HAL_IWDG_Init()
- 及时喂狗,即写入0xAAAA到IWDG_KR:HAL_IWDG_Refresh()
WWDG
WWDG(Window watchdog):窗口看门狗,能产生系统复位信号和提前唤醒中断的计数器,主要应用再需要检测程序运行时间的场合(因为使用的时钟源来自系统总线)
特性
- 递减计数器
- 当递减计时器值从0x40减到0x3F时复位(即T6位跳变到0)
- 计时器的值大于W[6:0]值时喂狗会复位
- 提前唤醒中断(EWI):当递减计数器 等于0x40时可产生
作用
用于检测单片机程序运行时效是否精准,主要检测软件异常
工作原理图
框图
WWDG超时时间计算
- \(T_{out}\):WWDG超时时间(没喂狗)
- \(F_{wwdg}\):WWDG时钟源频率
- \(4096\):WWDG固定的预分频系数
- \(2^{WDGTB}\):WWDG_CFR寄存器设置的预分频系数值
- \(T[5:0]\):WWDG计数器低六位
配置步骤
- WWDG工作参数初始化:HAL_WWDG_Init()
- WWDG Msp初始化:HAL_WWDG_MspInit() 配置NVIC、CLOCK等
- 设置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_Enable()
- 编写中断服务函数:WWDG_IRQHandler()->HAL_WWDG_IRQHandler
- 重定义提前唤醒回调函数:HAL_WWDG_EarlyWakeupCallback()
- 在窗口期内喂狗:HAL_WWDG_Refresh()
IWDG与WWDG主要区别
| 对比点 | IWDG | WWDG |
|---|---|---|
| 时钟源 | LSI(40KHz或32KHz) | PCLK1或PCLK3 |
| 复位条件 | 递减计数到0 | 计数值大于W[6:0]值或减到0x3F |
| 中断 | 没有中断 | 计数器减到0x40可产生中断 |
| 递减计数器位数 | 12位(最大计数范围:4096~0) | 7位(最大计数范围:127~63) |
| 应用场合 | 防止程序跑飞,死机,死循环 | 检测程序时效,防止软件异常 |
定时器
定时器使用精准的时基,通过硬件的方式,实现定时功能,其核心就是计数器。
分类
特性表
| 定时器类型 | 定时器 | 计数器位数 | 计数模式 | 预分频系数(整数) | 产生DMA请求 | 捕获/比较通道 | 互补输出 |
|---|---|---|---|---|---|---|---|
| 基本定时器 | TIM6 TIM7 |
16 | 递增 | 1~65535 | 可以 | 0 | 无 |
| 通用定时器 | TIM2 TIM3 TIM4 TIM5 |
16 | 递增、递减、中央对齐 | 1~65535 | 可以 | 4 | 无 |
| 高级定时器 | TIM1 TIM8 |
16 | 递增、递减、中央对齐 | 1~65535 | 可以 | 4 | 有 |
功能区别
| 定时器类型 | 主要功能 |
|---|---|
| 基本定时器 | 没有输入输出通道,常用作时基,即定时功能 |
| 通用定时器 | 具有多路独立通道,可用于捕获/输出比较,也可作时基 |
| 高级定时器 | 除具备通用定时器所有功能外,还具备死区控制的互补信号输出、刹车输入等功能(可用作电机控制、数字电源设计等) |
计数模式及溢出条件
| 计数器模式 | 溢出条件 |
|---|---|
| 递增计数模式 | CNT = = ARR |
| 递减计数模式 | CNT == 0 |
| 中心对齐模式 | CNT == ARR - 1、CNT == 1 |
溢出时间计算
- \(T_{out}\):定时器溢出时间
- \(F_t\):定时器时钟源频率
- \(ARR\):自动重装载器的值
- \(PSC\):预分频寄存器的值
基本定时器
- 可用于触发DAC
- 在更新事件(计数器溢出)时,可产生中断/DMA请求
框图
配置步骤
- 配置定时器基础工作参数:HAL_TIM_Base_Init()
- 定时器基础MSP初始化:HAL_TIM_Base_MspInit() 配置NVIC、CLOCK等
- 使能更新中断并启动计数器:HAL _TIM_Base_Start_IT()
- 设置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
- 编写中断服务函数:TIMx_IRQHandler()等->HAL_TIM_IRQHandler()
- 编写定时器更新中断回调函数:HAL_TIM_PeriodElapsedCallback()
通用定时器
- 可用于触发DAC、ADC
- 在更新事件、触发事件、输入捕获、输出比较时,会产生中断/DMA请求
- 4个独立通道,可用于:输入捕获、输出比较、输出PWM、单脉冲模式
- 使用外部信号控制定时器且可实现多定时器互连的同步电路
- 支持编码器和霍尔传感器电路等
框图
计时器时钟源
- 内部时钟(CK_INT):来自外设总线APB提供的时钟
- 外部时钟模式1:外部输入引脚(TIx):来自定时器通道1或者通道2引脚的信号
- 外部时钟模式2:外部触发输入(ETR):来自可以复用位TIMx_ETR的IO引脚
- 内部触发输入(ITRx):用于芯片内部其他通用/高级定时器级联
外部时钟模式1
外部时钟模式2
使用一个定时器作为另一个定时器的预分频器
PWM
通用定时器输出PWM原理
PWM模式
PWM输出配置步骤
- 配置定时器基础工作参数:HAL_TIM_PWM_Init()
- 定时器PWM输出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置PWM模式/比较值等:HAL_TIM_PWM_ConfigChannel()
- 使能输出并启动计数器:HAL_TIM_PWM_Start()
- 修改比较值控制占空比(可选):__HAL_TIM_SET_COMPARE()
- 使能通道预装载(可选):__HAL_TIM_ENABLE_OCxPRELOAD()
输入捕获
输入捕获脉宽测量原理
配置步骤
- 配置定时器基础工作参数:HAL_TIM_IC_Init()
- 定时器输入捕获MSP初始化:HAL_TIM_IC_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置输入通道映射、捕获边沿等:HAL_TIM_IC_ConfigChannel()
- 设置优先级,使能中断:HAL_NVIC_SetPriority()、 HAL_NVIC_EnableIRQ()
- 使能定时器更新中断:__HAL_TIM_ENABLE_IT()
- 使能捕获、捕获中断及计数器:HAL_TIM_IC_Start_IT()
- 编写中断服务函数:TIMx_IRQHandler()等 -> HAL_TIM_IRQHandler()
- 编写更新中断和捕获回调函数:HAL_TIM_PeriodElapsedCallback()、HAL_TIM_IC_CaptureCallback()
脉冲计数
配置步骤
- 配置定时器基础工作参数:HAL_TIM_IC_Init()
- 定时器输入捕获MSP初始化:HAL_TIM_IC_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置定时器从模式等:HAL_TIM_SlaveConfigSynchro()
- 使能输入捕获并启动计数器:HAL_TIM_IC_Start()
- 获取计数器的值:__HAL_TIM_GET_COUNTER()
- 设置计数器的值:__HAL_TIM_SET_COUNTER()
高级定时器
- 重复计数器(计数器每次上溢或者下溢都能使重复计数器减1,减到0时,再发生一次溢出就会产生更新事件)
- 死区时间带可编程的互补输出
- 断路输入,用于将定时器的输出信号置于用户可选的安全配置中
框图
重复计数器特性
输出指定个数PWM实验配置步骤
- 配置定时器基础工作参数:HAL_TIM_PWM_Init()
- 定时器PWM输出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置PWM模式/比较值等:HAL_TIM_PWM_ConfigChannel()
- 配置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_Enable()
- 使能定时器更新中断:__HAL_TIM_ENABLE_IT()
- 使能输出、主输出(仅高级定时器有)、计数器:HAL_TIM_PWM_Start()
- 编写中断服务函数:TIMx_IRQHandler()等 -> HAL_TIM_IRQHandler()
- 编写更新中断回调函数:HAL_TIM_PeriodElapsedCallback()
输出比较
实验原理
配置步骤
- 配置定时器基础工作参数:HAL_TIM_OC_Init()
- 定时器输出比较MSP初始化:HAL_TIM_OC_MspInit()
- 配置输出比较模式等:HAL_TIM_OC_ConfigChannel()
- 使能通道预装载:__HAL_TIM_ENABLE_OCxPRELOAD()
- 使能输出、主输出、计数器:HAL_TIM_OC_Start()
- 修改捕获/比较器的值:__HAL_TIM_SET_COMPARE()
带死区控制的互补输出
因为元器件有延迟特性,所以需要加上死区时间控制。
死区时间计算
-
确定\(t_{DTS}\)的值:\(f_{DTS} = \frac{F_t}{2^{CKD[1:0]}}\)
![CKD[1:0]](https://images.cnblogs.com/cnblogs_com/blogs/839742/galleries/2449093/o_250325115516_image.png)
-
判断DTG[7:5],选择计算公式
![DTG[7:5]](https://images.cnblogs.com/cnblogs_com/blogs/839742/galleries/2449093/o_250325115520_image.png)
-
代入选择的公式计算
刹车(断路)功能
使能刹车功能:将TIMx_BDTR的BKE位置1,刹车输入信号极性由BKP位设置
使能刹车功能后:由TIMx_BDTR的MOE、OSSI、OSSR位,TIMx_CR2的OISx、OISxN位,TIMx_CCER的CCxE、CCxNE位控制OCx和OCxN输出状态
无论何时,OCx和OCxN输出都不能同时处在有效电平
配置步骤
- 配置定时器基础工作参数:HAL_TIM_PWM_Init()
- 定时器PWM输出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置PWM模式/比较值等:HAL_TIM_PWM_ConfigChannel()
- 配置刹车功能、死区时间等:HAL_TIMEx_ConfigBreakDeadTime()
- 使能输出、主输出、计数器:HAL_TIM_PWM_Start()
- 使能互补输出、主输出、计数器:HAL_TIM_PWMN_Start
PWM输入模式
工作原理
时序
配置步骤
- 配置定时器基础工作参数:HAL_TIM_IC_Init()
- 定时器捕获输入MSP初始化:HAL_TIM_IC_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置IC1/2映射、捕获边沿等:HAL_TIM_IC_ConfigChannel()
- 配置从模式,触发源等:HAL_TIM_SlaveConfigSynchro()
- 配置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
- 使能捕获、捕获中断及计数器:HAL_TIM_IC_Start_IT()、HAL_TIM_IC_Start()
- 编写中断服务函数:TIMx_IRQHandler()等 -> HAL_TIM_IRQHandler()
- 编写输入捕获回调函数:HAL_TIM_IC_CaptureCallback()
电容触摸按键
电容触摸按键可以等效为一个电容。
优势:无机械装置,使用寿命长,非接触式感应,面板不用开孔,简洁美观,防水性好。
- 无手指触摸:上电时,电阻作用下,电容Cs进行充电,直到电容充满,这时会有一个充电时间Tcs
- 有手指触摸,上电时,电阻作用下,电容Cs和Cx进行充电,直到电容充满,这时会有一个充电时间Tcx
充电过程可以看成是一个信号从低电平变为高电平的过程,可以利用定时器输入捕获功能计算充电时间(注:电容的初始状态要为0,即一开始就要放电)
先测量到的无触摸时充电时间Tcs作为比较基准,然后定时循环测量充电时间T与Tcs作比较,如果超过一定的阈值就认为有手指触摸。
检测电容触摸按键过程
- TPAD引脚设置为推挽输出,输出低电平,实现电容放电到地
- TPAD引脚设置为浮空输入 (IO复位后的状态),电容开始充电
- 同时开启TPAD引脚的输入捕获功能,开始捕获高电平
- 等待充电过程中,上升沿触发(充电放到Vth(上升沿的电压值))
- 计算充电时间(定时器捕获/比较寄存器获取)
OLED
驱动原理
- 选择驱动芯片时序:8080、6800、SPI、IIC等,根据时序实现数据写入/读取
- 初始化序列:由厂家提供,用于初始化屏幕
- 实现画点函数、读点函数(可选):基于这两个函数可以实现各种绘图功能
8080并口读/写过程
-
设置DC为高(数据)/低(命令):根据写入/读取的数据类型
-
拉低片选:选中芯片
-
设置RD/WR为低:取决于要读数据还是写数据
-
准备数据
-
拉高RD/WR,出现上升沿:在RD的上升沿,将数据锁存到数据线D[7:0]上;在WR上升沿,数据写入到芯片中
写时序示例:
GRAM
GRAM(图形显示数据RAM)是一个位映射静态RAM,保存要显示的位模式。内存大小为128 * 64位,可分为8页,从页0到页7,用于黑白128 * 64点阵显示。
页可以理解为行的选择。8页控制64行,每1页选中8行
三种设置内存地址模式:
- 页地址模式
- 水平地址模式
- 垂直地址模式
页地址模式
对GRAM进行操作时,列地址指针会自动递增。当列地址指针到达列结束地址时,重置为开始地址,但页地址指针不变。用户碧玺设置新的页面和列地址,以便访问下一页GRAM内容。
GRAM与OLED屏幕坐标对应关系表
注:GRAM设定为gram[列数][页数]
一个通用的点(x, y)置1表达式为:GRAM[x][y / 8] |= 1 << (y % 8 )
LCD
LCD屏幕驱动原理与OLED基本一致,详细参考OLED驱动原理
LCD 8080时序信号
| 信号 | 名称 | 控制状态 | 作用 |
|---|---|---|---|
| CS | 片选 | 低电平 | 选中器件,低电平有效,先选中,后操作 |
| WR | 写 | ↑ | 写信号,上升沿有效,用于数据/命令写入 |
| RD | 读 | ↑ | 读信号,上升沿有效,用于数据/命令读取 |
| RS | 数据/命令 | 0:命令 1:数据 |
表示当前是写数据还是命令,也叫DC信号 |
| D[15:0] | 数据线 | 无 | 双向数据线,可以写入/读取驱动IC数据 |
一般只需要6条指令即可完成对LCD的基本使用(以ILI9341为例)
| 指令(HEX) | 名称 | 作用 |
|---|---|---|
| 0xD3 | 读ID | 用于读取LCD控制器的ID,区分型号用 |
| 0x36 | 访问控制 | 设置GRAM读取方向,控制显示方向 |
| 0x2A | 列地址 | 一般用于设置X坐标 |
| 0x2B | 页地址 | 一般用于设置Y坐标 |
| 0x2C | 写GRAM | 用于往LCD写GRAM数据(地址自增,支持连续写入) |
| 0x2E | 读GRAM | 用于往LCD读GRAM数据(地址自增,支持连续读) |
FSMC
FSMC(Flexible Static Memory Controller)灵活静态存储控制器,用于驱动SRAM、NOR FLASH、NAND FLASH及PC卡类型的存储器。配置好FSMC,定义一个指向这些地址的指针,通过对指针操作就可以直接修改存储单元内容,FSMC自动完成读写命令和数据访问操作,不需要程序去实现时序。
框图
| FSMC信号 | 信号方向 | 功能 |
|---|---|---|
| FSMC_NE[x] | 输出 | 片选引脚,x=1…4,每个对应不同的内存块 |
| FSMC_CLK | 输出 | 时钟(同步突发模式使用) |
| FSMC_A[25:0] | 输出 | 地址总线 |
| FSMC_D[15:0] | 输出/输入 | 双向数据总线 |
| FSMC_NOE | 输出 | 输出使能(“N”表明低电平有效信号) 类似于8080 RD读信号 |
| FSMC_NWE | 输出 | 写使能 |
| FSMC_NWAIT | 输入 | NOR闪存要求FSMC等待的信号 |
| FSMC_NADV | 输出 | 地址、数据线复用时作锁存信号 |
使用FSMC驱动LCD
时序
FSMC可以产生多种时序来控制外部存储器
NR/PSRAM控制器产生的异步时序就有5种,总体分为两类:一类是模式1,其他为拓展模式
拓展模式相对于模式1来说时序时间参数设置可以不同,满足存储器读写时序不一样的需求
| 访问模式 | 对应的外部存储器 | 时序特性 |
|---|---|---|
| 模式1 | SRAM/CRAM | OE在读时序片选过程不翻转,有NBL信号,无NADV信号 |
| 模式A | SRAM/PSRAM(CRAM) | OE在读时序片选过程翻转,有NBL信号,无NADV信号 |
| 模式B/2 | NOR FLASH | OE在读时序片选过程不翻转,无NBL信号,有NADV信号 |
| 模式C | NOR FLASH | OE在读时序片选过程翻转,无NBL信号,有NADV信号 |
| 模式D | 带地址扩展的异步操作 | OE在读时序片选过程翻转,无NBL信号,有NADV信号,存在地址保存时间 |
地址映射
使用FSMC外接存储器,其存储单元是映射到STM32的内部寻址空间的。从FSMC角度看,可以把外部存储器分为固定大小为256M字节的四个存储块;每个存储块分4个区,每个区管理64M字节空间
HADDR总线是转换到外部存储器的内部AHB地址线,简单来说,从CPU通过AHB总线到外部信号线之间的关系,HADDR是字节地址,而存储器访问不都是按字节访问,接到存储器的地址线与其数据宽度相关。
LCD使用16位数据线
数据宽度位16位时,地址存在偏移
8080接口种的RS信号,用FSMC的某根A地址线进行替换。以本人手中的STM32F103ZE开发板为例,FSMC_A10接到RS线上,使用FSMC_NE4片选信号。
- 当FSMC_A10为高电平时(即RS为高电平),FSMC_D[15:0]被理解为数据
- 当FSMC_A10为低电平时(即RS为低电平),FSMC_D[15:0]被理解为命令
确定代替的地址:
- 确认FSMC_NE4基地址:0x6C00 0000 计算公式NEx(x=1~4):0x6000 0000 + (0x0400 0000 * (x - 1))
- 确认FSMC_A10对应地址值:\(2^{10} * 2(双字节数据) = 0x800\) 计算公式:FSMC_Ay(y=0~25): \(2^y * 2\)
- 确认两个地址:代表LCD命令的地址:0x6C00 0000;代表LCD数据的地址:0x6C00 0800
相关寄存器
| 寄存器 | 名称 | 作用 |
|---|---|---|
| FSMC_BCR4 | 片选控制寄存器 | 包含存储器块的信息(存储器类型/数据宽度等) |
| FSMC_BTR4 | 片选时序寄存器 | 设置读操作时序参数(ADDSET/DATAST) 如果未设置FSMC_BCRx种的EXTMOD位,则读写公用该寄存器 |
| FSMC_BWTR4 | 写时序寄存器 | 设置写操作时序参数(ADDSET/DATAST) |
在ST官方提供的寄存器定义里面,并没有定义FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx等这个单独的寄存器,而是将他们进行了一些组合,规则如下:
FSMC_BCRx和FSMC_BTRx,组合成BTCR[8]寄存器组,他们的对应关系如下:
BTCR[0]对应FSMC_BCR1,BTCR[1]对应FSMC_BTR1
BTCR[2]对应FSMC_BCR2,BTCR[3]对应FSMC_BTR2
BTCR[4]对应FSMC_BCR3,BTCR[5]对应FSMC_BTR3
BTCR[6]对应FSMC_BCR4,BTCR[7]对应FSMC_BTR4
FSMC_BWTRx则组合成BWTR[7]寄存器组,他们的对应关系如下:
BWTR[0]对应FSMC_BWTR1,BWTR[2]对应FSMC_BWTR2,
BWTR[4]对应FSMC_BWTR3,BWTR[6]对应FSMC_BWTR4,
BWTR[1]、BWTR[3]和BWTR[5]保留,没有用到
RTC
RTC(Real Time Clock 实时时钟),本质是计数器,技术频率通常为秒,专门用来记录时间,能在MCU掉电后运行,功耗低
配置步骤
- 使能电源时钟并使能后备域访问:__HAL_RCC_PWR_CLK_ENABLE 使能电源时钟、__HAL_RCC_BKP_CLK_ENABLE 使能备份时钟、HAL_PWR_EnableBkUpAccess 使能备份访问
- 开启LSE/选择RTC时钟源/使能RTC时钟:HAL_RCC_OscConfig 开启LSE、HAL_RCCEx_PeriphCLKConfig 选择RTC时钟源、__HAL_RCC_RTC_ENABLE 使能RTC时钟
- 初始化RTC,设置分频值以及工作参数:HAL_RTC_Init 初始化RTC、HAL_RTC_MspInit 完成RTC底层初始化工作
- 设置RTC的日期和时间:操作寄存器方式实现rtc_set_time
- 获取RTC当前日期和时间:定义rtc_get_time函数
低功耗
STM32具有运行、睡眠、停止和待机四种工作模式。
上电后默认是在运行模式,当内核不需要继续运行时,可以选择后面三种低功耗模式。
- 睡眠模式:内核时钟关闭
- 对系统影响小
- 节能效果最差
- 停止模式:内核时钟关闭、 关闭内核逻辑电路的所有时钟、关闭时钟系统
- 节能效果好,程序不会复位
- 恢复时间长(要重新起振)
- 退出停止模式,HSI RC振荡器被选为系统时钟
- 待机模式:内核时钟关闭、 关闭内核逻辑电路的所有时钟、关闭时钟系统、关闭电压调节器
- 节能效果最好
- 程序会复位,少数条件才能唤醒
- 待机模式下所有I/O引脚处于高阻态,除了复位引脚、被使能的唤醒引脚等
配置步骤
-
睡眠模式:
- 初始化WKUP为中断触发源:参考外部中断引脚初始化
外设低功耗处理(可选) - 进入睡眠模式:HAL_PWR_EnterSLEEPMode()
- 等待WKUP外部中断唤醒
- 初始化WKUP为中断触发源:参考外部中断引脚初始化
-
停止模式:
- 初始化WKUP为中断触发源:参考外部中断引脚初始化
外设低功耗处理(可选) - 进入停止模式:HAL_PWR_EnterSTOPMode()
- 等待WKUP外部中断唤醒
- 重新设置时钟、重新选择滴答时钟源、失能systick中断
- 初始化WKUP为中断触发源:参考外部中断引脚初始化
-
待机模式:
- 初始化WKUP为中断触发源(可选):参考外部中断引脚初始化
外设低功耗处理(可选) - 使能电源时钟:__HAL_RCC_PWR_CLK_ENABLE()
- 使能WKUP的唤醒功能:HAL_PWR_EnableWakeUpPin()
- 清除唤醒标记WUF:__HAL_PWR_CLEAR_FLAG()
- 进入待机模式:HAL_PWR_EnterSTANDBYMode()
- 初始化WKUP为中断触发源(可选):参考外部中断引脚初始化
DMA
DMA(Direct Memory Access,直接存储器访问),DMA传输 将数据从一个地址空间复制到另一个地址空间。DMA传输无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。
仲裁器管理DMA通道请求分为两个阶段:软件阶段(1)、硬件阶段(2)
第一阶段(软件阶段):每个通道的优先级可在DMA_CCRx寄存器中设置,有四个等级:最高、高、中和低优先级。
第二阶段(硬件阶段):如果两个请求有相同软件优先级,较低编号的通道比较高编号的通道有较高的优先级。
注意:
大容量芯片中,DMA1控制器拥有高于DMA2控制器的优先级
多个请求通过逻辑或输入到DMA控制器,只能有一个请求有效。
传输串口数据配置步骤
- 使能DMA时钟:__HAL_RCC_DMA1_CLK_ENABLE
- 初始化DMA:HAL_DMA_Init函数初始化DMA相关参数、__HAL_LINKDMA函数连接DMA和外设
- 使能串口的DMA发送,启动传输:HAL_UART_Transmit_DMA
查询DMA传输状态:__HAL_DMA_GET_FLAG查询通道传输状态、__HAL_DMA_GET_COUNTER获取当前传输剩余数据量
DMA中断使用:HAL_NVIC_EnableIRQ、HAL_NVIC_SetPriority、编写中断服务函数
IIC
IIC(Inter Integrated Circuit,集成电路总线),是一种同步 串行 半双工通信总线。
IIC协议可以归纳为:
- 三个信号:起始信号(主机)、停止信号(主机)、应答信号(主机、从机)
- 两个注意:数据有效性、数据传输顺序
- 一个状态:空闲状态
IIC时序:
硬件IIC和软件IIC对比:
| IIC | 用法 | 速度 | 稳定性 | 管脚 |
|---|---|---|---|---|
| 硬件IIC | 比较复杂 | 快 | 较稳定 | 需使用特定管脚 |
| 软件IIC | 操作过程比较清晰 | 较慢 | 稳定 | 任意管脚,比较灵活 |
软件IIC配置步骤
- 使能SCL和SDA对应时钟:__HAL_RCC_GPIOB_CLK_ENABLE()
- 设置GPIO工作模式:SDA开漏/SCL推挽输出模式,使用HAL_GPIO_Init初始化
- 编写基本信号:起始信号 停止信号 应答信号 (主机:send ack send nack,从机:wait ack)
- 编写读和写函数:iic_read_byte、iic_send_byte(注意:发送完成,主机释放SDA)
SPI
SPI(Serial Peripheral Interface,串行外设设备接口),是一种高速、全双工、同步的通信总线
与IIC对比
| 功能说明 | SPI总线 | IIC总线 |
|---|---|---|
| 通信方式 | 同步 串行 全双工 | 同步 串行 半双工 |
| 总线接口 | MOSI、MISO、SCL、CS | SDA、SCL |
| 拓扑结构 | 一主多从/一主一从 | 多主从 |
| 从机选择 | 片选引脚选择 | SDA上设备地址片选 |
| 通信速率 | 一般50MHz以下 | 100kHz、400kHz、3.4MHz |
| 数据格式 | 8位/16位 | 8位 |
| 传输顺序 | MSB/LSB | MSB |
框图
数据收发流程
工作模式
- 时钟极性(CPOL):没有数据传输时时钟线的空闲状态电平。0:SCK在空闲状态保持低电平;1:SCK在空闲状态保持高电平
- 时钟相位(CPHA):时钟线在第几个时钟边沿采样数据。0:SCK的第一(奇数)边沿进行数据位采样,数据在第一个时钟边沿被锁存;1:0:SCK的第二(偶数)边沿进行数据位采样,数据在第二个时钟边沿被锁存
| SPI工作模式 | CPOL | CPHA | SCL空闲状态 | 采样边沿 | 采样时刻 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 低电平 | 上升沿 | 奇数边沿 |
| 1 | 0 | 1 | 低电平 | 下降沿 | 偶数边沿 |
| 2 | 1 | 0 | 高电平 | 下降沿 | 奇数边沿 |
| 3 | 1 | 1 | 高电平 | 上升沿 | 偶数边沿 |
NOR FLASH
FLASH是常用的用于储存数据的半导体器件,它具有容量大,可重复擦写、按“扇区/块”擦除、掉电后数据可继续保存的特性。
FLASH是有一个物理特性:只能写0,不能写1,写1靠擦除。
FLASH主要有NOR Flash和NAND Flash两种类型,NOR和NAND是两种数字门电路。
| 类型 | 特点 | 应用举例 |
|---|---|---|
| NOR FLASH | 基于字节读写,读取速度快,独立地址/数据线,无坏块,支持XIP | 25Qxx、程序ROM |
| NAND FLASH | 基于块读写,读取速度稍慢,地址数据线共用,有坏块,不支持XIP | EMMC、SSD、U盘等 |
驱动步骤
- SPI配置步骤:
- SPI工作参数配置初始化:工作模式、时钟极性、时钟相位等 HAL_SPI_Init
- 使能SPI时钟和初始化相关引脚:GPIO模式设为复用推挽输出模式 HAL_SPI_MspInit
- 使能SPI:__HAL_SPI_ENABLE
- SPI传输数据:HAL_SPI_Transmit发送数据、HAL_SPI_Receive接收数据、HAL_SPI_TransmitReceive进行发送与接收
- 设置SPI传输速度(可选):操作SPI_CR1寄存器中的波特率控制位(注:设置前需要先使能SPI,设置完成后再使能SPI)
- NOR FLASH(NM25Q128)配置步骤:
- 初始化片选引脚与SPI接口:相关GPIO初始化、SPI初始化(模式、位数、分频、MSB等)
- NM25Q128读取:0x03指令 + 24位地址 + 读取数据
- NM25Q128扇区擦除:0x06指令 + 等待空闲 + 0x20指令 + 24位地址 + 等待空闲
- NM25Q128写入:擦除扇区(可选) + 0x06指令 + 0x02指令 + 24位地址 + 写入数据 + 等待空闲
写数据需要注意:
- 是否需要擦除?
- 写入数据(是否需要换页?是否需要换扇区?)
- 遵循:读、改、写的原则(解释:读取扇区原数据,在一个大数组中改写需要变动的数据,然后再擦除扇区数据,将大数组中的数据写回扇区中)
RS485
RS485是串行通信标准,使用差分信号传输,抗干扰能力强,常用于工控领域,具有强大的组网功能,在串口基础协议之上还制定了MODBUS协议。
串口基础协议:仅指封装了基本数据包格式的协议(基于数据位)
MODBUS协议:使用基本数据包组成通讯帧格式的高层应用协议(基于数据包或字节)
| 通信接口 | 通信方式 | 信号线 | 电平标准 | 拓扑结构 | 通信距离 | 通讯速率 | 抗干扰能力 |
|---|---|---|---|---|---|---|---|
| TTL | 全双工 | TX/RX/GND | 逻辑1 : 2.4~5 V 逻辑0 : 0~0.4 V |
点对点 | 1米 | 100kbps | 弱 |
| RS232 | 全双工 | TX/RX/GND | 逻辑1 : -(15~3) V 逻辑0 : +(3~15) V |
点对点 | 100米 | 20kbps | 较弱 |
| RS485 | 半双工 | 差分线AB | 逻辑1 : +(2~6)V 逻辑0 : -(2~6)V |
多点双向 | 1200米 | 100kbps | 强 |
配置步骤
- 配置串口工作参数:HAL_UART_Init()
- 串口底层初始化:配置GPIO、NVIC、CLOCK等
- 开启串口异步接收中断:__HAL_UART_ENABLE_IT()
- 设置优先级、使能中断:HAL_NVIC_SetPriority、HAL_NVIC_EnableIRQ()
- 编写中断服务函数:USARTx_IRQHandler()、HAL_UART_Receive()
- 串口数据发送:USART_DR、HAL_UART_Transmit()
ADC
ADC(Analog-to-Digital Converter,模拟/数字转换器)
常见ADC类型
| ADC电路类型 | 优点 | 缺点 |
|---|---|---|
| 并联比较型 | 转换速度最快 | 成本高、功耗高,分辨率低 |
| 逐次逼近型 | 结构简单,功耗低 | 转换速度较慢 |
-
并联比较型:
- 优点:转换速度快
- 缺点:成本高、功耗高、分辨率低

-
逐次逼近型(STM32所用):
- 优点:结构简单、低功耗
- 缺点:转换速度慢
- 特点:分辨率和采样速度相互矛盾,分辨率越高,采样速率越低

ADC特性参数
- 分辨率:表示ADC能辨别的最小模拟量,用二进制位数表示,比如:8、10、12、16位等
- 转换时间:表示完成一次A/D转换所需要的时间,转换时间越短,采样率就可以越高
- 精度:最小刻度基础上叠加各种误差的参数,精度受ADC性能、温度和气压等影响
- 量化误差:用数字量近似表示模拟量,采用四舍五入原则,此过程产生的误差为量化误差

框图

转换序列
A/D转换被组织为两组:规则组(常规转换组)和注入组(注入转换组)
规则组最多可以有16个转换,注入组最多有4个转换
注入组可以打断规则组的转换


触发源
- ADON位触发转换(仅限F1系列):当ADC_CR2寄存器的ADON位为1时,再单独给ADON位写1,只能启动规则组转换
- 外部事件触发转换:外部事件触发转换分为规则组外部触发和注入组外部触发

转换时间
ADC转换时间\(T_{CONV} = 采样时间 + 12.5个周期\)
采样时间可通过SMPx[2:0]位设置,x=0~17
- SMP = 000:1.5 个 ADC 时钟周期
- SMP = 001:7.5 个 ADC 时钟周期
- SMP = 010:13.5 个 ADC 时钟周期
- SMP = 011:28.5 个 ADC 时钟周期
- SMP = 100:41.5 个 ADC 时钟周期
- SMP = 101:55.5 个 ADC 时钟周期
- SMP = 110:71.5 个 ADC 时钟周期
- SMP = 111:239.5 个 ADC 时钟周期
中断
ADC中断事件汇总表:
| 中断事件 | 事件标志 | 使能控制位 |
|---|---|---|
| 规则通道转换结束 | EOC | EOCIE |
| 注入通道转换结束 | JEOC | JEOCIE |
| 设置了模拟看门狗状态位 | AWD | AWDIE |
| 溢出(F1没有) | OVR | OVRIE |
DMA请求(只适用于规则组):规则组每个通道转换结束后,除了可以产生中断外,还可以产生DMA请求,我们利用DMA及时把转换好的数据传输到指定的内存里,防止数据被覆盖。
转换模式
| 转换组/转换模式 | 单次转换模式(只触发一次转换) | 连续转换模式(自动触发下一次转换) 注意:只有规则组才能触发该模式 |
|---|---|---|
| 规则组 | 转换结果被储存在ADC_DR EOC(转换结束)标志位被置1 如果设置了EOCIE位,则产生中断然后ADC停止 | 转换结果被储存在ADC_DR EOC(转换结束)标志位被置1 如果设置了EOCIE位,则产生中断 |
| 注入组 | 转换结果被储存在ADC_DRJx JEOC(转换结束)标志位被置1 如果设置了JEOCIE位,则产生中断然后ADC停止 | 转换结果被储存在ADC_DRJx JEOC(转换结束)标志位被置1 如果设置了JEOCIE位,则产生中断 自动注入:将JAUTO位置1 |
扫描模式
- 关闭扫描模式:ADC只转换ADC_SQRx或ADC_JSQR选中的第一个通道进行转换
- 使用扫描模式:ADC会扫描所有被ADC_SQRx或ADC_JSQR选中的所有通道
一种比较少用的模式:不连续采样模式(F1手册称为:间断模式),只适用在扫描模式下。若间断模式通道计数设置为2,则每次只会转换两个通道,如1/2->3/4->5/6顺序。
单通道ADC采集实验配置步骤
- 配置ADC工作参数、ADC校准:HAL_ADC_Init()、HAL_ADCEx_Calibration_Start()
- ADC MSP初始化:HAL_ADC_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置ADC相应通道相关参数:HAL_ADC_ConfigChannel()
- 启动A/D转换:HAL_ADC_Start()
- 等待规则通道转换完成:HAL_ADC_PollForConversion()
- 获取规则通道A/D转换结果:HAL_ADC_GetValue()
单通道ADC采集(DMA读取)实验配置步骤
- 初始化DMA:HAL_DMA_Init()
- 将DMA和ADC句柄联系起来:__HAL_LINKDMA()
- 配置ADC工作参数、ADC校准:HAL_ADC_Init()、HAL_ADCEx_Calibration_Start()
- ADC MSP初始化:HAL_ADC_MspInit() 配置NVIC、CLOCK、GPIO等
- 配置ADC相应通道相关参数:HAL_ADC_ConfigChannel()
- 使能DMA数据流传输完成中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
- 编写DMA数据流中断服务函数:DMAx_Channely_IRQHandler()
- 启动DMA,开启传输完成中断:HAL_DMA_Start_IT()
- 触发ADC转换,DMA传输数据:HAL_ADC_Start_DMA()
通过过采样和求均值提升ADC分辨率
根据要增加的分辨率位数计算过采样频率方程:
\(f_{os}\)是过采样频率,\(w\)是希望增加的分辨率位数,\(f_s\)是初始采样频率要求
方程推导过程:https://max.book118.com/html/2018/0506/165038217.shtm
举例说明:12位分辨率的ADC提高4位分辨率,采样频率就要提高256倍(即需要256次采集才能得到一次16位分辨率的数据),然后将这256次采集结果求和,求和的结果再右移4位,就得到提高分辨率后的结果。
注意:提高N位分辨率,需要右移N位
内部温度传感器
温度计算方法:
- \(V_{25}\):25°C时的\(V_{SENSE}\)值(典型值:1.43)
- \(Avg\_Slope\):温度与\(V_{SENSE}\)曲线的平均斜率(单位:mv/°C或uv/°C),典型值:4.3mv/°C
- \(V_{SENSE}\):ADC采集到内部温度传感器的电压值
光敏二极管
-
光敏二极管:核心是一个PN结,对光强非常敏感,单向导电性,工作时需加反向电压
-
暗电流:无光照时,反向电流很小(一般小于0.1微安),称为暗电流
-
光电流:有光照时,光的强度越大,反向电流也越大,形成光电流(非线性变化)。利用电流变化的特点,串联一个电阻,就可以得到电压的变化,通过ADC读取,从而知道光强变化

浙公网安备 33010602011771号