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异步通信协议

RS-232异步通信协议
  • 启动位:必须占1位,保持逻辑0电平
  • 有效数据位:可选5~9个位长,LSB(最低有效位)在前,MSB在后
  • 校验位:可选占1位长,也可以没有该位
  • 停止位:必须有,可选0.5、1、1.5、2个位长,保持逻辑1电平

USART框图

F1/F4/F7 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中断回调机制

HAL库USART中断回调机制

USART/UART异步通信配置步骤

  1. 配置串口工作参数:HAL_UART_Init()
  2. 串口底层初始化: HAL_UART_MspInit() 配置GPIO、NVIC、CLOCK等
  3. 开启串口异步接收中断:HAL_UART_Receive_IT()
  4. 设置中断优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
  5. 编写中断服务函数:USARTx_IRQHandler()、UARTx_IRQHandler()
  6. 串口数据发送:USART_DR、HAL_UART_Transmit()

IWDG

IWDG(Indepndent watchdog):独立看门狗,能产生系统复位信号的计数器 ,主要应用在一些需要高稳定性的产品中,并且对时间精度要求比较低(因为时钟来自RC振荡器)的场合。

特性

  • 递减计数器

  • 时钟由独立的RC振荡器提供(可在待机和停止模式下运行)

  • 看门狗被激活后,当递减计数器计数到0x000时产生复位

  • 喂狗:在计数器到0之前,重装载计数器的值,防止复位

作用

异常概念:外界电磁干扰或者自身系统(硬件或软件)异常,造成程序跑飞,如:陷入某个不正常的循环,打断正常程序运行

主要用于检测外界电磁干扰,或者硬件异常造成的程序跑飞

独立看门狗时异常处理的最后手段,不可依赖,应当在设计时尽量避免异常的发生

框图

IWDG框图

IWDG溢出时间计算

\[T_{out} = \frac{psc * rlr}{f_{IWDG}} \]

  • \(T_{out}\):看门狗溢出时间
  • \(f_{IWDG}\):看门狗的时钟源频率
  • \(psc\):看门狗预分配系数
  • \(rlr\):看门狗重装载值

配置步骤

  1. 取消PR(预分频系数寄存器)/RLR(重装载值寄存器)写保护,设置IWDG预分频系数和重装载值,启动IWDG:HAL_IWDG_Init()
  2. 及时喂狗,即写入0xAAAA到IWDG_KR:HAL_IWDG_Refresh()

WWDG

WWDG(Window watchdog):窗口看门狗,能产生系统复位信号和提前唤醒中断的计数器,主要应用再需要检测程序运行时间的场合(因为使用的时钟源来自系统总线)

特性

  • 递减计数器
  • 当递减计时器值从0x40减到0x3F时复位(即T6位跳变到0)
  • 计时器的值大于W[6:0]值时喂狗会复位
  • 提前唤醒中断(EWI):当递减计数器 等于0x40时可产生

作用

用于检测单片机程序运行时效是否精准,主要检测软件异常

工作原理图

工作原理图

框图

WWDG框图

WWDG超时时间计算

\[T_{out} = \frac{4096 * 2^{WDGTB} * (T[5:0] + 1)}{F_{wwdg}} \]

  • \(T_{out}\):WWDG超时时间(没喂狗)
  • \(F_{wwdg}\):WWDG时钟源频率
  • \(4096\):WWDG固定的预分频系数
  • \(2^{WDGTB}\):WWDG_CFR寄存器设置的预分频系数值
  • \(T[5:0]\):WWDG计数器低六位

配置步骤

  1. WWDG工作参数初始化:HAL_WWDG_Init()
  2. WWDG Msp初始化:HAL_WWDG_MspInit() 配置NVIC、CLOCK等
  3. 设置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_Enable()
  4. 编写中断服务函数:WWDG_IRQHandler()->HAL_WWDG_IRQHandler
  5. 重定义提前唤醒回调函数:HAL_WWDG_EarlyWakeupCallback()
  6. 在窗口期内喂狗: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} = \frac{(ARR + 1) * (PSC + 1)}{F_t} \]

  • \(T_{out}\):定时器溢出时间
  • \(F_t\):定时器时钟源频率
  • \(ARR\):自动重装载器的值
  • \(PSC\):预分频寄存器的值

基本定时器

  • 可用于触发DAC
  • 在更新事件(计数器溢出)时,可产生中断/DMA请求

