4.一节课讲明白GPIO口
hello,小伙伴们,大家好,这里是左左右,今天通过这节课的学习让大家学明白什么是GPIO口,通过上一节课的学习,大家对GPIO应该有了一定的了解,GPIO就是通用输入输出口,下面我们打开STM32中文手册的第106页 ,这张图就是IO口的基本结构图,没有的小伙伴可以关注我的个人公众号领取。

这里我们把这张图单独拿出来,这里的IO引脚就是我们单片机上一根根银色的金属条,其余部分指的就是我们stm32单片机的芯片内部了。

这里的VDD和VSS分别代表3.3V和0V,当我们的输入电压大于3.3V时,电流就会从VDD流出。
当我们的输入电压是负压,小于0V时,电流就会沿着VSS从IO引脚流出,所以只有输入电压在0V和3.3V之间,我们的电流才会流入芯片内部,对我们的芯片起到一个保护的作用,既然是IO口,那么它肯定包含输入和输出两种模式,大家已经听过上节课的讲解,那么我就从大家熟悉的输出模式开始讲起吧,输出模式由输出驱动器和输出寄存器两部分构成,我们先讲(输出驱动器),这里我们将P-MOS和N-MOS可以理解为两个开关,当P-MOS闭合时,从VDD通过IO引脚向外输出3.3V的高电平。
当N-MOS闭合时,从VSS通过IO引脚向外输出0V的低电平。
当在推挽输出模式下,我们对P-MOS和N-MOS的开合有绝对的控制权,就是说IO口是输出3.3V的高电平还是0V的低电平,完全是由我们说了算的,在开漏模式下P-MOS相当于彻底断开了,我们只能从VSS通过IO引脚向外输出0V的低电平,这种模式下是有特殊用途的,留个悬念,我们在后面的课程揭晓。
那么P-MOS和N-MOS的开合是靠什么来控制的呢?就是前面的输出寄存器,这里假设我们的需求是将PA5输出3.3V的高电平,要想输出3.3V的高电平,我们必须首先把输出模式设置为推挽模式,由于我们的STM32单片机是32位的,而不管是PA还是PB引脚都只有16个,所以我们将输出寄存器的后16位保留,前16位和我们的PA引脚一一对应,这时通过编写程序控制位设置寄存器,来改变输出数据寄存器中PA5对应的值,通过输出控制将PA5对应的P-MOS管闭合,电流沿VDD从PA5对应的IO口输出3.3V高电平。
我们可以把输出模式分为4种,当走上面这条路时分为推挽输出和开漏输出两种模式。
当走下面这条路时分为复用推挽输出和复用开漏输出,一共加起来就是4种模式。
下面我们接着讲输入模式,他和输出模式一样,也是包括输入驱动器和输入寄存器这两大块。
在输入驱动器这里我们可以看到两个开关,当上面这个开关闭合时,此时默认输入高电平,称为上拉输入模式。
当下面这个开关闭合时,此时默认输入低电平,称为下拉输入模式
那这里的这个斯密特触发器起到一个什么作用呢?外部电压输入时难免会有波动,这时斯密特触发器设置了一高一低两个阈值电压,当输入电压高于高的那个阈值电压时 输入高电平,当输入电压低于低的那个阈值电压时 输入低电平,经过斯密特触发器形成一个稳定的方波信号。
当上下两个开关都处于打开状态时,输入电压不确定,称为浮空输入,当电路处浮空输入模式下,输入电压极易受到外部线路的干扰。
前面讲到的上拉和下拉模式都属于弱上拉和弱下拉,这是因为在VSS和VDD上都串联了一个阻值很大的电阻,在模拟输入模式下,VDD、VSS和施密特触发器的这三个开关都处于失效状态,电流从IO引脚直接到片上外设,由于模拟输入我们需要得到真实的输入电压值,如果经过斯密特触发器,IO口的输入电压值就失真了,模拟输入的使用情况,我也会在后面的课程中为大家一一讲解的。
通过刚才的学习我们不难得出,输入模式分为上拉、下拉、浮空、模拟四种模式。
好了,我们趁热打铁开始今天的案例,首先我们打开STM32cubeide这款软件,点击收藏,找到我们上节课收藏好的stm32 ,点击next,这里我们新建一个项目,并给他命名,第一步我们仍然是点击SYS,选择Debug模式为 serial wire,这时我们设置PA15引脚为GPIO_output,这时我们设置默认输出低电平,输出模式选择为推挽输出,我们点击保存,这时代码就自动生成了,我们找到main.c的文件,这里的main函数,就是我们程序执行的入口,也就是我们程序开始的地方,下面是一些初识化的函数,下面我们按下ctrl按键用鼠标点击GPIO_init这个函数,我们就跳转到定义这个函数的地方了,这个函数里的代码是和我们前面的设置是一一对应的,我们在前面设置好了,代码就自动生成了,是不是很方便。
好的,我们回到主函数,这里我们看到一些绿色的注释,/* 和 */之间的代码是不执行的,起到一个解释代码的作用,方便自己或者其他人维护代码时,一眼就能看出这段代码的作用。
接着我们可以看到 ,user code begin和user code end两行注释,我们自己写的代码必须放到这两行注释之间,否则在自动生成代码时,不在这两行注释之间的代码会被删掉,那么我们的程序就白写了。
上节课我们讲到想要把学习板上的小灯点亮,只需要设置PA15引脚为低电平就可以了,那么我们看代码是怎么实现的,前面我们刚讲HAL_GPIO_WritePin这个函数时,就是设置PA15引脚为低电平,我们将他复制下来,将他放到WHILE(1)的大括号里,这时我的小灯就被点亮,下面我们给他一个延时,让小灯亮一会,我们输入HAL_DEL,然后同时按下键盘上的ALT键和/,我们的代码就被自动补全了,这里我们输入500ms也就是0.5秒,还有每行代码后的分号是必不可少的。
那么我们如何实现小灯的熄灭呢,我们还是打开LED小灯的电路原理图,这时我们将PA15引脚输出3.3V的高电平,小灯两边没有电压差,是不是小灯就熄灭了。

