stm32入门篇
基础知识说明
1. 上拉输入
- 悬空 / 无外接:引脚 = 高电平(平时高)
- 外接 GND(接地、开关按下):引脚 = 低电平(按下低)
- 口诀:默认高,接地变低
2. 下拉输入
- 悬空 / 无外接:引脚 = 低电平(平时低)
- 外接 VCC(接电源、开关按下):引脚 = 高电平(按下高)
- 口诀:默认低,接电变高
选择原则:模式和外部模块保持默认状态一致,若外部模块默认输出低电平,就选择输入低电平(下拉输入),若外部模块默认输出高电平,就选择输入高电平(上拉输入) 。
三极管示意图:

左边是基极,带箭头的是发射极,剩下的是发射极

一.STM32所需用到的函数解析:
对于LED闪烁所需要用到的库函数:
![]()
可指定GPIOA,GPIOB,调用这个函数后,所指定的GPIO外设就会被复位。
![]()
![]()
可将指定的端口设置为高电平
![]()
可将指定的端口设置为低电平
![]()
根据第三个参数的值来设置指定的端口(Bit_RESET是低电平,Bit_SET是高电平)
二.STM32与51外设的逻辑语关系:
2.1LED
LED正极接面包板正极,负极接GPI/O口时输入低电平亮,反之,输入高电平亮,蜂鸣器是低电平发出响声,高电平不发声,且LED初始化模式和频率设置如下

![]()
2.2按键
但对于按键是相同的当按键按下时,函数的返回值均为0,初始化模式和频率设置如下
![]()
![]()
(按键Speed的取值与实际使用无关)
例:if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==0)
2.3光敏电阻
光敏电阻的特性:
- 有光照时:光敏电阻阻值很小(比如几百欧~几千欧)
- 被遮挡 / 黑暗时:光敏电阻阻值很大(几兆欧甚至更高)
对于光敏电阻,当选择上拉输入时:
- 被遮挡(光敏电阻阻值大) → 内部上拉主导 → 引脚高电平 → 返回
1 - 有光照(光敏电阻阻值小) → 光敏电阻拉低主导 → 引脚低电平 → 返回
0

上图符号表示或门,可以有多个输入,但是只能有一个输出,执行的是或的逻辑,在输出端只要有一个是高电平1,就输出的是高电平1,只有全部输入低电平0,才会输出0

上图符号是与门,可以有多个输入,但是只能有一个输出,执行的是与的逻辑,在输出端只要有一个是低电平0,就输出的是低电平0,只有全部输入高电平1,才会输出1

上图符号是非门,只能有一个输入和一个输出,执行的是非的逻辑,在输出端只要有一个是低电平0,就输出的是高电平1,只要有一个是高电平1,就输出的是低电平0,

上图是数据选择器,有多个输入,一个输出
三.GPIO
简介:单片机的引脚,用来读外部信号或控制外部设备
GPIO模式:

LED是浮空
四.EXTI(外部中断)
4.1EXTI简介
简介:STM32 引脚触发中断,外部电平 / 边沿变化触发程序跳转

AFIO的用处:
- AFIO 的核心作用:AFIO 主要用于引脚复用功能的选择和重定义,是 STM32 中配置 GPIO 引脚特殊功能的关键模块。
- STM32 中 AFIO 的两大核心任务:
- 复用功能引脚重映射:调整外设默认引脚映射关系,解决引脚资源冲突,优化硬件设计。
- 中断引脚选择:确定外部中断线与具体 GPIO 引脚的对应关系,配置外部中断输入源。
4.2步骤:
- 开启GPIO和AFIO的时钟

- GPIO初始化

- AFIO选择中断引脚

- EXIT初始化

- NVIC中断分组

- NVIC配置
//若是PX5到PX9,则通道为 EXTI9_5_IRQHandler //若是PX10到PX15,则通道为 EXTI15_10_IRQHandler //NVIC_IRQ通道可在stm32f10x.h文件的297行之后找到
五.TIM定时器
工作图:

5.1TIM定时中断
5.1.1关于定时器的函数
时钟源选择:

时基单元:
![]()
中断输出控制:
![]()
运行控制:(来决定定时器运行和静止)
![]()
写预分频值的函数:
![]()
改变计数器的计数模式:
![]()
选择是否有预装:
![]()
给自动重装器写一个值:
![]()
配置时基单元时可通过以下公式定时:

此为定时1s时所配置的函数:

因为预分频器和计数器都有一个数的偏差,所以要减个1(实际分频数=预分频数+1)
- ARR 控制 波形长短(周期 / 频率) 下图就是设置ARR值的函数
- PSC决定定时器的计数频率
清除标志位:
![]()
5.1.2步骤:
- 开启TIM时钟

- 配置时钟源

- 时基单元初始化
对于计数:当计时器数到ARR的值加一(100)就会清零重新开始计算 (ARR+1)*(PSC+1)/72000000就是每增加一所需要的时间 TIM_Prescaler:决定了 “计数的速度”,数值越大,数得越慢。TIM_Period:决定了 “数多少个数才溢出”,数值越大,溢出越慢。 - 中断输出配置
硬件只会自动置 1,不会自动清 0!必须软件手动清零(通过TIM_ClearFlag函数来实现)。 - NVIC分组和配置(和EXTI一样)
- TIM使能

5.2TIM输出比较
5.2.1OC(Output Capture)输出比较
简介:输出比较可以通过比较 CNT 与 CCR 寄存器值的关系,来对输出电平进行置 1、置 0 或翻转的操作,用于输出一定频率和占空比的 PWM 波形。
5.2.2PWM (Pulse Width Modulation) 脉冲宽度调制

PWM的频率越快,它等效模拟的信号就平稳
占空比决定了PWM等效出来的模拟电压的大小
若占空比是以0.1%的速率来变化的,即10%->10.1%->10.2%->10.3%,则分辨率为0.1%
- PWM 频率:
Freq = CK_PSC / (PSC + 1) / (ARR + 1) - PWM 占空比:
Duty = CCR / (ARR + 1) - PWM 分辨率 :
Reso = 1 / (ARR + 1)
PWM的输出比较模式:


- 蓝色斜线:代表定时器的计数器
CNT的值随时间变化的过程。它从 0 开始,一直向上计数,直到达到最大值后自动清零,重新开始计数,形成锯齿状的上升波形。 - 红色水平线:代表捕获 / 比较寄存器
CCR的值,这里数值是 30。当CNT计数值小于这个值时,输出 PWM 为有效电平;大于等于时则变为无效电平,它决定了 PWM 的占空比。 - 黄色水平线:代表自动重装载寄存器
ARR的值,这里数值是 99。当CNT计数到这个值时,就会自动清零并重新计数,它决定了 PWM 的周期(频率)。
参数计算:
PWM占空比:Duty=CCR/(ARR+1)
- ARR 控制 波形长短(周期 / 频率) 下图就是设置ARR值的函数
- CCR 控制 高电平长短(占空比) CCR=300->300 个时钟高电平
5.2.3步骤:
- 开启时钟

- 配置时钟源(TIM)和初始化(GPIO)
GPIO初始化不能使用推挽输出(Mode_Out_PP),只能使用复用推挽输出(Mode_AF_PP) - 实基单元初始化(与上文TIM相同)
- 输出比较初始化
不同通道对应的引脚不同如下图 - TIM使能
- 外部封装一个函数,来设置CCR的值

5.2.4各个通道对应的引脚




5.2.5舵机
舵机的内部图:

工作原理:PWM信号输入到控制板,给控制板一个指定的目标角度,电位器就会检测目标当前角度,如果大于目标角度就会反转,反之就会正转
输入 PWM 信号要求:周期为 20ms,高电平宽度为 0.5ms~2.5ms

周期20ms:从一个上升沿到下一个上升沿的时间为20ms。
舵机分为两种:旋转角度180和360
旋转角度180:输入不同信号脉冲宽度旋转角度不同
旋转角度360:输入不同信号脉冲宽度旋转方向和速度不同
电机驱动板的硬件电路:


5.2.6函数解读

用来配置输出比较模块的,一个函数对应一个输出单元
![]()
给输出比较结构体赋一个默认值

用来配置强制输出模式

单独更改CCR寄存器的值,可用来更改占空比
![]()
仅高级定时器使用,在使用高级定时器输出 PWM 时,需要调用这个函数,使能主输出,否则 PWM 将不能正常输出。
![]()
用来给结构体赋初始值,当从通用计时器更换为高级定时器时,需要配置的成员变多,如果没有配置,就会导致高级定时器输出PWM时会出现问题,所以我们可以先给所有成员先赋一个初始值,然后修改部分结构体成员的方式来处理问题。

对于普通/开漏推挽输出,引脚的控制权是来自于输出数据寄存器的(GPIO_Mode_Out_PP)
若想让定时器来控制引脚,则需要使用复用开漏/推挽输出的模式,输出控制权将转移给片上外设
(GPIO_Mode_AF_PP),PWM波形才能通过引脚输出
5.2.7重映射
定义:将片上外设(如串口、定时器)的默认 I/O 引脚,切换到芯片上其他备用引脚。(例:
将作用于PA0的功能转移到PA15上)
![]()
引脚重映射配置函数
步骤:
-
开启时钟(必须开启AFIO)