框图

基本定时器框图

配置步骤

  1. 配置定时器基础工作参数:HAL_TIM_Base_Init()
  2. 定时器基础MSP初始化:HAL_TIM_Base_MspInit() 配置NVIC、CLOCK等
  3. 使能更新中断并启动计数器:HAL _TIM_Base_Start_IT()
  4. 设置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
  5. 编写中断服务函数:TIMx_IRQHandler()等->HAL_TIM_IRQHandler()
  6. 编写定时器更新中断回调函数:HAL_TIM_PeriodElapsedCallback()

通用定时器

  • 可用于触发DAC、ADC
  • 在更新事件、触发事件、输入捕获、输出比较时,会产生中断/DMA请求
  • 4个独立通道,可用于:输入捕获、输出比较、输出PWM、单脉冲模式
  • 使用外部信号控制定时器且可实现多定时器互连的同步电路
  • 支持编码器和霍尔传感器电路等

框图

通用定时器框图

计时器时钟源

计数器时钟源
  1. 内部时钟(CK_INT):来自外设总线APB提供的时钟
  2. 外部时钟模式1:外部输入引脚(TIx):来自定时器通道1或者通道2引脚的信号
  3. 外部时钟模式2:外部触发输入(ETR):来自可以复用位TIMx_ETR的IO引脚
  4. 内部触发输入(ITRx):用于芯片内部其他通用/高级定时器级联
外部时钟模式1
外部时钟模式1
外部时钟模式2
外部时钟模式2
使用一个定时器作为另一个定时器的预分频器
使用一个定时器作为另一个定时器的预分频器

PWM

通用定时器输出PWM原理
通用定时器输出PWM原理
PWM模式
PWM模式
PWM输出配置步骤
  1. 配置定时器基础工作参数:HAL_TIM_PWM_Init()
  2. 定时器PWM输出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
  3. 配置PWM模式/比较值等:HAL_TIM_PWM_ConfigChannel()
  4. 使能输出并启动计数器:HAL_TIM_PWM_Start()
  5. 修改比较值控制占空比(可选):__HAL_TIM_SET_COMPARE()
  6. 使能通道预装载(可选):__HAL_TIM_ENABLE_OCxPRELOAD()

输入捕获

输入捕获脉宽测量原理
输入捕获脉宽测量原理
配置步骤
  1. 配置定时器基础工作参数:HAL_TIM_IC_Init()
  2. 定时器输入捕获MSP初始化:HAL_TIM_IC_MspInit() 配置NVIC、CLOCK、GPIO等
  3. 配置输入通道映射、捕获边沿等:HAL_TIM_IC_ConfigChannel()
  4. 设置优先级,使能中断:HAL_NVIC_SetPriority()、 HAL_NVIC_EnableIRQ()
  5. 使能定时器更新中断:__HAL_TIM_ENABLE_IT()
  6. 使能捕获、捕获中断及计数器:HAL_TIM_IC_Start_IT()
  7. 编写中断服务函数:TIMx_IRQHandler()等 -> HAL_TIM_IRQHandler()
  8. 编写更新中断和捕获回调函数:HAL_TIM_PeriodElapsedCallback()、HAL_TIM_IC_CaptureCallback()

脉冲计数

配置步骤
  1. 配置定时器基础工作参数:HAL_TIM_IC_Init()
  2. 定时器输入捕获MSP初始化:HAL_TIM_IC_MspInit() 配置NVIC、CLOCK、GPIO等
  3. 配置定时器从模式等:HAL_TIM_SlaveConfigSynchro()
  4. 使能输入捕获并启动计数器:HAL_TIM_IC_Start()
  5. 获取计数器的值:__HAL_TIM_GET_COUNTER()
  6. 设置计数器的值:__HAL_TIM_SET_COUNTER()

高级定时器

  • 重复计数器(计数器每次上溢或者下溢都能使重复计数器减1,减到0时,再发生一次溢出就会产生更新事件)
  • 死区时间带可编程的互补输出
  • 断路输入,用于将定时器的输出信号置于用户可选的安全配置中

框图

高级定时器框图

重复计数器特性

