图片均来自江科大STM32教学PPT
GPIO理论
GPIO简介
- GPIO(General Purpose Input Output)通用输入输出口。
- 可配置为8种输入输出模式。
- 引脚电平:0V~3.3V,部分引脚可容忍5V(在引脚定义表中带FT就是表示可以容忍5V)。
- 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等。
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等。
GPIO基本结构
- 在STM32中所有的GPIO都是挂载到APB2总线上的。
- 寄存器:就是特殊的存储器,内核可以通过APB2总线对其进行读写操作。每一位对应一个引脚。对输出寄存器写1就是输出高电平,写0就是输出低电平。对输入寄存器读取为1就证明端口目前为高电平,读取为0就是低电平。
- 因为是32位单片机,寄存器都是32位的,但是端口只有16位,所以寄存器低16位有对应的端口,高16位没有用到。
- 驱动器是用来增加信号驱动能力的。
GPIO位结构
- 左边为寄存器,中间驱动器,右边I/O引脚。
- 上半为输入部分,下半为输出部分。
- 施密特触发器:对输入电压进行整形。执行逻辑就是:输入电压大于某一阈值,输出高电平,低于某一阈值,输出低电平。
- 控制输出寄存器就是普通I/O口输出,写某一位就可以操作对应引脚。
- 位设置/清除寄存器:可以单独操作输出寄存器的某一位,不影响其他位。
- 推挽输出模式:输出寄存器为1,P-MOS导通,接到VDD,N-MOS断开,输出高电平,反之输出低电平。
- 开漏输出模式:P-MOS无效,只有N-MOS在工作。输出寄存器为1,下管断开,高阻模式,为0,下管导通,接到VSS,输出低电平。开漏模式下高电平没有驱动能力。
GPIO输出
LED灯闪烁代码
#include "stm32f10x.h" // 设备头文件
#include "Delay.h"
int main(void)
{
// 开启GPIOA外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// GPIO初始化结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// 配置GPIOA引脚0为推挽输出模式,最大输出速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 使用指定的配置初始化GPIOA
while (1)
{
// 将GPIOA的引脚0置为低电平(复位状态)
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
// 延迟500毫秒
Delay_ms(500);
// 将GPIOA的引脚0置为高电平
GPIO_SetBits(GPIOA, GPIO_Pin_0);
// 延迟500毫秒
Delay_ms(500);
// 将GPIOA的引脚0写为低电平
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
// 延迟500毫秒
Delay_ms(500);
// 将GPIOA的引脚0写为高电平
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
// 延迟500毫秒
Delay_ms(500);
}
}
流水灯代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开GPIOA的时钟
GPIO_Init(GPIOA,&GPIO_InitStructure);
while(1)
{
// 因为是低电平点亮,所以要取反
GPIO_Write(GPIOA,~0x0001); //0000 0000 0000 0001
Delay_ms(500);
GPIO_Write(GPIOA,~0x0002); //0000 0000 0000 0010
Delay_ms(500);
GPIO_Write(GPIOA,~0x0004); //0000 0000 0000 0100
Delay_ms(500);
GPIO_Write(GPIOA,~0x0008); //0000 0000 0000 1000
Delay_ms(500);
GPIO_Write(GPIOA,~0x0010); //0000 0000 0001 0000
Delay_ms(500);
GPIO_Write(GPIOA,~0x0020); //0000 0000 0010 0000
Delay_ms(500);
GPIO_Write(GPIOA,~0x0040); //0000 0000 0100 0000
Delay_ms(500);
GPIO_Write(GPIOA,~0x0080); //0000 0000 1000 0000
Delay_ms(500);
}
}
蜂鸣器代码
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
while(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
Delay_ms(100);
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
Delay_ms(700);
}
}
GPIO输入
按键控制LED
LED.c
#include "stm32f10x.h" // Device header
//初始化LED灯
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2);
}
//开灯
void LED1_ON(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
//关灯
void LED1_OFF(void)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
//实现翻转
void LED1_Turn(void)
{
// 判断此时IO口的状态,高->低|低->高
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1)==0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1); // 输出高电平
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1); // 输出低电平
}
}
void LED2_ON(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
void LED2_OFF(void)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
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);
}
}
Key.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
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);
}
// 获取按键数值
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;
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
uint8_t keyNum;
int main(void)
{
LED_Init();
Key_Init();
while(1)
{
keyNum=Key_GetNum();
if(keyNum==1)
{
LED1_Turn();
}
if(keyNum==2)
{
LED2_Turn();
}
}
}