-
引脚重映射配置
第一行是选择了部分重映射方式一(参考手册上有详细的说明)
对于引脚PA15:上电后默认复用为了调试端口JTDI,若想让其作为普通的GPIO端口,则需解除调试端口
5.3TIM输入捕获
5.3.1IC(Input Capture)输入捕获
简介:输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前 CNT 的值将被锁存到 CCR 中,可用于测量 PWM 波形的频率、占空比、脉冲间隔、电平持续时间等参数。
四个输入捕获和输出比较通道,共用4个CCR寄存器,以及四个通道的引脚(CH1-CH4)也是共用的,所以两者只能使用一个,不能同时使用
5.3.2频率测量

- 测频法:在闸门时间 T 内,对上升沿计次,得到 N,则频率 fx=N/T
- 测周法:两个上升沿内,以标准频率fc计次,得到 N,则频率 fx=fc/N
- 中界频率:测频法与测周法误差相等的频率点 fm=fc/T(令测频法和测周法的N相等,然后将fx解出来)
fc从哪里来?
-
硬件来源
- 系统时钟(如 HSE 晶振 72MHz)
- 定时器时钟(经过分频后的频率,比如 1MHz)
- 外部高精度晶振(比如 8MHz)
-
软件配置
- 比如定时器配置为:
- 时钟源:72MHz
- 预分频 PSC=71 → 分频系数 72
- 计数时钟:
fc = 72MHz / 72 = 1MHz
- 这个
1MHz就是你在测周法里用的fc
- 比如定时器配置为:
高频适合测频法,低频适合测周法
当待测频率小于中界频率时为低频,高于中界频率时为高频
5.3.3主从触发模式

主模式:可将定时器内部的信号映射到TRGO引脚,用于触发别的外设
即:主动发时钟、主动发起通信,说了算
从模式:接收其他外设或者自身外设的信号,用于控制自身定时器的运行
即:被动等时钟、被动响应,听指挥
选择从模式:
![]()
触发源选择:选择从模式的触发信号源
选择从模式输入的触发源
![]()
选择主模式输出的触发源
![]()
5.3.4输入捕获和PWMI基本结构
输入捕获:

先转运CNT到CCR中,再触发从模式使CNT清零
PWMI:

对左上角的图进行分析:
- 在触发上升沿时,CCR1先赋值CNT,然后令CNT=0,在高电平时间内CNT一直++
- 在触发下降沿时,给CCR2赋值CNT,这时CNT是在高电平期间的值,然后在低电平时间内CNT也一直++
- 在触发下一个上升沿时,给CCR1赋值CNT,这时的CNT是一个周期的总值
- 则CCR1/CCR2=占空比
5.3.5步骤:
IC配置步骤:
- 开启时钟

- 配置GPIO,时钟源

- 时基单元初始化

- 输入捕获初始化

- 选择触发源和从模式

- TIM使能
- 封装函数,获得输入捕获的频率

同时要配置PWM
分析:
- tim2的psc,arr只负责控制输出的频率,而tim3的psc负责测周法中的fc,arr负责不让计数器溢出
- 必须将PWM波配置完全(占空比,频率,分辨率),否则无法测量
例子分析:当输入信号为100HZ时
先明确你的定时器配置
- TIM3 时钟:72MHz
- PSC 预分频:72-1 = 71
- 计数频率 = 72MHz / (71+1) = 1MHz
- 意思:计数器每 1μs 加 1
100Hz 信号的周期是多少?
频率 f = 100Hz 周期 T = 1 /f = 0.01 秒 = 10,000 微秒(μs)
计数器会计多少个数?
因为 1μs 计 1 个数 10000μs 就会计 10000 个数
则输入捕获测量的频率值为1MHz/10000
5.3.6各个通道对应的引脚





5.3.7输入捕获和输出比较之间的差别
| 输入捕获 | 输出比较 | |
| 引脚 | 输入端口 | 输出端口 |
| 执行流程 | 接收到输入信号,执行CNT锁存到CCR的动作 | 根据CCR和CNT的大小关系来执行输出动作 |
- 每个通用定时器和高级定时器都有4个输入捕获通道(在输入捕获中,高级定时器和通用定时器没有区别,基本定时器没有输入捕获功能)
函数方面上的差别:
输入捕获下:CCR是只读的,要用GetCapture