重复计数器特性
输出指定个数PWM实验配置步骤
  1. 配置定时器基础工作参数:HAL_TIM_PWM_Init()
  2. 定时器PWM输出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
  3. 配置PWM模式/比较值等:HAL_TIM_PWM_ConfigChannel()
  4. 配置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_Enable()
  5. 使能定时器更新中断:__HAL_TIM_ENABLE_IT()
  6. 使能输出、主输出(仅高级定时器有)、计数器:HAL_TIM_PWM_Start()
  7. 编写中断服务函数:TIMx_IRQHandler()等 -> HAL_TIM_IRQHandler()
  8. 编写更新中断回调函数:HAL_TIM_PeriodElapsedCallback()

输出比较

实验原理
输出比较实验原理
配置步骤
  1. 配置定时器基础工作参数:HAL_TIM_OC_Init()
  2. 定时器输出比较MSP初始化:HAL_TIM_OC_MspInit()
  3. 配置输出比较模式等:HAL_TIM_OC_ConfigChannel()
  4. 使能通道预装载:__HAL_TIM_ENABLE_OCxPRELOAD()
  5. 使能输出、主输出、计数器:HAL_TIM_OC_Start()
  6. 修改捕获/比较器的值:__HAL_TIM_SET_COMPARE()

带死区控制的互补输出

因为元器件有延迟特性,所以需要加上死区时间控制。

死区时间计算
  1. 确定\(t_{DTS}\)的值:\(f_{DTS} = \frac{F_t}{2^{CKD[1:0]}}\)
    CKD[1:0]

  2. 判断DTG[7:5],选择计算公式
    DTG[7:5]

  3. 代入选择的公式计算

刹车(断路)功能

使能刹车功能:将TIMx_BDTR的BKE位置1,刹车输入信号极性由BKP位设置

使能刹车功能后:由TIMx_BDTR的MOE、OSSI、OSSR位,TIMx_CR2的OISx、OISxN位,TIMx_CCER的CCxE、CCxNE位控制OCx和OCxN输出状态

无论何时,OCx和OCxN输出都不能同时处在有效电平

配置步骤
  1. 配置定时器基础工作参数:HAL_TIM_PWM_Init()
  2. 定时器PWM输出MSP初始化:HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
  3. 配置PWM模式/比较值等:HAL_TIM_PWM_ConfigChannel()
  4. 配置刹车功能、死区时间等:HAL_TIMEx_ConfigBreakDeadTime()
  5. 使能输出、主输出、计数器:HAL_TIM_PWM_Start()
  6. 使能互补输出、主输出、计数器:HAL_TIM_PWMN_Start

PWM输入模式

工作原理
PWM输入模式工作原理
时序
PWM输入模式时序
配置步骤
  1. 配置定时器基础工作参数:HAL_TIM_IC_Init()
  2. 定时器捕获输入MSP初始化:HAL_TIM_IC_MspInit() 配置NVIC、CLOCK、GPIO等
  3. 配置IC1/2映射、捕获边沿等:HAL_TIM_IC_ConfigChannel()
  4. 配置从模式,触发源等:HAL_TIM_SlaveConfigSynchro()
  5. 配置优先级,使能中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
  6. 使能捕获、捕获中断及计数器:HAL_TIM_IC_Start_IT()、HAL_TIM_IC_Start()
  7. 编写中断服务函数:TIMx_IRQHandler()等 -> HAL_TIM_IRQHandler()
  8. 编写输入捕获回调函数:HAL_TIM_IC_CaptureCallback()

电容触摸按键

电容触摸按键可以等效为一个电容。

优势:无机械装置,使用寿命长,非接触式感应,面板不用开孔,简洁美观,防水性好。

电容触摸按键原理
  • 无手指触摸:上电时,电阻作用下,电容Cs进行充电,直到电容充满,这时会有一个充电时间Tcs
  • 有手指触摸,上电时,电阻作用下,电容Cs和Cx进行充电,直到电容充满,这时会有一个充电时间Tcx

充电过程可以看成是一个信号从低电平变为高电平的过程,可以利用定时器输入捕获功能计算充电时间(注:电容的初始状态要为0,即一开始就要放电)

先测量到的无触摸时充电时间Tcs作为比较基准,然后定时循环测量充电时间T与Tcs作比较,如果超过一定的阈值就认为有手指触摸。

检测电容触摸按键过程

  1. TPAD引脚设置为推挽输出,输出低电平,实现电容放电到地
  2. TPAD引脚设置为浮空输入 (IO复位后的状态),电容开始充电
  3. 同时开启TPAD引脚的输入捕获功能,开始捕获高电平
  4. 等待充电过程中,上升沿触发(充电放到Vth(上升沿的电压值))
  5. 计算充电时间(定时器捕获/比较寄存器获取)

