STM32 关于 GPIO总结 以及学习心得

在一开始学习stm32中,由于部分内容涉及到后面的知识 而后面的知识又没有学习 导致在很多概念上难以理解,感觉知识很抽象,不通透,学起来很费解。

在我个人经过一段时间的学习后,有了很多的感悟,以及我对stm32的理解与知识总结

GPIO

在学习GPIO之前我觉得 首先要对M3,M4的内核架构有一定的认识理解 不能直接去学习GPIO
同时 要对stm32里面寄存器的概念,要有一定的认识,要记住一句话:在写调用库函数代码时实际上都是对寄存器进行操作 我们要做到 知其所以然 ,只有这样我们才知道自己在每调用一次函数 进行参数配置时清楚实际上我们都干了写什么,这样就不会感到摸不着头脑,但是,我们不用用寄存器的方式进行编程,所谓站在巨人的肩膀上,我们就要好好的利用st公司为我们提供的库函数进行编程,理解寄存器辅助帮助我们学习即可!

我们来看下面这张图

首先要告诉大家一件事,在读这张图时,一定不要将其当成 电路图 这张图只是一个图示,并不是真正意义上的电路图,我们要善于根据图片上的信息 理解出这张图想要表达的意思,而不是将这张图当作电路图去细细琢磨,研究电流具体走向,最后发现很多矛盾的地方,百思不得其解。原因是很多初学者将这张图当作了电路图看待,实际真正的硬件电路要复杂的多,而且内部真正的电路我们也不得而知。

GPIO八种工作模式

1.模拟输入
此模式可以检测外部输入的模拟电压,可以检测电压值,只要不高于Vcc即可。
模拟输入模式下,不需要连接上拉和下拉电阻,因为GPIO用于模拟功能时,引脚的上、下拉电阻是不起作用的。这个时候即使在配置了上拉或下拉电阻,也不会影响到模拟信号的输入。
输入信号不再经过TTL施密特触发器,可将外部电压信号直接输入到内部的ADC 外设中去。因为经过施密特触发器后信号只有0、1两种状态,所以ADC外设要采集到原始的、连续变化的模拟信号,信号源输入必须在施密特触发器之前。

2.浮空输入
输入浮空模式下,指的是该IO口既不配置接上拉电阻也不配置接下拉电阻。如果该引脚悬空的情况无信号输入时,该端口的电平是不确定的。当有电平信号进入IO时,IO电平状态是完全由外部输入决定,MCU复位上电后,默认为浮空输入模式。

3.上拉输入
上拉输入模式下,GPIO端口悬空无输入信号时,输入端的电平可以默认保持在高电平;而当输入信号低电平时,IO口读取的电平就是低电平;当输入信号高电平时,IO口读取的电平自然就是高电平。

4.下拉模式
输入下拉模式下,GPIO端口悬空无输入信号时,输入端的电平可以默认保持在低电平;而当输入信号高电平时,IO口读取的电平就是高电平;当输入信号低电平时,IO口读取的电平自然就是低电平。

5.推挽输出
推挽输出模式就是,对输出数据寄存器进行置0或置1操作,然后通过输出控制缓冲器对双MOS电路进行控制。IO电平输出的双MOS电路通路同时由PMOS和NMOS组成。当输出控制端输出为1时,上方PMOS导通,下方NMOS截止,电流方向为VDD->PMOS->输出端,对外部引脚输出高电平;当输出控制端输出为0时,上方PMOS截止,下方NMOS导通, 电流方向为VSS->NMOS->输出端,对外输出低电平;简单来说就是pmos和nmos, 同一时间只有一个mos管导通, 可输出高电平或低电平, 输出寄存器决定输出什么就是什么。

6.开漏输出
开漏输出最主要的特性就是高电平没有驱动能力,需要借助外部上拉电阻才能真正输出高电平,这一特性一个明显的优势就是可以很方便的调节输出的电平,因为输出电平完全由上拉电阻连接的电源电平决定。所以在需要进行电平转换的地方,非常适合使用开漏输出。