输出比较下:CCR是只写的,要用SetCompare

5.4编码器接口(Encoder Interface )
- 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制 CNT 自增或自减,从而指示编码器的位置、旋转方向和旋转速度
- 每个高级定时器和通用定时器都拥有 1 个编码器接口
- 两个输入引脚借用了输入捕获的通道 1 和通道 2
5.4.1正交编码器
正转:超前90°

反转:滞后90°

A相 B相

分析:
在TI1和TI2上计数的情况下:若A相上升沿,则相对信号的电平是指B相的电平高低,此时B相高电平,就为向下计数
5.4.2编码器接口基本结构

过程:
- 输入捕获的前两个通道通过GPIO口接入编码器的A、B相
- 通过滤波器和边沿检测极性选择产生TI1FP1、TI2FP2通向编码器接口
- 编码器接口再通过预分频器控制CNT的时钟,同时还根据编码器的旋转方向控制CNT的计数方向
5.4.3步骤:
- 开启时钟

- 配置GPIO(因为编码器接口就是一个带方向控制的外部时钟,所以不需要配置内部时钟)

- 时基单元配置

- 输入捕获初始化
因为只需配置滤波器和极性边沿选择,所以分频选择和选择是否直流的结构体参数可以去掉 - 编码器接口配置
因为此处可以进行极性边沿选择,所以上处进行初始化时可省略,且此处配置会覆盖上面函数的参数;这里的上升沿不代表上升沿有效,因为旋转编码器上升沿和下降沿始终都是有效的,而是代表TI1和TI2是否反相,选择Rising通道不反相,选择Falling通道反相
- 反相:通道的输入信号直接送入定时器,不做电平翻转
- 不反向:通道的输入信号先被取反,再送入定时器
| 配置 | 含义 | 效果 |
| Rising, Rising | 两个通道都不反相 | 编码器正转时计数器向上计数 |
| Falling, Rising | CH1 反相,CH2 不反相 | 计数方向整体反转 |
| Rising, Falling | CH1 不反相,CH2 反相 | 计数方向整体反转 |
| Falling, Falling | 两个通道都反相 | 相位关系不变,方向和默认一致 |
六.ADC(模拟-数字转换器)
6.1ADC简介
简介:将模拟电压转换为数字变量,可将ADC看成一个电压表,将引脚的电压值测出,放在一个变量里
- ADC:将模拟电压转换为数字变量,是模拟电路到数字电路的桥梁。
- DAC:将数字变量转换为模拟电压,是模拟电路到数字电路的桥梁。
- 12 位(位数越高,量化结果就越精细,对应分辨率越高)逐次逼近型 (ADC的工作模式)ADC,AD转化开始到产生结果的时间为1us(1MHz,此为stm32中,ADC最快转换频率)
- 输入电压范围:0~3.3V,转换结果范围:0~4095(输入电压和转换结果为一 一对应关系)
6.2逐次逼近型ADC

STM32的通道有18个
ADC逐次比较:给DAC一个数据使其生成一个对应的电压(已知),然后与通道输入的一个未知电压进行比较,若DAC的电压比未知电压大,就通过二分法使DAC电压变小,不断重复就得到了未知的电压

6.3ADC的基本结构

分析:
- 输入通道有18个:16个GPIO口和2个内部通道;

- AD转换器里的规则组最多选择16个通道,注入组最多选择4个通道;
- 转换的结果存放在数据寄存器中,其中规则组有1个寄存器,注入组有四个;
- 触发控制可分为软件触发和硬件触发,硬件触发主要来自于定时器和外部中断的引脚,RCC是推动ADC逐次比较的时钟;
- 模拟看门狗用于监测转换结果的范围,若超出设定阈值,就通过中断输出控制向NVIC申请中断
- EOF是结束信号
规则组的四种转换模式:
- 单次转换,非扫描模式
只有序列1的通道转换有效 - 多次转换,非扫描模式

- 单次转换,扫描模式
将前7个序列的通道都转换,将数据结果放在数据寄存器里,并用DMA将数据挪走(防止数据被覆盖) - 多次转换,扫描模式

总结:
- 单次 + 非扫描:单通道、转一次就停(只有第一个通道)
- 单次 + 扫描:多通道序列跑一遍就停
- 连续 + 非扫描:单通道高速连续采样(只有第一个通道)
- 连续 + 扫描:多通道循环采样,高速数据采集
数据对齐:
- 数据右对齐(一般使用)

- 数据左对齐(不想要高分辨率时使用)

