GPIO
全称:(General Purpose Input Output):通用输入输出口,也就是常说的I/O口
可配置为8种输入输出模式 引脚电平:输出0V~3.3V,部分引脚可容忍输入5V (带FT(Five Tolerate))
对于功率比较大的设备需要加入驱动电路
如果输入的是模拟信号,GPIO可以编程模拟输入的模式,再配合内部ADC外设,就能读取端口的模拟电压
GPIO基本结构
每一个GPIO外设上都有一个寄存器与一个驱动器,寄存器上有16个端口分别通过驱动器与十六个引脚相连,GPIO外设命名方式为GPIOX(X=A、B、C……),十六个引脚命名的方式为PX0,PX1,PX2……PX15,其中X=A、B、C,根据引脚所在外设决定。
STM32是32位的单片机,所以STM32内部的寄存器也是32位的,但这里只用了低16位,高16位并没有用到。
内核通过APB2外设总线控制寄存器进行读写操作,当读到寄存器某一位为1时,则可知道对应的引脚为高电平,当写入寄存器中的某一位为1时,就是把其对应的引脚输出高电平。
所有GPIO都是挂载在APB2外设总线上的。
驱动器负责增大驱动能力,寄存器只负责存储功能。
GPIO位结构
保护二级管工作原理:当I/O口输入高于3.3V的电压时,接VDD的二极管导通,电流从I/O口流向VDD,不流入后续电路,起到了保护作用;当I/O口的电压为负电压时,电流从VSS流向I/O口,不汲取后续电路的电流,同样起到了保护作用。若VDD改为VDD_FT,则表示电源为5V。
上拉电阻及下拉电阻:可以通过软件配置,当VDD导通VSS断开时,为上拉输入模式,引脚悬空时为高电平,反之为下拉输入模式,引脚悬空时为低电平,两者都断开时,为浮空输入模式,引脚悬空时电平不确定,极易受外界干扰而变化。
模拟输入:一般接ADC,接收模拟量。
施密特触发器:作用为对输入电压整形,设置有阈值上限和阈值下限,当I/O口的输入模拟信号超过上限时,施密特触发器输出高电平,当I/O口输入的模拟信号低于下限时,施密特触发器输出低电平,其余时候保持原有电平不变。整形后输入数据存储器保存,再用程序读取就可以知道某位的高低电平。
复用功能输入:一般接其他外设。
位设置/清除寄存器:可以对寄存器中的数据进行单独的位操作,不用整体进行&=或者/=,方便快捷。写1是设置或者清除,写0的位保持不变。高16位是用于位清除的,低16位是用于位设置的,还有一个单独的位清除寄存器,两者配合使用就能之用低16位就可以完成设置与清除,更加便捷,但缺点是不能同步进行,若想要同步进行,就只是采用设置/清除寄存器即可。
P-MOS和N-MOS:两者可以控制三种输出模式:推挽输出,开漏输出以及关闭。
当设置为推挽输出时,P-MOS和N-MOS都有效,当1信号通过输出控制进入MOS管,在P-MOS管被取反为0,在N-MOS管依旧是1,此时P-MOS管导通,N-MOS管断开,输出高电平,反之低电平。
当设置为开漏输出时,P-MOS管一直断开,当1信号通过输出控制进入MOS管,N-MOS管不导通,这时输出高阻态。当0信号通过输出控制进入MOS管,N-MOS管导通,输出高电平。当输入驱动器开启时,为关闭。可以设置开漏模式,外接5v电源加一个电阻,设置输出5v电压。
一个端口可以只能有一个输入,却可以有多个输出。
GPIO模式
器件原理解析
LED
面包板:
蜂鸣器:
对于功率比较大的器件,一般使用三极管驱动的方法来连接电路,避免I/O口负担过重,有箭头是发射极,对左图,当基极给低电平时,三极管导通,蜂鸣器工作;对右图,当基极给高电平时,三极管导通,蜂鸣器工作; 需要注意的是,基极跟发射极之间需要一点开启电压,故而负载蜂鸣器一般不接在发射极一端。
小文件分享
小文件keilkill可以删减过程函数,因为工程文件一般比较大,主要内容就是这些过程量,故而想要实现高效率的分享,可以通过删减过程量,把原来的代码分享出去即可,需要编译后才能恢复如初。
LED闪烁
源代码百度云地址:
链接:https://pan.baidu.com/s/1ZL-6_cgzzKMiS8oxC2MA8Q
提取码:0323
第一步:使用RCC开启GPIO时钟
第二步:使用GPIO_Init函数初始化GPIO
第三步:使用输出或者输入函数控制GPIO
RCC常用函数在rcc.h文件中692行,跳转查看RCC用法,若无法跳转,则重新编译再尝试
GPIO常用库函数在gpio.h的349行左右,跳转查看RCC用法,若无法跳转,则重新编译再尝试
Ctr+Shift+N 快速新建文件夹
Library文件夹中可以看到各种外设的函数使用方法
根据表中寻找要使用的外设连接到哪个总线上
GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_SET);
GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET);
.c文件看内在逻辑,.h看怎么用
GPIO_WriteBit(GPIOA, GPIO_Pin_2,(BitAction)1);强制转换类型才能设置,不能直接设置1或者0.
第一步:使用RCC开启GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能APB2总线上的GPIOC上的所有引脚
第二步:使用GPIO_Init函数初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体名为GPIO_InitStructure GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13; //目标GPIOC_Pin_13,所以引脚选13 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //速读姑且选择50MHz GPIO_Init(GPIOC,&GPIO_InitStructure); //注意第二个参数必须为指向结构名字的指针
GPIO_InitTypeDef GPIO_InitStructure;中,设置的名字必须是GPIO_的格式,不然运行不了,因为在GPIO_Init();中,要求地址格式是那样子 。 第三步:使用输出或者输入函数控制GPIO GPIO_SetBits(GPIOC,GPIO_Pin_13); //PC13口输出高电平 GPIO_ResetBits(GPIOC,GPIO_Pin_13); //PC13口输出低电平
#include "stm32f10x.h" #include "Delay.h" //延时函数头文件 int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOC,&GPIO_InitStructure); while (1) { GPIO_SetBits(GPIOC,GPIO_Pin_13); Delay_ms(500); //延时500ms,可以任意修改 GPIO_ResetBits(GPIOC,GPIO_Pin_13); Delay_ms(500); } }
第一步:使用RCC开启GPIO时钟
第二步:使用GPIO_Init函数初始化GPIO
GPIO_InitStucture.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; 第一步第二步完整代码如下: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_InitStucture; GPIO_InitStucture.GPIO_Mode= GPIO_Mode_Out_PP; GPIO_InitStucture.GPIO_Pin=GPIO_Pin_All; GPIO_InitStucture.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStucture); 第三步:使用输出或者输入函数控制GPIO GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);控制多个端口,其中uint16_t PortVal表示十六位二进制数的十六进制表示,直接写到ODR寄存器中,C语言不支持直接写二进制,所以以十六进制代替。 比如:0000 0000 0000 0001 用0x0001表示 GPIO_Write(GPIOA,~0x0001);~为各位取反符号,就是0变1,1变0; 比如:~0x0001=~(0000 0000 0000 0001)=1111 1111 1111 1110 二进制的十六位分别代表PA0到PA15的16个端口。 要配置多个端口,可以选择GPIO_Pin_All;或者GPIO_Pin_1|GPIO_Pin_2这种格式,应为寄存器的每一位都相当于一个端口,设置为1高电平,0低电平,所以还可以加上个取反符号。GPIO_Pin_1|GPIO_Pin_2代表0x0001或0x0002(十六进制,换成二进制理解即可) GPIO_Write(GPIOA,~0x0001);//1111 1111 1111 1110 十六位依次对应十六个引脚,意思就是PA0置0,其余置1. Delay_ms(500); GPIO_Write(GPIOA,~0x0002); Delay_ms(500); GPIO_Write(GPIOA,~0x0004); Delay_ms(500); GPIO_Write(GPIOA,~0x0008); Delay_ms(500); GPIO_Write(GPIOA,~0x0010);//0000 0000 0001 0000
#include "stm32f10x.h"
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStucture;
GPIO_InitStucture.GPIO_Mode= GPIO_Mode_Out_PP;
GPIO_InitStucture.GPIO_Pin=GPIO_Pin_All;
GPIO_InitStucture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStucture);
while (1)
{
GPIO_Write(GPIOA, ~0x0001);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0002);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0004);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0008);
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0010);
Delay_ms(500);
}
注意:A15 B3 B4调试端口,不能直接作为普通I/O口进行作用,要进行重映射后方可正常使用,尽量不适用这三者进行I/O口调用。
————————————————
版权声明:本文为CSDN博主「笔下觅封侯」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_63148816/article/details/125805677