1、 GPIO
1.1、简介
就是通用输入输出口
2, STM32 GPIO简介(了解)
2.1,GPIO特点
1,不同型号,IO口数量可能不一样,可通过选型手册快速查询
2,快速翻转,每次翻转最快只需要两个时钟周期(F1最高速度可以到50Mhz)
3,每个IO口都可以做中断
4,支持8种工作模式
2.2,GPIO电气特性
1,STM32工作电压范围?
2 V ≤ VDD ≤ 3.6 V
2,GPIO识别电压范围?
COMS端口:-0.3V ≤ VIL ≤ 1.164V
1.833V ≤ VIH ≤ 3.6V
3,GPIO输出电流?
单个IO,最大25mA
3,IO端口基本结构介绍(熟悉)
F1系列IO端口基本结构
① 保护二极管
② 内部上拉、下拉电阻
③ 施密特触发器
④ P-MOS & N-MOS管
施密特触发器简介
施密特触发器就是一种整形电路,可以将非标准方波,整形成方波
特点:
当输入电压高于正向阈值电压,输出为高;
当输入电压低于负向阈值电压,输出为低;
当输入在正负向阈值电压之间,输出不改变。
作用:整形!如正弦波转方波
P-MOS & N-MOS管简介
MOS管是压控型元件,通过控制栅源电压( Vgs )来实现导通或关闭。
G:栅极
S:源极
D:漏极
P:Vgs<0,导通
N:Vgs>0,导通
4,GPIO的八种模式分析
4.1、GPIO工作模式:输入浮空
①上拉电阻关闭
②下拉电阻关闭
③施密特触发器打开(指的图中的肖特基触发器(这不是专有名词,指的是通过肖特基组成的施密特触发器))
④双MOS管不导通
特点:空闲时,IO状态不确定,由外部环境决定
4.2 GPIO工作模式:输入上拉
①上拉电阻打开(这里的打开指的是连通)
②下拉电阻关闭
③施密特触发器打开
④双MOS管不导通
特点:空闲时,IO呈现高电平
4.3 GPIO工作模式:输入下拉
①上拉电阻关闭
②下拉电阻打开
③施密特触发器打开
④双MOS管不导通
特点:空闲时,IO呈现低电平
4.4 GPIO工作模式:模拟功能
①上拉电阻关闭
②下拉电阻关闭
③施密特触发器关闭 (都不整形了)
④双MOS管不导通
特点:专门用于模拟信号输入或输出,如:ADC和DAC
4.5GPIO工作模式:开漏输出
①上拉电阻关闭
②下拉电阻关闭
③施密特触发器打开
④ P-MOS管始终不导通
⑤往ODR对应位写0,
N-MOS管导通,
写1则N-MOS管不导通
特点:不能输出高电平,
必须有外部(或内部)
上拉才能输出高电平
4.6 GPIO工作模式:开漏式复用功能
①上拉电阻关闭
②下拉电阻关闭
③施密特触发器打开
④ P-MOS管始终不导通
特点:
1、不能输出高电平,
必须有外部(或内部)
上拉才能输出高电平
2、由其他外设控制输出
4.7 、GPIO工作模式:推挽输出
①上拉电阻关闭
②下拉电阻关闭
③施密特触发器打开
④往ODR对应位写0,
N-MOS管导通,
写1则P-MOS管导通
特点:可输出高低电平,
驱动能力强
4.8、GPIO工作模式:推挽式复用功能
①上拉电阻关闭
②下拉电阻关闭
③施密特触发器打开
特点:
1、可输出高低电平,
驱动能力强
2、由其他外设控制输出
F4/F7/H7系列和F1系列的GPIO差异点
1,F1在输出模式,禁止使用内部上下拉
F4/F7/H7在输出模式,可以使用内部上下拉
2,不同系列IO翻转速度可能不同
5,GPIO寄存器介绍(熟悉)
一个IO配置为输出模式也能读取其状态
这里重点说两个寄存器
ODR
该寄存器低 16 位有效,分别对应每一组 GPIO 的 16 个引脚。当 CPU 写访问该寄存器,如
果对应的某位写 0(ODRy=0),则表示设置该 IO 口输出的是低电平,如果写 1(ODRy=1),则表
示设置该 IO 口输出的是高电平,y=0~15。
除了 ODR 寄存器,还有一个寄存器也是用于控制 GPIO 输出的,它就是 BSRR 寄存器。
BSRR
为什么有了 ODR 寄存器,还要这个 BDRR 寄存器呢?我们先看看 BSRR 的寄存器描述,
首先 BSRR 是只写权限,而 ODR 是可读可写权限。BSRR 寄存器 32 位有效,对于低 16 位(0-
15),我们往相应的位写 1(BSy=1),那么对应的 IO 口会输出高电平,往相应的位写 0(BSy=0),
对 IO 口没有任何影响,高 16 位(16-31)作用刚好相反,对相应的位写 1(BRy=1)会输出低电
平,写 0(BRy=0)没有任何影响,y=0~15。
也就是说,对于 BSRR 寄存器,你写 0 的话,对 IO 口电平是没有任何影响的。我们要设置
某个 IO 口电平,只需要相关位设置为 1 即可。而 ODR 寄存器,我们要设置某个 IO 口电平,
我们首先需要读出来 ODR 寄存器的值,然后对整个 ODR 寄存器重新赋值来达到设置某个或者
某些 IO 口的目的,而 BSRR 寄存器,我们就不需要先读,而是直接设置即可,这在多任务实时
操作系统中作用很大。BSRR 寄存器还有一个好处,就是 BSRR 寄存器改变引脚状态的时候,
不会被中断打断,而 ODR 寄存器有被中断打断的风险。
6、位带操作
6.1 位带简介
位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见。51 单片机中通过关键字 sbit 来实现位定义,F407 中没有这样的关键字,而是通过访问位带别名区来实现。
在 F407 中,有两个地方实现了位带,一个是 SRAM 区的最低 1MB 空间,另一个是外设区最低1MB 空间。这两个 1MB 的空间除了可以像正常的 RAM 一样操作外,他们还有自己的位带别名区,位带别名区把这 1MB 的空间的每一个位膨胀成一个 32 位的字,当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的。
1M空间中的每一位膨胀成为32M的空间的字 ,我们对1个32位地址操作时其实是在操作1位
6.1.1 外设位带区
外设位带区的地址为:0X40000000-0X400F0000,大小为 1MB,这 1MB 的大小包含了APB1/2和 AHB1 上所以外设的寄存器,AHB2/3 总线上的寄存器没有包括。AHB2 总线上的外设地址范围为:0X50000000-0X50060BFF,AHB3 总线上的外设地址范围为:0XA0000000~0XA0000FFF。
外设位带区经过膨胀后的位带别名区地址为:0X42000000~0X43FFFFFF,这部分地址空间为保留地址,没有跟任何的外设地址重合。
6.1.2 SRAM 位带区
SRAM 的位带区的地址为:0X2000 0000-X200F 0000,大小为 1MB,经过膨胀后的位带别名区地址为:0X2200 0000~0X23FF FFFF,大小为 32MB。操作 SRAM 的比特位这个用得很少。
6.1.3 位带区和位带别名区地址转换
位带区的一个比特位经过膨胀之后,虽然变大到 4 个字节,但是还是 LSB (最低位)才有效。有人会问这不是浪费空间吗,要知道 F407 的系统总线是 32 位的,按照 4 个字节访问的时候是最快的,所以膨胀成 4 个字节来访问是最高效的。
我们可以通过指针的形式访问位带别名区地址从而达到操作位带区比特位的效果。那这两个地址直接如何转换,我们简单介绍一下。
6.1.3 .1外设位带别名区地址
对于片上外设位带区的某个比特,记它所在字节的地址为 A, 位序号为 n(0<=n<=31)(n 的范围根
据具体寄存器能控制的位决定),则该比特在别名区的地址为:
AliasAddr= =0x42000000+ (A-0x40000000)84 +n*4
0X42000000 是外设位带别名区的起始地址,0x40000000 是外设位带区的起始地址, (A-0x40000000)表示该比特前面有多少个字节,一个字节有 8 位,所以 *8,一个位膨胀后是 4 个字节,所以 *4,n 表示该比特在 A 地址的序号,因为一个位经过膨胀后是四个字节,所以也 *4。
6.1.3.2 SRAM 位带别名区地址
对于 SRAM 位带区的某个比特,记它所在字节的地址为 A, 位序号为 n(0<=n<=31)(n 的范围根据具体寄存器能控制的位决定),则该比特在别名区的地址为:
AliasAddr= =0x22000000+ (A-0x20000000)84 +n*4
6.1.3.3统一公式
为了方便操作,我们可以把这两个公式合并成一个公式,把“位带地址 + 位序号”转换成别名区地址统一成一个宏。
addr & 0xF0000000 是为了区别 SRAM 还是外设,实际效果就是取出 4 或者 2,如果是外设,则取出的是 4,+0X02000000 之后就等于 0X42000000,0X42000000 是外设别名区的起始地址。如果是 SRAM,则取出的是 2,+0X02000000 之后就等于 0X22000000,0X22000000 是 SRAM 别名区的起始地址。
addr & 0x00FFFFFF 屏蔽了高三位,相当于减去 0X20000000 或者 0X40000000,但是为什么是屏蔽高三位?因为外设的最高地址是:0X20100000,跟起始地址 0X20000000 相减的时候,总是低5 位才有效,所以干脆就把高三位屏蔽掉来达到减去起始地址的效果,具体屏蔽掉多少位跟最高地址有关。SRAM 同理分析即可。«5 相当于 84,«2 相当于 *4,这两个我们在上面分析过。
最后我们就可以通过指针的形式操作这些位带别名区地址,最终实现位带区的比特位操作。
6.4.2 GPIO 位带操作
外设的位带区,覆盖了全部的片上外设的寄存器,我们可以通过宏为每个寄存器的位都定义一个位带别名地址,从而实现位操作。但这个在实际项目中不是很现实,也很少人会这么做,我们在这里仅仅演示下 GPIO 中 ODR 和 IDR 这两个寄存器的位操作。从手册中我们可以知道 ODR 和 IDR 这两个寄存器对应 GPIO 基址的偏移是 20 和 16,我们先实现这两个寄存器的地址映射,其中 GPIOx_BASE 在库函数里面有定义