OLED

驱动原理

  1. 选择驱动芯片时序:8080、6800、SPI、IIC等,根据时序实现数据写入/读取
  2. 初始化序列:由厂家提供,用于初始化屏幕
  3. 实现画点函数、读点函数(可选):基于这两个函数可以实现各种绘图功能

8080并口读/写过程

  1. 设置DC为高(数据)/低(命令):根据写入/读取的数据类型

  2. 拉低片选:选中芯片

  3. 设置RD/WR为低:取决于要读数据还是写数据

  4. 准备数据

  5. 拉高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[列数][页数]

GRAM与OLED屏幕坐标对应关系表

一个通用的点(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数据(地址自增,支持连续读)
读GRAM指令

FSMC

FSMC(Flexible Static Memory Controller)灵活静态存储控制器,用于驱动SRAM、NOR FLASH、NAND FLASH及PC卡类型的存储器。配置好FSMC,定义一个指向这些地址的指针,通过对指针操作就可以直接修改存储单元内容,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驱动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字节空间

FSMC地址映射

HADDR总线是转换到外部存储器的内部AHB地址线,简单来说,从CPU通过AHB总线到外部信号线之间的关系,HADDR是字节地址,而存储器访问不都是按字节访问,接到存储器的地址线与其数据宽度相关。

HADDR与FSMC连接关系

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]被理解为命令

确定代替的地址:

  1. 确认FSMC_NE4基地址:0x6C00 0000 计算公式NEx(x=1~4):0x6000 0000 + (0x0400 0000 * (x - 1))
  2. 确认FSMC_A10对应地址值:\(2^{10} * 2(双字节数据) = 0x800\) 计算公式:FSMC_Ay(y=0~25): \(2^y * 2\)
  3. 确认两个地址:代表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掉电后运行,功耗低

RTC框图

配置步骤

  1. 使能电源时钟并使能后备域访问:__HAL_RCC_PWR_CLK_ENABLE 使能电源时钟、__HAL_RCC_BKP_CLK_ENABLE 使能备份时钟、HAL_PWR_EnableBkUpAccess 使能备份访问
  2. 开启LSE/选择RTC时钟源/使能RTC时钟:HAL_RCC_OscConfig 开启LSE、HAL_RCCEx_PeriphCLKConfig 选择RTC时钟源、__HAL_RCC_RTC_ENABLE 使能RTC时钟
  3. 初始化RTC,设置分频值以及工作参数:HAL_RTC_Init 初始化RTC、HAL_RTC_MspInit 完成RTC底层初始化工作
  4. 设置RTC的日期和时间:操作寄存器方式实现rtc_set_time
  5. 获取RTC当前日期和时间:定义rtc_get_time函数

低功耗

电源系统结构

STM32具有运行睡眠停止待机四种工作模式。

上电后默认是在运行模式,当内核不需要继续运行时,可以选择后面三种低功耗模式。

  • 睡眠模式:内核时钟关闭
    • 对系统影响小
    • 节能效果最差
  • 停止模式:内核时钟关闭、 关闭内核逻辑电路的所有时钟、关闭时钟系统
    • 节能效果好,程序不会复位
    • 恢复时间长(要重新起振)
    • 退出停止模式,HSI RC振荡器被选为系统时钟
  • 待机模式:内核时钟关闭、 关闭内核逻辑电路的所有时钟、关闭时钟系统、关闭电压调节器
    • 节能效果最好
    • 程序会复位,少数条件才能唤醒
    • 待机模式下所有I/O引脚处于高阻态,除了复位引脚、被使能的唤醒引脚等
低功耗模式表 三种模式功耗

配置步骤

  • 睡眠模式:

    1. 初始化WKUP为中断触发源:参考外部中断引脚初始化
      外设低功耗处理(可选)
    2. 进入睡眠模式:HAL_PWR_EnterSLEEPMode()
    3. 等待WKUP外部中断唤醒
  • 停止模式:

    1. 初始化WKUP为中断触发源:参考外部中断引脚初始化
      外设低功耗处理(可选)
    2. 进入停止模式:HAL_PWR_EnterSTOPMode()
    3. 等待WKUP外部中断唤醒
    4. 重新设置时钟、重新选择滴答时钟源、失能systick中断
  • 待机模式:

    1. 初始化WKUP为中断触发源(可选):参考外部中断引脚初始化
      外设低功耗处理(可选)
    2. 使能电源时钟:__HAL_RCC_PWR_CLK_ENABLE()
    3. 使能WKUP的唤醒功能:HAL_PWR_EnableWakeUpPin()
    4. 清除唤醒标记WUF:__HAL_PWR_CLEAR_FLAG()
    5. 进入待机模式:HAL_PWR_EnterSTANDBYMode()