开漏输出的另一特性好处在于可以实现"线与"功能,所谓的"线与"指的是多个信号线直接连接在一起,只有当所有信号全部为高电平时,合在一起的总线为高电平;只要有任意一个或者多个信号为低电平,则总线为低电平。而推挽输出就不行

开漏输出常用在通信接口,有多个设备连接在同一线上(例如 I2C、One-Wire)。线路默认被上拉电阻拉至高电平,当任意设备有信号触发时,就会将整条线电平拉低。

开漏输出和推挽输出的区别最普遍的说法就是开漏输出无法真正输出高电平,即高电平时没有驱动能力,需要借助外部上拉电阻完成对外驱动。

7.复用推挽输出
GPIO不仅仅可以用作普通的 IO 口输出,还可以作为芯片上其他外设的特殊功能引脚,有些引脚可能可以用作多种不同功能,这种就叫做GPIO的复用,具体用作哪种功能,需要根据使用进行相应的配置。使用GPIO复用功能时,当配置成推挽输出,这样片上外设就可以输出高电平或者低电平,例如将GPIO配置成串口USART输出TXD管脚。

需要注意的是,如果需要实现DAC模拟输出,那么也需要将管脚配置成复用功能,但是此时作为“模拟输出”功能,DAC的模拟信号输出就不经过双MOS管结构了

8.复用开漏输出
与开漏输出模式的不同在于是片上外设决定输出

我们着重将推挽和开漏进行对比:

应用场景:

各自的特征:

其实上面的这些内容绝大部分初学者都能理解,而且绝大部分都觉得自己已经差不多理解了。
但是这里我要发出灵魂拷问
1.推挽输出为什么叫推挽输出?
2.怎么就推挽输出了呢?
3.谁给它推挽的呢?
4.推挽和开漏到底有什么区别

基本的库函数初始化LED灯的代码:
` GPIO_InitTypeDef GPIO_InitStructure; //定义结构体类型的变量
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能F端口

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //pin9 ,pin10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;			//输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;		//电平翻转的速率
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 			//上拉电阻

GPIO_Init(GPIOF, &GPIO_InitStructure);	            //结构体赋值到函数中`

当然这些代码都很简单,我们要做的是通过这些代码去明白 在系统内部到底做了什么事情,这需要通过寄存器来具体分析:
首先我们要通过查询参考手册知道每个寄存器的每个biy位代表什么含义
`RCC->AHB1ENR |= 1<<5; //使能外部时钟 GPIOF [bit 5] //[使能F端口]

GPIOF->MODER &= ~(3<<18);//GPIOF_MODER寄存器bit 18,19 清零
GPIOF->MODER |= (1<<2*9);//GPIOF_MODER寄存器 引脚9 设置为 0 1 [普通输出模式]		//[输出模式]

GPIOF->OSPEEDR &= ~(3<<18);// 速度寄存器引脚9清零
GPIOF->OSPEEDR |= (1<<2*9); //速度寄存器引脚9 设置为1 0 							//[电平翻转的速率]

GPIOF->PUPDR &= ~(3<<18);//上拉寄存器引脚9 清零
GPIOF->PUPDR |= (2<<2*9);//配置成上拉 0 1										//[上拉电阻]	

GPIOF->OTYPER &= ~(1<<9);//模式 开漏或者推挽[0推挽 1开漏] 进行清零
GPIOF->OTYPER |= 0<<9; //设置为推挽												//[推挽输出]

`
其实库函数调用 实际上就是对寄存器特定bit位进行修改 我们可以直接操作寄存器进行修改,也可以调用库函数赋值,当然有库函数这种好东西,便捷,易读,优雅,何乐而不为呢!

消抖其实也不难理解,知道了按键抖动的原因,有了消除抖动的思路,代码也自然而然的很容易写出来,下面也贴一些关于消抖的代码,其实网上消抖的代码太多了,我也贴一下吧:

个人学习技巧:在寻找想用的函数时,只需要去到库函数对应的.c文件,拉到最后,一般所有要用的函数全在那

posted @   WJay  阅读(252)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示