GPIO简介
---------------------------------------------------------------------------------------------------------------------------------
- GPIO(General Purpose Input Output)通用输入输出口
- 可配置为8种输入输出模式
- 引脚电平:0V~3.3V,部分引脚可容忍5V
- 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
---------------------------------------------------------------------------------------------------------------------------------
GPIO基本结构
GPIO位结构
GPIO模式
- 通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式
浮空/上拉/下拉输入
模拟输入
开漏/推挽输出
复用开漏/推挽输出
代码测试
---------------------------------------------------------------------------------------------------------------------------------
LED灯闪烁(连线图+代码)
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式:推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO引脚:Pin_0
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度:50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
/*GPIO_ResetBits设置低电平,GPIO_SetBits设置高电平*/
GPIO_ResetBits(GPIOA, GPIO_Pin_0); //将GPIOA_Pin_0设置为低电平
Delay_ms(500);
GPIO_SetBits(GPIOA, GPIO_Pin_0); //将GPIOA_Pin0设置为高电平
Delay_ms(500);
/*GPIO_WriteBit设置低/高电平,由Bit_RESET/Bit_SET指定*/
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); //将GPIOA_Pin_0设置为低电平
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); //将GPIOA_Pin_0设置为高电平
Delay_ms(500);
/*GPIO_WriteBit设置低/高电平,由数据0/1指定,数据需要强转为BitAction类型*/
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0); //将Pin_0设置为低电平
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1); //将Pin_0设置为高电平
Delay_ms(500);
/*GPIO_Write设置GPIOA16位*/
GPIO_Write(GPIOA, ~0x0001); //将GPIOA_Pin_0设置为低电平,其它设置为高电平
Delay_ms(500);
GPIO_Write(GPIOA, 0x0001); //将GPIOA_Pin_0设置为高电平,其它设置位低电平
Delay_ms(500);
}
}
LED流水灯(连线图+代码)
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式:推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //GPIO引脚:Pin_All(所有引脚)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度:50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
/*使用GPIO_Write,同时设置GPIOA所有引脚的高低电平(32位),实现LED流水灯*/
GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001,GPIOA_Pin_0引脚为低电平,其它为高电平
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010,GPIOA_Pin_1引脚为低电平,其它为高电平
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100,GPIOA_Pin_2引脚为低电平,其它为高电平
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000,GPIOA_Pin_3引脚为低电平,其它为高电平
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000,GPIOA_Pin_4引脚为低电平,其它为高电平
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000,GPIOA_Pin_5引脚为低电平,其它为高电平
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000,GPIOA_Pin_6引脚为低电平,其它为高电平
Delay_ms(100);
GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000,GPIOA_Pin_7引脚为低电平,其它为高电平
Delay_ms(100);
}
}
蜂鸣器(连线图+代码)
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式:推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //GPIO引脚:Pin_12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度:50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
while (1)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12); //GPIOB_Pin_12设置为低电平,蜂鸣器鸣叫
Delay_ms(100);
GPIO_SetBits(GPIOB, GPIO_Pin_12); //GPIOB_Pin_12设置为高电平,蜂鸣器停止
Delay_ms(100);
GPIO_ResetBits(GPIOB, GPIO_Pin_12); //GPIOB_Pin_12设置为低电平,蜂鸣器鸣叫
Delay_ms(100);
GPIO_SetBits(GPIOB, GPIO_Pin_12); //GPIOB_Pin_12设置为高电平,蜂鸣器停止
Delay_ms(700);
}
}
按键控制LED灯(连线图+代码)
(LED.h + LED.c)
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
void LED_On(uint8_t Num);
void LED_Off(uint8_t Num);
void LED_Turn(uint8_t Num);
#endif
#include "stm32f10x.h" // Device header
/**
* 函 数:LED初始化
* 参 数:NULL
* 返 回 值:NULL
*/
void LED_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式:推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; //GPIO引脚:Pin_1、Pin_2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度:50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*设置GPIO初始化后的默认电平*/
GPIO_SetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2); //Pin_1、Pin_2设置为高电平(LED默认关闭)
}
/**
* 函 数:LED开启
* 参 数:uint8_t Num
* 返 回 值:NULL
*/
void LED_On(uint8_t Num)
{
if (1 == Num)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET); //GPIOA_Pin_1设置为低电平
}
if (2 == Num)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET); //GPIOA_Pin_2设置为低电平
}
}
/**
* 函 数:LED关闭
* 参 数:uint8_t Num
* 返 回 值:NULL
*/
void LED_Off(uint8_t Num)
{
if (1 == Num)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET); //GPIOA_Pin_1设置为高电平
}
if (2 == Num)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_SET); //GPIOA_Pin_2设置为高电平
}
}
/**
* 函 数:LED状态翻转
* 参 数:uint8_t Num
* 返 回 值:NULL
*/
void LED_Turn(uint8_t Num)
{
if (1 == Num)
{
if (!GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)) //读取GPIO输出数据寄存器的状态,如果GPIOA_Pin_1输出为低电平
{
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET); //GPIOA_Pin_1设置为高电平
}
else
{
GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET); //GPIOA_Pin_1设置为低电平
}
}
if (2 == Num)
{
if (!GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2)) //读取GPIO输出数据寄存器的状态,如果GPIOA_Pin_2输出为低电平
{
GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_SET); //GPIOA_Pin_2设置为高电平
}
else
{
GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET); //GPIOA_Pin_2设置为低电平
}
}
}
(Delay.h + Delay.c)
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
#endif
#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);
}
}
(Key.h + Key.c)
#ifndef __KEY_H
#define __KEY_H
void Key_Init(void);
uint8_t Key_GetNum(void);
#endif
#include "stm32f10x.h" // Device header
#include "Delay.h"
/**
* 函 数:按键初始化
* 参 数:NULL
* 返 回 值:NULL
*/
void Key_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //GPIO模式:上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11; //GPIO引脚:Pin_1、Pin_11
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度:50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**
* 函 数:按键获取键码值
* 参 数:NULL
* 返 回 值:按下按键的键码值,范围:0~2,返回0代表没有按键按下
* 注意事项:此函数是阻塞式操作,当按键按住不放时,函数会卡住,直到按键松手
*/
uint8_t Key_GetNum(void)
{
uint8_t KeyNum = 0; //定义变量,默认键码值为0
if (!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)) //读取GPIO输入数据寄存器的状态,如果GPIOB_Pin_1输出为低电平,则表示按键1按下
{
Delay_ms(20); //延时消抖(按键抖动大概10~15ms)
while (!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)); //等待按键松手,读取GPIO输入数据寄存器的状态,如果GPIOB_Pin_1输出为低电平,则表示按键1未松手
Delay_ms(20); //延时消抖(按键抖动大概10~15ms)
KeyNum = 1; //键码值为1
}
if (!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)) //读取GPIO输入数据寄存器的状态,如果GPIOB_Pin_11输出为低电平,则代表按键2按下
{
Delay_ms(20); //延时消抖(按键抖动大概10~15ms)
while (!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)); //等待按键松手,读取GPIO输入数据寄存器的状态,如果GPIOB_Pin_11输出为低电平,则表示按键2未松手
Delay_ms(20); //延时消抖(按键抖动大概10~15ms)
KeyNum = 2; //键码值为2
}
return KeyNum; //返回键码值,如果没有按键按下,键码为默认值0
}
(main.c)
#include "stm32f10x.h" // Device header
#include "LED.h"
#include "Key.h"
uint8_t KeyNum; //接收按键键码值
int main(void)
{
/*模块初始化*/
LED_Init(); //LED初始化
Key_Init(); //按键初始化
while (1)
{
KeyNum = Key_GetNum(); //获取按键键码值
if (1 == KeyNum) //如果按键1按下
{
LED_Turn(1); //LED1灯状态翻转
}
if (2 == KeyNum) //如果按键2按下
{
LED_Turn(2); //LED2灯状态翻转
}
}
}
光敏电阻控制蜂鸣器(连线图+代码)
(Puzzer.h + Puzzer.c)
#ifndef __PUZZER_H
#define __PUZZER_H
void Puzzer_Init(void);
void Puzzer_On(void);
void Puzzer_Off(void);
void Puzzer_Turn(void);
#endif
#include "stm32f10x.h" // Device header
/**
* 函 数:蜂鸣器初始化
* 参 数:NULL
* 返 回 值:NULL
*/
void Puzzer_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式:推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //GPIO引脚:Pin_12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度:50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*设置GPIO初始化后的默认电平*/
GPIO_SetBits(GPIOB, GPIO_Pin_12); //GPIOB_Pin_12设置为高电平(蜂鸣器默认关闭)
}
/**
* 函 数:蜂鸣器开启
* 参 数:NULL
* 返 回 值:NULL
*/
void Puzzer_On(void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET); //GPIOB_Pin_12设置为低电平
//GPIO_ResetBits(GPIOB, GPIO_Pin_12):
}
/**
* 函 数:蜂鸣器关闭
* 参 数:NULL
* 返 回 值:NULL
*/
void Puzzer_Off(void)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_SET); //GPIOB_Pin_12设置为高电平
//GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
/**
* 函 数:蜂鸣器状态翻转
* 参 数:NULL
* 返 回 值:NULL
*/
void Puzzer_Turn(void)
{
if (!GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12)) //读取GPIO输出寄存器的状态,如果GPIOB_Pin_12输出低电平
{
GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_SET); //GPIOB_Pin_12设置为高电平
}
else
{
GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET); //GPIOB_Pin_12设置为低电平
}
}
(LDR.h + LDR.c)
#ifndef __LDR_H
#define __LDR_H
void LDR_Init(void);
uint8_t LDR_GetNum(void);
#endif
#include "stm32f10x.h" // Device header
/**
* 函 数:光敏传感器初始化
* 参 数:NULL
* 返 回 值:NULL
*/
void LDR_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //GPIO模式:上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //GPIO引脚:Pin_13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度:50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**
* 函 数:获取光敏传感器输出电平
* 参 数:无
* 返 回 值:光敏传感器输出的电平,范围:0/1
*/
uint8_t LDR_GetNum(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13); //读取GPIO输入寄存器的状态,并返回GPIOB_Pin_13电平:0/1
}
(main.c)
#include "stm32f10x.h" // Device header
#include "Puzzer.h"
#include "LDR.h"
int main(void)
{
/*模块初始化*/
Puzzer_Init(); //蜂鸣器初始化
LDR_Init(); //光敏传感器初始化
while (1)
{
if (1 == LDR_GetNum()) //如果光敏传感器输出为1
{
Puzzer_On(); //蜂鸣器开启
}
else
{
Puzzer_Off(); //蜂鸣器关闭
}
}
}