DMA

DMA(Direct Memory Access,直接存储器访问),DMA传输 将数据从一个地址空间复制到另一个地址空间。DMA传输无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。

DMA框图

仲裁器管理DMA通道请求分为两个阶段:软件阶段(1)、硬件阶段(2)

第一阶段(软件阶段):每个通道的优先级可在DMA_CCRx寄存器中设置,有四个等级:最高、高、中和低优先级。

第二阶段(硬件阶段):如果两个请求有相同软件优先级,较低编号的通道比较高编号的通道有较高的优先级。

注意:
大容量芯片中,DMA1控制器拥有高于DMA2控制器的优先级
多个请求通过逻辑或输入到DMA控制器,只能有一个请求有效。

传输串口数据配置步骤

  1. 使能DMA时钟:__HAL_RCC_DMA1_CLK_ENABLE
  2. 初始化DMA:HAL_DMA_Init函数初始化DMA相关参数、__HAL_LINKDMA函数连接DMA和外设
  3. 使能串口的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协议可以归纳为:

  1. 三个信号:起始信号(主机)、停止信号(主机)、应答信号(主机、从机)
  2. 两个注意:数据有效性、数据传输顺序
  3. 一个状态:空闲状态

IIC时序:

IIC时序

硬件IIC和软件IIC对比:

IIC 用法 速度 稳定性 管脚
硬件IIC 比较复杂 较稳定 需使用特定管脚
软件IIC 操作过程比较清晰 较慢 稳定 任意管脚,比较灵活

软件IIC配置步骤

  1. 使能SCL和SDA对应时钟:__HAL_RCC_GPIOB_CLK_ENABLE()
  2. 设置GPIO工作模式:SDA开漏/SCL推挽输出模式,使用HAL_GPIO_Init初始化
  3. 编写基本信号:起始信号 停止信号 应答信号 (主机:send ack send nack,从机:wait ack)
  4. 编写读和写函数: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

框图

SPI主机模式框图

数据收发流程

数据收发流程