前面我讲过 只有在推挽输出模式下,我们对GPIO输出低电平还是高电平才有绝对的控制权,这就是我们前面为什么要把PA15设置为推挽输出的原因,好了,我们接着复制上面这行代码,将RESET改为SET就实现了将PA15输出高电平,然后我们接着给一个500ms的延时,还有这个while(1)代表什么呢,它代表下面这个大括号里的代码由第一行开始执行到最后一行,然后再从第一行开始执行到最后一行,反复无限循环,以我们这段代码为例,第一行执行将PA15设置为低电平,小灯被点亮,第二行等待500ms,第三行执行将PA15设置为高电平,小灯熄灭,第四行等待500ms,接着在重新执行第一行代码,这样就是实现了LED小灯亮0.5秒灭0.5秒的效果,小灯就会这样一闪一闪的无限循环下去。
while (1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
好了,拿出我们的学习板和电脑连接,手里之前买过最小系统板的小伙伴们可以按这个图接线,接着我们点击运行就能实现视频开始LED小灯闪烁的效果了,可能最近大家也发现我更新的速度并没有之前那么快了,一方面是因为自己制作一期视频用时很长,需要写稿 ,写稿的目的是以尽量精简语言来提高大家学习的效率,再加上制作动画、添加字幕,一期十几分钟的视频制作时间都在十个小时以上,由于白天还有自己的本职工作要做,每天晚上都会抽出两三个小时去做视频,另一方面是因为之前发布的视频,播放量和互动量都没有预想的那么好,所以我把更多的时间投入到了的视频的打磨上,值得欣慰的是最近没有更新的日子里,视频的播放量和关注还是在慢慢上涨的,我始终坚信 好的视频迟早都会得到大家的认可,好了,今天的视频就到这里了,制作不易,您的关注、收藏和点赞是我更新下去的最大动力,下集我们讲一下C语音的基础,下集见。