1.GPIO是什么

单片机的GPIO(General Purpose Input/Output)是指通用输入输出口,是单片机上的一种通用的数字输入输出接口。它可以通过编程控制单片机与外部电路之间的数据传输,从而实现单片机控制外部电路或外部电路控制单片机的功能。 通常情况下,单片机的GPIO口可以配置为输入或输出模式。在输入模式下,GPIO口可以读取外部电路的信号,并将其转换为数字信号输入到单片机中进行处理。在输出模式下,GPIO口可以将单片机处理后的数字信号输出到外部电路中,控制外部电路的运行。 GPIO口的数量和功能因单片机型号而异,有些单片机只有几个GPIO口,而有些单片机则具有更多的GPIO口和更丰富的功能。GPIO口的使用需要根据具体的应用场景进行配置和编程。

可以说,GPIO是掌握单片机的一个重要基础,基本上后面所有的开发都离不开驱动GPIO的输入与输出,包括一些通信,都是通过高低电平来传输0跟1的。

2.GPIO的两种模式

GPIO大致上来说分为两种模式,输出跟输入,本次只讲解简单的推挽输出与输入模式,实际上分为8种模式:

1.输出模式(Output Mode):GPIO口作为输出端口,用于将单片机处理后的信号输出到外部电路。

2.输入模式(Input Mode):GPIO口作为输入端口,用于读取外部电路的信号。

3.上拉输入模式(Pull-up Input Mode):GPIO口作为输入端口,同时启用上拉电阻,使得当外部信号未连接时,GPIO口的电平保持为高电平。

4.下拉输入模式(Pull-down Input Mode):GPIO口作为输入端口,同时启用下拉电阻,使得当外部信号未连接时,GPIO口的电平保持为低电平。

5.开漏输出模式(Open-drain Output Mode):GPIO口作为输出端口,输出为开漏(或称为双向电流输出)模式,这个模式下单片机引脚在未连接任何外部电路的时候不能输出高电平,但是可以通过上拉电阻连接到外部电源,实现更强大的电流输出。

6.推挽输出模式(Push-pull Output Mode):GPIO口作为输出端口,输出为推挽模式,可以提供较高的输出电流能力。

7.复用功能模式(Alternate Function Mode):GPIO口可以配置为其他功能模块所需的引脚,如串口通信、定时器、PWM输出等。

8.模拟模式(Analog Mode):GPIO口可以配置为模拟输入或输出模式,用于连接模拟电路。

(1)推挽输出模式

输出模式顾名思义,是单片机引脚向外输出一个电平,也就是我们常说的高电平与低电平,我们这里只做简单的输出,STM32F103C8T6的引脚在推挽输出模式下能输出的高电平为3.3V,因此高电平为3.3V,低电平为0V。

在下面这个电路中,发光二极管的左侧通过一个限流电阻连接到了单片机的PA0引脚上,右侧接地,这样当我们的单片机输出高电平,发光二极管左右产生电压差,电流就像水流从高处流到低处一样从发光二极管的左侧流到右侧,于是乎发光二极管被点亮,同理STM32引脚输出低电平0V的时候,发光二极管左右两侧没有产生电压差,发光二极管没有电流通过,于是乎发光二极管被熄灭。

①GPIO初始化

void GPIO_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOC, &GPIO_InitStruct); 
}

上面的代码逐条解释如下:
1.开启GPIOC的时钟,它是被挂载在APB2总线上面的,所以用RCC_APB2PeriphClockCmd()这个函数(大多数外设在使用的第一步就应该使能时钟,否则外设不会工作)

2.定义一个结构体GPIO_InitStruct,这个结构体中的成员就是我们需要配置的引脚属性

3.设置为推挽输出模式

4.设置引脚为13号引脚

5.设置引脚速度为50MHz(一般我们直接设置最快的50MHz即可)

6.初始化引脚(起到将我们写入结构体的参数配置到寄存器的作用)

②使用

直接在main函数中调用下面的语句即可实现相对的功能

GPIO_SetBits(GPIOC, GPIO_Pin_13);
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
 
GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)0);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)1);

上面的代码逐条解释如下:

1.GPIO_SetBits()函数可以将引脚设置为高电平,参数为端口号以及引脚号,在这里是将PC13引脚设置为高电平

2.GPIO_ResetBits()函数与上面的正好相反,将PC13引脚设置为低电平

3.GPIO_WriteBit()函数可以将单片机引脚设置为高电平或者低电平,这里是将PC13引脚拉高

4.与上面的正好相反,将PC13引脚拉低

(第三条第四条语句中的最后一个参数用了强制转换,通过转到定义可以查询到这是一个枚举类型,(BitAction)0这个参数也可以替换成Bit_RESET,(BitAction)1这个参数也可以换成Bit_SET,他们的作用都是一样的,只不过换了个名字而已)

(1)输入模式(按键为例)

单片机引脚的输入模式是指将引脚配置为输入端口,用于读取外部电路的信号。在输入模式下,单片机引脚可以接收外部电路的信号,并将其转换为数字信号输入到单片机中进行处理。

我们这里已读取按键键值为例,下图中按键左侧接到单片机引脚PA0,右侧接到引脚地,我们会将单片机引脚配置为上拉输入模式,在这个模式下在没有外部因素影响之下一直保持为高电平,当我们按下按键时,按键左右两侧被导通,瞬间高电平跳转为低电平,在程序的角度来说,我们只需要一直监测引脚状态,当引脚为低电平时就判断为按键被按下。

①GPIO初始化

void Key_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

上面的代码逐条解释如下:

1.GPIOB时钟初始化

2.定义结构体

3.设置为上拉输入模式

4.设置引脚为PB1跟PB10引脚

5.引脚速度设置为50MHz

6.初始化引脚(起到将我们写入结构体的参数配置到寄存器的作用)

①使用

我们封装成一个按键函数,返回值为键值,只需要在main函数中的While(1)死循环中调用该函数,就可以检测按下的按键

uint8_t Key_GetNum(void)
{
    uint8_t KeyNum = 0;
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
    {
        Delay_ms(20);
        while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);
        Delay_ms(20);
        KeyNum = 1;
    }
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)
    {
        Delay_ms(20);
        while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);
        Delay_ms(20);
        KeyNum = 2;
    }
    
    return KeyNum;
}

上面的代码中,GPIO_ReadInputDataBit()函数是读取指定引脚的电平,我们在上述代码中的延时函数为消抖措施(不清楚的可以去百度一下), while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)这一句是我们按键按下后跳转为低电平,程序卡死在while循环中,等我们松手电平跳转为高电平,while中的条件不成立,于是程序继续执行下面的语句,返回键值。

3.开发技巧

在开发过程中,大家肯定要问了,你怎么知道用哪个函数,实际上你需要开发那个外设,就去library组中找到它的头文件(比如说我要开发GPIO,那我就去查看stm32f10x_gpio.h),查看他们的函数声明(一般都在头文件的最底部),右键跳转到函数主体,大多数函数都有它的注释,包括里面的参数应该填什么,不要看到英文就发怵,实际上单片机开发能用到的单词来来回回就那么几个,多看多练多熟悉,自然而然就能够上手。

书山有路勤为径,学海无涯苦作舟!学习和成长的道路是没有尽头的,我们需要不断地努力和探索才能不断地前进。

 

本次笔记基于B站UP主江协科技STM32教程总结而来

发表回复

后才能评论