AD转换时间:
- AD 转换的步骤:采样,保持,量化,编码
- STM32 ADC 的总转换时间为: TCONV = 采样时间 + 12.5 个 ADC 周期(量化,编码所需时间)
- 例如:当 ADCCLK=14MHz(最大频率),采样时间为 1.5 个 ADC 周期 :TCONV = 1.5 + 12.5 = 14 个 ADC 周期 = 1μs
校准:
- ADC 有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码 (数字值),这个码用于消除在随后的转换中每个电容器上产生的误差
- 建议在每次上电后执行一次校准
- 启动校准前, ADC 必须处于关电状态超过至少两个 ADC 时钟周期
硬件电路:
- 点位器产生可调电压的电路
中间的滑动端可输出一个0~3.3V的可调电压,向上滑电压增大,向下电压减小
- 传感器输出电压的电路

传出端感器阻值变小,下拉作用变强,输出电压下降,
传出端感器阻值变大,下拉作用变弱,输出电压上升,
- 电压转换电路
通过串联分压来实现测量VIN电压
6.4步骤
- 开启RCC时钟

- 配置GPIO口
AIN模式下,GPIO口是无效的,目的是为了防止GPIO口的输入输出对模拟电压造成干扰,AIN模式是ADC的专属模式 - 选择规则组的输入通道

- 规则组通道配置

- ADC初始化

- ADC使能
- ADC校准

- 封装一个用于得到转换值的函数

以上是选择单次转换,非扫描模式的操作步骤
若选择多次转换,非扫描模式,则如图所示:

大参数稳定,小参数更快
![]()
给SWSTART置1,开始转换
![]()
返回SWSTART的状态,由于SWSTART在开始转换后立刻就清零了,所以此函数返回值与转换是否结束无关
七.DMA直接存储器存取
7.1DMA简介
简介:不用CPU参与,DMA 自己在内存 ↔ 外设之间和内存 ↔ 内存高速搬数据
- 12个独立可配置的通道:DMA1(7个通道),DMA2(5个通道)
- 每个通道都支持软件触发和特定的硬件触发
7.2存储器映像

- 在stm32中变量是存储在SRAM里面的,用const修饰的常量是存储在Flash里面的
- 访问ADC1的DR寄存器方式:ADC1->DR
ROM 只读存储器(程序闪存)
- 断电数据保留
- 只读为主,可擦写
- 存放:烧录固件、常量
- STM32:片内 Flash
RAM 随机存取存储器(运行内存)
- 断电数据丢失
- 读写速度快
- 存放:程序运行变量、栈、堆
- STM32:片内 SRAM
7.3DMA基本结构

分析:DMA的数据转运可以是存储器(一般指Flash和SRAM)到外设,也可是外设到存储器,也可是Flash到SRAM,但不能是SRAM到Flash(Flash只读)
当是存储器到存储器时,外设的参数应该写Flash的
数据宽度:可选择字节(Byte)、半字(HalfWord)、字(Word)
地址自增:外设寄存器不需要自增,存储器需要自增
自动重装器:转运完成后是否恢复到未转运前传输计数器的数字
传输计数器:自减计数器,用于设定需要转运几次
M2M:用于选择软件触发(用于存储器到存储器)或硬件触发(方式:ADC、串口、定时器),但软件触发不能和自动重装器一起用,软件触发的目的是为了使传输计数器清零,而自动重装器是防止其清零
DMA转运条件:
- DMA必须使能
- 传输计数器必须大于0,若其等于0,且没有自动重装器,这时就要给DMA_Cmd失能,再给传输计数器一个大于0的数,然后使能开启
- 触发源必须有触发信号
当传输数据和被传输数据的传输宽度不同时:
- 大数据传到小数据时,高位会被舍弃
- 小数据传到大数据时,高位会补0
7.4步骤
- 开启时钟
注:DMA的时钟在AHBP总线上 - DMA初始化
其中AddrB,AddrA,Size均为自定义变量 - DMA使能
- 封装一个DMA转运函数

当DMA和ADC一起使用时
- 开启时钟

- 设置ADC的时钟

- GPIO初始化

- ADC规则组通道配置和ADC初始化

- DMA初始化

- DMA和ADC使能

- ADC校准
- ADC触发

- 以上为ADC连续扫描模式的配置方法
- 强制转换
(uint32_t)就是把 “指针类型的地址” 转换成 “32 位整数” - 选择DMA_PeripheralDataSize_HalfWord(低16位数据)是因为低16位数据是规则组的数据,高16位数据是ADC2的(stm32中没有ADC2)
- AD_Value为自定义数组
更多推荐



所有评论(0)