深入了解STM32-GPIO的相关介绍和功能
一.GPIO的工作模式,通常的操作步骤
二.相关输出函数及功能实现
三.相关输入函数与功能
1.GPIO的工作模式,通常的操作步骤
- GPIO(General Purpose Input Output)通用输入输出口,可配置为8种输出输入方式。
- 引脚电压0~3.3V,部分引脚可容忍5V。
- 使用GPIO时通常先用RCC开启GPIO时钟,之后利用函数初始化GPIO(代码见下),最后控制GPIO口即可。(如LED灯,蜂鸣器)
#include "stm32f10x.h" // Device header
/*实现芯片上LED的点亮与熄灭*/
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//配置时钟
GPIO_InitTypeDef GPIO_InitStruture;//定义结构体给他起名,赋值
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStruture);//配置定时器,需要结构体参数
// GPIO_SetBits(GPIOC,GPIO_Pin_13);//设置高电平——暗
GPIO_ResetBits(GPIOC,GPIO_Pin_13);//设置低电平——亮
while(1)
{
}
}
2.相关输出函数及功能实现
- GPIO的输出函数可再库函数中自己查看详情信息,我只简单介绍一下
- void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); - 前两个函数用于将指定位分别设置成高低电平。
- 第三个函数可以选中想要控制的端口之后设置端口,第四个函数直接对16个端口进行写入。
- 利用以上函数可以实现LED的闪烁以及LED流水灯(以led闪烁为例),注意面包板上引脚位置,和代码的GPIO设定,代码如下
#include "stm32f10x.h" /** * @brief 微秒级延时 * @param xus 延时时长,范围:0~233015 * @retval 无 */ void Delay_us(uint32_t xus) { SysTick->LOAD = 72 * xus; //设置定时器重装值 SysTick->VAL = 0x00; //清空当前计数值 SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器 while(!(SysTick->CTRL & 0x00010000)); //等待计数到0 SysTick->CTRL = 0x00000004; //关闭定时器 } /** * @brief 毫秒级延时 * @param xms 延时时长,范围:0~4294967295 * @retval 无 */ void Delay_ms(uint32_t xms) { while(xms--) { Delay_us(1000); } } /** * @brief 秒级延时 * @param xs 延时时长,范围:0~4294967295 * @retval 无 */ void Delay_s(uint32_t xs) { while(xs--) { Delay_ms(1000); } }
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置时钟注意GPIO
GPIO_InitTypeDef GPIO_InitStruture;//定义结构体给他起名,赋值,注意结构式是地址
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_0;//选择memner
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruture);//配置定时器,需要结构体参数
// GPIO_SetBits(GPIOA,GPIO_Pin_0);//LED高电平不亮
// GPIO_ResetBits(GPIOA,GPIO_Pin_0);//低电平,亮
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);//置低电平
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);//置高电平
while(1)
{
/*通过上方函数实现led闪烁,此时led长脚接的正极*/
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
Delay_ms(500);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
Delay_ms(500);
}
}
3.相关输入函数与功能
- stm32中的数据类型与c语言有所不同,通过typedef函数对数据类型换了一个名字用来简化操作,新名如下:

2.利用新的名字定义了如下的读取函数,也是只简单介绍一下
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
3.可使用上方函数实现按钮控制LED灯,相关代码如下
#include "stm32f10x.h" // Device header
/**
*@brief 根据引脚初始化LED,默认是点亮状态,可以去除注释关闭
*@param 无
*@retval 无
*/
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置时钟注意GPIO
/*定义结构体*/
GPIO_InitTypeDef GPIO_InitStruture;
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruture);
// GPIO_SetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);
}
/**
*@brief 引脚1的led点亮与熄灭
*@param 1亮0灭
*@retval 无
*/
void LED1_ctrl(uint8_t a)
{
if(a)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}else GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
/**
*@brief 引脚2的led点亮与熄灭
*@param 1亮0灭
*@retval 无
*/
void LED2_ctrl(uint8_t a)
{
if(a)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}else GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
/**
*@brief 按下同一按钮后取反不亮
*@param 无
*@retval 无
*/
void LED1_Turn(void)
{
/*使用if中的函数读取当前端口的输出状态,输出为0置1,否之置0,实现电平翻转*/
if( GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);//亮
}
else GPIO_ResetBits(GPIOA,GPIO_Pin_1);//不亮
}
void LED2_Turn(void)
{
if( GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
else GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
#include "stm32f10x.h" // Device header
#include "Delay.h"
void Key_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//配置时钟注意GPIO
/*定义结构体*/
GPIO_InitTypeDef GPIO_InitStruture;
GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;//按钮配置成上拉输入
GPIO_InitStruture.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruture);
}
/**
*@brief 读取按钮,读取PB的值,PB1是1,PB11是2
*@param 无
*@retval 按下后1或2,不按0
*/
uint8_t Key_Gotnum(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;
}
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "key.h"
static uint8_t keynum;
int main(void)
{
LED_Init();
Key_Init();
while(1)
{
/*通过keynum的值控制两个led*/
keynum = Key_Gotnum();
if (keynum == 1)
{
LED1_Turn();
}
if (keynum == 2)
{
LED2_Turn();
}
}
}
最后,由于本人刚刚学习stm32很多地方理解的不够深入,如果你发现错误或者哪里没有理解请告诉我
作者:numbers0410