提示:stm32 基于库函数开发,GPIO 相关。
文章目录
- 1. GPIO 简介
- 1.1 基本结构
- 1.2 模式
- 1.3 寄存器
- 1.3.1 端口功能配置寄存器
- 1.3.2 数据输入寄存器
- 1.3.3 数据输出寄存器
- 1.3.4 位设置/位清除寄存器
- 1.3.5 位清除寄存器
- 1.4 库函数
- 2. GPIO 输出及应用
- 2.1 led 灯
- 2.1.1 基础
- 2.1.2 硬件电路
- 2.1.3 软件实现
- 2.2 蜂鸣器
- 2.2.1 基础
- 2.2.2 硬件电路
- 2.2.3 软件实现
- 3. GPIO 输入及应用
- 3.1 按键
- 3.1.1 基础
- 3.1.2 硬件电路
- 3.1.3 软件实现
- 3.2 传感器
- 3.2.1 基础
- 3.2.2 硬件电路
- 3.2.3 软件实现
- 4. 总结
1. GPIO 简介
✔️ 输出:用于驱动 LED,蜂鸣器,模拟通信协议数据
✔️ 输入:用于读取按键输入,传感器输入采集,ADC电压采集,模拟通信协议数据
1.1 基本结构
① 整体结构
内核对寄存器置位实现读写,包含输入和输出寄存器
② GPIO位结构
输出时还可通过位寻址对寄存器和 RAM 进行位设置。总结输出模式如下表所示:
| 模式 | 数据寄存器 | P-MOS | N-MOS | 输出电平 | 说明 |
|---|---|---|---|---|---|
| 推挽 | 1 | ✔️ | ❌ | 1 | 具有驱动能力 |
| 推挽 | 0 | ❌ | ✔️ | 0 | 具有驱动能力 |
| 开漏 | 1 | 不可用 | ❌ | R∞ | 高阻态 |
| 开漏 | 0 | 不可用 | ✔️ | 0 | 低电平驱动 |
| 关闭 | 不可用 | 不可用 | 不可用 | ❌ | 输入模式 |
① 作为通信协议的驱动方式,例如 I2C,可避免多机通信的相互干扰
② io 口接 5V 的上拉时,如果为 R∞,则可输出 5V 的电平
1.2 模式
通过 GPIO 端口配置寄存器,可以影响寄存器和驱动器,实现以下一些模式。
1️⃣ 浮空/上拉/下拉输入
2️⃣ 模拟输入
💡 GPIO 无效,引脚直接接入内部 ADC
3️⃣ 推挽输出
4️⃣ 开漏输出
5️⃣ 复用功能
💡 复用功能,输出来源于片上外设,可以查看stm32的参考手册,8.1.11节有片上外设的GPIO推荐配置
1.3 寄存器
1.3.1 端口功能配置寄存器
端口配置低寄存器定义如下所示,每个端口由 4 位进行控制。
1.3.2 数据输入寄存器
高位保留,低 16 位可直接读出。
1.3.3 数据输出寄存器
高位保留,低 16 位可读可写。
1.3.4 位设置/位清除寄存器
高 16 位用于清除,低 16 位用于设置,使用时写1即可。
1.3.5 位清除寄存器
高位保留,使用时写1即可。
1.4 库函数
在 stm32f10x_gpio.c 和 stm32f10x_rcc.c 中,有以下函数
/* 时钟相关 */voidRCC_AHBPeriphClockCmd(uint32_tRCC_AHBPeriph,FunctionalState NewState);voidRCC_APB2PeriphClockCmd(uint32_tRCC_APB2Periph,FunctionalState NewState);voidRCC_APB1PeriphClockCmd(uint32_tRCC_APB1Periph,FunctionalState NewState);/* GPIO相关函数 */voidGPIO_DeInit(GPIO_TypeDef*GPIOx);/* 复位GPIO */voidGPIO_AFIODeInit(void);/* 复位AFIO */voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct);/* 用GPIO_InitStruct初始化GPIOx */voidGPIO_StructInit(GPIO_InitTypeDef*GPIO_InitStruct);/* 结构体变量赋默认值 */uint8_tGPIO_ReadInputDataBit(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);/* 读函数: */uint16_tGPIO_ReadInputData(GPIO_TypeDef*GPIOx);/* 读函数: */uint8_tGPIO_ReadOutputDataBit(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);/* 读函数: */uint16_tGPIO_ReadOutputData(GPIO_TypeDef*GPIOx);/* 读函数: */voidGPIO_SetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);/* 写函数:设置高电平 */voidGPIO_ResetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);/* 写函数:设置低电平 */voidGPIO_WriteBit(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin,BitAction BitVal);/* 写函数:设置高低电平 */voidGPIO_Write(GPIO_TypeDef*GPIOx,uint16_tPortVal);/* 写函数:设置端口 */voidGPIO_PinLockConfig(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);/* 未使用 */voidGPIO_EventOutputConfig(uint8_tGPIO_PortSource,uint8_tGPIO_PinSource);/* 未使用 */voidGPIO_EventOutputCmd(FunctionalState NewState);/* 未使用 */voidGPIO_PinRemapConfig(uint32_tGPIO_Remap,FunctionalState NewState);/* 未使用 */voidGPIO_EXTILineConfig(uint8_tGPIO_PortSource,uint8_tGPIO_PinSource);/* 未使用 */voidGPIO_ETH_MediaInterfaceConfig(uint32_tGPIO_ETH_MediaInterface);/* 未使用 */2. GPIO 输出及应用
具体函数使用方法,可参考 固件库使用手册
2.1 led 灯
2.1.1 基础
单向导通,长脚+短脚-,小脚+大脚-。
2.1.2 硬件电路
2.1.3 软件实现
使用正点原子精英板,LED0 接在 PB5,LED1 接在 PE5,低电平点亮。LED 流水灯:
#include"stm32f10x.h"// Device header#include"delay.h"/* 定义 LED 端口数组 */uint16_tled_ports[]={GPIO_Pin_0,GPIO_Pin_1,GPIO_Pin_5,GPIO_Pin_4};intmain(void){/* 1. 在rcc.h中定义了总线配置,外设时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/* 2. 配置IO口模式 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);uint8_ti=0;/* 用于循环 */uint8_tsize=sizeof(led_ports)/sizeof(led_ports[0]);while(1){/* 3. 库函数置位,gpio.h */for(uint8_tj=0;j<size;j++){GPIO_WriteBit(GPIOA,led_ports[j],Bit_SET);/* 关闭所有 LED */}GPIO_WriteBit(GPIOA,led_ports[i],Bit_RESET);/* 循环点灯 */Delay_ms(500);i++;if(i>=size){i=0;}}}GPIO使用的一般步骤:设置时钟 → 设置mode → 点灯
2.2 蜂鸣器
2.2.1 基础
▪️ 有源:自带振荡源,频率固定
▪️ 无源:需提供振荡脉冲,根据脉冲频率,发出不同声音
2.2.2 硬件电路
PNP 型,基极低电平触发;NPN 型,基极高电平触发。基极和发射极之间需要一定电压,因此负载接在另一侧。
2.2.3 软件实现
使用正点原子精英板,beep 接在 PB8,高电平触发。
#include"stm32f10x.h"#include"delay.h"intmain(void){/* 1. 在rcc.h中定义了总线配置,外设时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);/* 2. 配置IO口模式 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);while(1){/* 3. 库函数置位,gpio.h */GPIO_ResetBits(GPIOB,GPIO_Pin_8);Delay_ms(100);GPIO_SetBits(GPIOB,GPIO_Pin_8);Delay_ms(100);GPIO_ResetBits(GPIOB,GPIO_Pin_8);Delay_ms(100);GPIO_SetBits(GPIOB,GPIO_Pin_8);Delay_ms(700);}}3. GPIO 输入及应用
3.1 按键
3.1.1 基础
按下导通,松手断开,同时由于是机械触点,有按键抖动需要消抖。
3.1.2 硬件电路
一般采用上面两种方式,key 下接的方式,按下为低电平,io口设置IPU方式
3.1.3 软件实现
使用正点原子精英板,KEY0 接在 PE4,KEY1 接在 PE3,按下为低电平;LED0 接在 PB5,LED1 接在 PE5,低电平点亮。使得 KEY0 控制 LED0 , KEY1 控制 LED1main.c:
#include"stm32f10x.h"#include"delay.h"#include"led.h"#include"key.h"/* 变量定义 */uint8_tkeyNum=0;intmain(void){/* 1. led and key init */ledInit();keyInit();while(1){keyNum=getKeyNum();/* 接线时注意,短的接mcu */switch(keyNum){case3:led1_Turn();break;case4:led0_Turn();break;default:break;}}}led.c:
#include"stm32f10x.h"/* 灯选择参数 */#defineLED00#defineLED11/* 开关状态参数 */#defineLED_ON0#defineLED_OFF1voidledInit(void){/* 1. 在rcc.h中定义了总线配置,外设时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);/* 2. 配置IO口模式 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOE,&GPIO_InitStruct);/* 3. 先关闭 */GPIO_SetBits(GPIOB,GPIO_Pin_5);GPIO_SetBits(GPIOE,GPIO_Pin_5);}/** * @brief LED控制函数 * @param led : 灯选择 (LED0 / LED1) * @param state : 开关状态 (LED_ON / LED_OFF) * @note 低电平点亮 */voidled_set(uint8_tled,uint8_tstate){/* 根据灯选择确定端口和引脚 */GPIO_TypeDef*port;uint16_tpin;switch(led){caseLED0:port=GPIOB;pin=GPIO_Pin_5;break;caseLED1:port=GPIOE;pin=GPIO_Pin_5;break;default:return;/* 非法参数直接返回 */}/* 根据状态设置电平:低电平点亮,高电平熄灭 */if(state==LED_ON){GPIO_ResetBits(port,pin);/* 输出低电平,点亮 */}else{GPIO_SetBits(port,pin);/* 输出高电平,熄灭 */}}/* led turn on or off */voidled0_Turn(void){if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5)==0){led_set(LED0,LED_OFF);}else{led_set(LED0,LED_ON);}}/* 状态翻转 */voidled1_Turn(void){if(GPIO_ReadOutputDataBit(GPIOE,GPIO_Pin_5)==0){led_set(LED1,LED_OFF);}else{led_set(LED1,LED_ON);}}key.c:
#include"stm32f10x.h"#include"delay.h"/* key init */voidkeyInit(void){/* 1. 在rcc.h中定义了总线配置,外设时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);/* 2. 配置IO口模式 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOE,&GPIO_InitStruct);}/* 哪个按键按下 */uint8_tgetKeyNum(void){uint8_tkeyNum=0;if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)/* 按键按下 */{Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0);Delay_ms(20);keyNum=3;}if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)/* 按键按下 */{Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0);Delay_ms(20);keyNum=4;}returnkeyNum;}3.2 传感器
3.2.1 基础
传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出。
3.2.2 硬件电路
传感器电路如下所示:
3.2.3 软件实现
使用正点原子精英板,beep 接在 PB8,高电平触发;PA4 引脚外接光传感器。光敏传感器控制蜂鸣器:
#include"stm32f10x.h"#include"delay.h"/* bee init */voidbeeInit(void){/* 1. 在rcc.h中定义了总线配置,外设时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);/* 2. 配置IO口模式 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);/* 3. 先关闭 */GPIO_ResetBits(GPIOB,GPIO_Pin_8);}/* sensor init */voidsensorInit(void){/* 1. 在rcc.h中定义了总线配置,外设时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/* 1. 配置IO口模式 */GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);}uint8_tlightSensorGet(void){returnGPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4);/* 读取光敏的数据输出 */}intmain(void){/* 1. led and key init */beeInit();sensorInit();while(1){if(lightSensorGet()==1)/* 光线暗,电阻大,分压多,输出为1 */{GPIO_SetBits(GPIOB,GPIO_Pin_8);}else{GPIO_ResetBits(GPIOB,GPIO_Pin_8);}}}/* 逆时针电阻变小,顺时针变大 */现象:遮光时,输出高电平,蜂鸣器响,do 指示灯熄灭
4. 总结
GPIO 使用方法,可参考。