GPIO通用输入输出

📅 发布时间:2026/7/3 11:52:38 👁️ 浏览次数:
GPIO通用输入输出
GPIO通用输入输出1. 核心概念1.1 GPIO概述GPIOGeneral Purpose Input/Output通用输入输出是MCU最基本的外设接口可配置为输入或输出模式用于连接LED、按键、传感器等外围设备。核心特点可编程方向输入或输出多种模式推挽、开漏、上拉、下拉中断支持边沿/电平触发复用功能可配置为其他外设引脚低延迟直接硬件操作1.2 GPIO配置模式输入模式高阻输入浮空 VCC │ GPIO ───── 外部信号 │ GND 上拉输入 VCC │ ┌┴┐ 上拉电阻10-100kΩ └┬┘ GPIO ───── 外部信号 下拉输入 GPIO ───── 外部信号 │ ┌┴┐ 下拉电阻 └┬┘ │ GND输出模式推挽输出Push-Pull VCC │ ┌─┴─┐ ────┤PNP├──┬── 输出 └───┘ │ ┌───┐ │ ────┤NPN├──┘ └─┬─┘ │ GND 特点 - 可输出高/低电平 - 驱动能力强 - 适合LED、电机驱动 开漏输出Open-Drain ┌───┐ ────┤NPN├──┬── 输出 └─┬─┘ │ │ │需外部上拉 GND 特点 - 仅能拉低需外部上拉 - 支持多设备线与 - 适合I2C总线1.3 电气特性典型参数以STM32为例参数最小值典型值最大值单位输入高电平2.0-VCCV输入低电平0-0.8V输出高电平VCC-0.4-VCCV输出低电平0-0.4V输出电流--25mA上拉/下拉电阻304050kΩ2. 技术原理2.1 GPIO寄存器典型GPIO寄存器ARM Cortex-M基地址GPIOA 0x40020000 偏移 寄存器名 功能 0x00 MODER 模式寄存器输入/输出/复用/模拟 0x04 OTYPER 输出类型推挽/开漏 0x08 OSPEEDR 输出速度 0x0C PUPDR 上拉/下拉配置 0x10 IDR 输入数据寄存器只读 0x14 ODR 输出数据寄存器读写 0x18 BSRR 位设置/复位寄存器 0x1C LCKR 锁定寄存器 0x20 AFRL 复用功能寄存器低位 0x24 AFRH 复用功能寄存器高位MODER寄存器模式配置每个引脚占2位 00 输入模式 01 输出模式 10 复用功能 11 模拟模式 示例配置PA5为输出 GPIOA-MODER ~(0x3 (5 * 2)); // 清除位 GPIOA-MODER | (0x1 (5 * 2)); // 设置为输出2.2 GPIO中断中断触发模式上升沿触发 ──┐ └── 产生中断 下降沿触发 ──┐ └── 产生中断 ▲ 双边沿触发 ──┐ ┌── └────┘ ▲ ▲ 都产生中断 电平触发 ────┐ └──── 高电平持续产生中断EXTI外部中断配置1. 配置GPIO为输入模式 2. 配置EXTI线路 3. 配置触发方式上升/下降/双边沿 4. 使能EXTI中断 5. 配置NVIC优先级3. 代码实现3.1 Raspberry Pi GPIOPythonclassGPIOController:GPIO控制器def__init__(self):GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)defsetup_output(self,pin:int):配置为输出GPIO.setup(pin,GPIO.OUT)defsetup_input(self,pin:int,pull_up_downGPIO.PUD_OFF): 配置为输入 Args: pin: GPIO引脚号 pull_up_down: 上拉/下拉配置 GPIO.PUD_OFF: 浮空 GPIO.PUD_UP: 上拉 GPIO.PUD_DOWN: 下拉 GPIO.setup(pin,GPIO.IN,pull_up_downpull_up_down)defwrite(self,pin:int,value:bool):输出电平GPIO.output(pin,GPIO.HIGHifvalueelseGPIO.LOW)defread(self,pin:int)-bool:读取电平returnGPIO.input(pin)GPIO.HIGHdeftoggle(self,pin:int):翻转输出currentGPIO.input(pin)GPIO.output(pin,notcurrent)defadd_interrupt(self,pin:int,callback,edgeGPIO.BOTH): 添加中断 Args: pin: GPIO引脚 callback: 中断回调函数 edge: 触发边沿 GPIO.RISING: 上升沿 GPIO.FALLING: 下降沿 GPIO.BOTH: 双边沿 GPIO.add_event_detect(pin,edge,callbackcallback,bouncetime200)defcleanup(self):清理GPIOGPIO.cleanup()classLED:LED控制def__init__(self,pin:int):self.gpioGPIOController()self.pinpin self.gpio.setup_output(pin)defon(self):点亮self.gpio.write(self.pin,True)defoff(self):熄灭self.gpio.write(self.pin,False)defblink(self,times:int3,interval:float0.5):闪烁for_inrange(times):self.on()time.sleep(interval)self.off()time.sleep(interval)classButton:按键控制def__init__(self,pin:int,callbackNone):self.gpioGPIOController()self.pinpin self.gpio.setup_input(pin,pull_up_downGPIO.PUD_UP)ifcallback:self.gpio.add_interrupt(pin,callback,edgeGPIO.FALLING)defis_pressed(self)-bool:检测按键是否按下returnnotself.gpio.read(self.pin)# 按下为低电平defwait_for_press(self):等待按键按下whilenotself.is_pressed():time.sleep(0.01)# 使用示例if__name____main__:# LED控制ledLED(pin18)print(LED闪烁...)led.blink(times5,interval0.3)# 按键控制defbutton_callback(channel):print(f按键按下: GPIO{channel})led.on()time.sleep(1)led.off()buttonButton(pin17,callbackbutton_callback)print(等待按键...)try:whileTrue:time.sleep(0.1)exceptKeyboardInterrupt:GPIO.cleanup()3.2 Arduino GPIO实现// arduino_gpio.ino - Arduino GPIO控制classGPIO{public:/** * 配置为输出 */staticvoidsetupOutput(uint8_tpin){pinMode(pin,OUTPUT);}/** * 配置为输入 */staticvoidsetupInput(uint8_tpin,uint8_tmodeINPUT){pinMode(pin,mode);// INPUT, INPUT_PULLUP}/** * 写入电平 */staticvoidwrite(uint8_tpin,boolvalue){digitalWrite(pin,value?HIGH:LOW);}/** * 读取电平 */staticboolread(uint8_tpin){returndigitalRead(pin)HIGH;}/** * 翻转输出 */staticvoidtoggle(uint8_tpin){write(pin,!read(pin));}};classLED{private:uint8_tpin;public:LED(uint8_tp):pin(p){GPIO::setupOutput(pin);}voidon(){GPIO::write(pin,true);}voidoff(){GPIO::write(pin,false);}voidtoggle(){GPIO::toggle(pin);}voidblink(uint16_ttimes3,uint16_tinterval_ms500){for(uint16_ti0;itimes;i){on();delay(interval_ms);off();delay(interval_ms);}}};classButton{private:uint8_tpin;boollast_state;uint32_tlast_debounce_time;staticconstuint16_tDEBOUNCE_DELAY50;// 防抖延迟mspublic:Button(uint8_tp):pin(p),last_state(HIGH),last_debounce_time(0){GPIO::setupInput(pin,INPUT_PULLUP);}/** * 检测按键是否按下带防抖 */boolisPressed(){boolcurrent_stateGPIO::read(pin);if(current_state!last_state){last_debounce_timemillis();}if((millis()-last_debounce_time)DEBOUNCE_DELAY){if(current_stateLOWlast_stateHIGH){last_statecurrent_state;returntrue;}}last_statecurrent_state;returnfalse;}/** * 等待按键按下 */voidwaitForPress(){while(!isPressed()){delay(10);}}};// Arduino主程序LEDled(13);// 板载LEDButtonbutton(2);// 按键连接到Pin 2voidsetup(){Serial.begin(115200);Serial.println(GPIO示例);// LED闪烁3次led.blink(3,200);}voidloop(){// 检测按键if(button.isPressed()){Serial.println(按键按下);led.on();delay(1000);led.off();}delay(10);}3.3 STM32 GPIO实现HAL库// stm32_gpio.c - STM32 GPIO驱动#includestm32f4xx_hal.h/** * 配置GPIO为输出 */voidGPIO_InitOutput(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin){GPIO_InitTypeDef GPIO_InitStruct{0};GPIO_InitStruct.PinGPIO_Pin;GPIO_InitStruct.ModeGPIO_MODE_OUTPUT_PP;// 推挽输出GPIO_InitStruct.PullGPIO_NOPULL;GPIO_InitStruct.SpeedGPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOx,GPIO_InitStruct);}/** * 配置GPIO为输入 */voidGPIO_InitInput(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin,uint32_tPull){GPIO_InitTypeDef GPIO_InitStruct{0};GPIO_InitStruct.PinGPIO_Pin;GPIO_InitStruct.ModeGPIO_MODE_INPUT;GPIO_InitStruct.PullPull;// GPIO_NOPULL, GPIO_PULLUP, GPIO_PULLDOWNHAL_GPIO_Init(GPIOx,GPIO_InitStruct);}/** * 配置GPIO中断 */voidGPIO_InitInterrupt(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin,uint32_tMode){GPIO_InitTypeDef GPIO_InitStruct{0};GPIO_InitStruct.PinGPIO_Pin;GPIO_InitStruct.ModeMode;// GPIO_MODE_IT_RISING, GPIO_MODE_IT_FALLING, GPIO_MODE_IT_RISING_FALLINGGPIO_InitStruct.PullGPIO_PULLUP;HAL_GPIO_Init(GPIOx,GPIO_InitStruct);// 配置NVICIRQn_Type IRQn;if(GPIO_PinGPIO_PIN_0){IRQnEXTI0_IRQn;}elseif(GPIO_PinGPIO_PIN_1){IRQnEXTI1_IRQn;}elseif(GPIO_PinGPIO_PIN_5GPIO_PinGPIO_PIN_9){IRQnEXTI9_5_IRQn;}elseif(GPIO_PinGPIO_PIN_10GPIO_PinGPIO_PIN_15){IRQnEXTI15_10_IRQn;}HAL_NVIC_SetPriority(IRQn,5,0);HAL_NVIC_EnableIRQ(IRQn);}/** * LED控制 */voidLED_Init(void){__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitOutput(GPIOA,GPIO_PIN_5);}voidLED_On(void){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);}voidLED_Off(void){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);}voidLED_Toggle(void){HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);}/** * 按键控制 */voidButton_Init(void){__HAL_RCC_GPIOC_CLK_ENABLE();GPIO_InitInterrupt(GPIOC,GPIO_PIN_13,GPIO_MODE_IT_FALLING);}/** * 外部中断回调 */voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){if(GPIO_PinGPIO_PIN_13){printf(按键中断\\r\\n);LED_Toggle();}}/** * 主程序示例 */intmain(void){HAL_Init();SystemClock_Config();// 初始化LED和按键LED_Init();Button_Init();printf(GPIO示例\\r\\n);// LED闪烁for(uint8_ti0;i5;i){LED_On();HAL_Delay(200);LED_Off();HAL_Delay(200);}// 主循环while(1){HAL_Delay(100);}}4. 行业案例案例1智能家居控制面板项目背景智能墙面开关使用GPIO控制LED和检测按键。技术方案MCUESP3230个GPIO输入6个触摸按键GPIO中断输出6个LED指示灯通信WiFiESP32内置实施效果响应延迟10ms功耗5mA待机寿命100万次按压案例2工业传感器采集项目背景工业PLC使用GPIO采集数字传感器信号。技术方案输入通道32路数字输入光耦隔离输出通道16路继电器输出扫描周期1ms实施效果隔离电压2500V AC抗干扰EMC Class AMTBF50,000小时5. 性能优化5.1 快速GPIO操作直接寄存器操作比HAL快10倍// HAL库方式慢HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);// 直接寄存器操作快GPIOA-BSRRGPIO_PIN_5;// 置位GPIOA-BSRR(GPIO_PIN_516);// 复位5.2 GPIO中断优化中断防抖volatileuint32_tlast_interrupt_time0;voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){uint32_tcurrent_timeHAL_GetTick();// 防抖50ms内忽略重复中断if((current_time-last_interrupt_time)50){return;}last_interrupt_timecurrent_time;// 处理中断// ...}6. 协议对比GPIO vs 专用接口特性GPIOI2CSPIUART速度最高50MHz最高3.4Mbps最高50Mbps最高12Mbps引脚数每设备1根2根共享3-4根2根复杂度极低中中低应用LED/按键/简单传感器复杂传感器/EEPROMFlash/DisplayGPS/蓝牙