工作模式

  • 时钟极性(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配置步骤:
    1. SPI工作参数配置初始化:工作模式、时钟极性、时钟相位等 HAL_SPI_Init
    2. 使能SPI时钟和初始化相关引脚:GPIO模式设为复用推挽输出模式 HAL_SPI_MspInit
    3. 使能SPI:__HAL_SPI_ENABLE
    4. SPI传输数据:HAL_SPI_Transmit发送数据、HAL_SPI_Receive接收数据、HAL_SPI_TransmitReceive进行发送与接收
    5. 设置SPI传输速度(可选):操作SPI_CR1寄存器中的波特率控制位(注:设置前需要先使能SPI,设置完成后再使能SPI
  • NOR FLASH(NM25Q128)配置步骤:
    1. 初始化片选引脚与SPI接口:相关GPIO初始化、SPI初始化(模式、位数、分频、MSB等)
    2. NM25Q128读取:0x03指令 + 24位地址 + 读取数据
    3. NM25Q128扇区擦除:0x06指令 + 等待空闲 + 0x20指令 + 24位地址 + 等待空闲
    4. NM25Q128写入:擦除扇区(可选) + 0x06指令 + 0x02指令 + 24位地址 + 写入数据 + 等待空闲

写数据需要注意:

  1. 是否需要擦除?
  2. 写入数据(是否需要换页?是否需要换扇区?)
  3. 遵循:读、改、写的原则(解释:读取扇区原数据,在一个大数组中改写需要变动的数据,然后再擦除扇区数据,将大数组中的数据写回扇区中)

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

配置步骤

  1. 配置串口工作参数:HAL_UART_Init()
  2. 串口底层初始化:配置GPIO、NVIC、CLOCK等
  3. 开启串口异步接收中断:__HAL_UART_ENABLE_IT()
  4. 设置优先级、使能中断:HAL_NVIC_SetPriority、HAL_NVIC_EnableIRQ()
  5. 编写中断服务函数:USARTx_IRQHandler()、HAL_UART_Receive()
  6. 串口数据发送:USART_DR、HAL_UART_Transmit()

ADC

ADC(Analog-to-Digital Converter,模拟/数字转换器)

常见ADC类型

ADC电路类型 优点 缺点
并联比较型 转换速度最快 成本高、功耗高,分辨率低
逐次逼近型 结构简单,功耗低 转换速度较慢
  • 并联比较型:

    • 优点:转换速度快
    • 缺点:成本高、功耗高、分辨率低

    并联比较型工作示意图

  • 逐次逼近型(STM32所用):

    • 优点:结构简单、低功耗
    • 缺点:转换速度慢
    • 特点:分辨率和采样速度相互矛盾,分辨率越高,采样速率越低

    逐次逼近型工作示意图

ADC特性参数

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

STM32各系列ADC的主要特性

框图

F1 ADC框图

转换序列

A/D转换被组织为两组:规则组(常规转换组)和注入组(注入转换组)

规则组最多可以有16个转换,注入组最多有4个转换

注入组可以打断规则组的转换

规则序列寄存器控制关系汇总

注入序列寄存器控制关系汇总

触发源

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

F1触发源

转换时间

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采集实验配置步骤

  1. 配置ADC工作参数、ADC校准:HAL_ADC_Init()、HAL_ADCEx_Calibration_Start()
  2. ADC MSP初始化:HAL_ADC_MspInit() 配置NVIC、CLOCK、GPIO等
  3. 配置ADC相应通道相关参数:HAL_ADC_ConfigChannel()
  4. 启动A/D转换:HAL_ADC_Start()
  5. 等待规则通道转换完成:HAL_ADC_PollForConversion()
  6. 获取规则通道A/D转换结果:HAL_ADC_GetValue()

单通道ADC采集(DMA读取)实验配置步骤

  1. 初始化DMA:HAL_DMA_Init()
  2. 将DMA和ADC句柄联系起来:__HAL_LINKDMA()
  3. 配置ADC工作参数、ADC校准:HAL_ADC_Init()、HAL_ADCEx_Calibration_Start()
  4. ADC MSP初始化:HAL_ADC_MspInit() 配置NVIC、CLOCK、GPIO等
  5. 配置ADC相应通道相关参数:HAL_ADC_ConfigChannel()
  6. 使能DMA数据流传输完成中断:HAL_NVIC_SetPriority()、HAL_NVIC_EnableIRQ()
  7. 编写DMA数据流中断服务函数:DMAx_Channely_IRQHandler()
  8. 启动DMA,开启传输完成中断:HAL_DMA_Start_IT()
  9. 触发ADC转换,DMA传输数据:HAL_ADC_Start_DMA()

通过过采样和求均值提升ADC分辨率

根据要增加的分辨率位数计算过采样频率方程:

\[f_{os} = 4^w * f_s \]

\(f_{os}\)是过采样频率,\(w\)是希望增加的分辨率位数,\(f_s\)是初始采样频率要求

方程推导过程:https://max.book118.com/html/2018/0506/165038217.shtm

举例说明:12位分辨率的ADC提高4位分辨率,采样频率就要提高256倍(即需要256次采集才能得到一次16位分辨率的数据),然后将这256次采集结果求和,求和的结果再右移4位,就得到提高分辨率后的结果。

注意:提高N位分辨率,需要右移N位

内部温度传感器

温度计算方法:

\[T(°C) = \frac{V_{25} - V_{SENSE}}{Avg\_Slope} + 25 \]

  • \(V_{25}\):25°C时的\(V_{SENSE}\)值(典型值:1.43)
  • \(Avg\_Slope\):温度与\(V_{SENSE}\)曲线的平均斜率(单位:mv/°C或uv/°C),典型值:4.3mv/°C
  • \(V_{SENSE}\):ADC采集到内部温度传感器的电压值

光敏二极管

  1. 光敏二极管:核心是一个PN结,对光强非常敏感,单向导电性,工作时需加反向电压

  2. 暗电流:无光照时,反向电流很小(一般小于0.1微安),称为暗电流

  3. 光电流:有光照时,光的强度越大,反向电流也越大,形成光电流(非线性变化)。利用电流变化的特点,串联一个电阻,就可以得到电压的变化,通过ADC读取,从而知道光强变化

posted @ 2025-03-13 20:38  键盘超人  阅读(49)  评论(0)    收藏  举报