笔记(6) —— GPIO检测高低电平

本文档详细介绍了如何在STM32微控制器上配置GPIO以检测按键、光电开关和水位传感器。硬件设计涉及GPIO端口的时钟使能和模式配置,软件设计部分包括固件库的使用、延时函数、LED控制及按键扫描函数的编写。代码示例展示了如何初始化GPIO、实现简单的延时以及读取和处理按键输入。整个系统通过优先级判断来响应不同的按键事件,从而控制LED的状态。
摘要由CSDN通过智能技术生成




一、适用功能

检测按键,光电开关,水位传感器等检测 GPIO 输入电平信号。


二、 硬件设计(参考)

在这里插入图片描述


在这里插入图片描述


三、 软件设计

① 使用到的固件库文件

#include stm32f10x_gpio.c/stm32f10x_gpio.h
#include stm32f10x_rcc.c/stm32f10x_rcc.h

② 代码整理

  • delay.h
#ifndef __DELAY_H
#define __DELAY_H


#include "stm32f10x.h"


void Delay(__IO uint32_t nCount);


#endif


  • delay.c
#include "delay.h"


void Delay(__IO uint32_t nCount) // 简单的延时函数
{
	for(; nCount != 0; nCount--);
}


  • led.h
#ifndef _LED_H
#define _LED_H


#include "stm32f10x.h"


void LED_Init(void);
void LED0_Level(unsigned char Level);
void LED1_Level(unsigned char Level);


#endif


  • led.c
#include "led.h"


/*******************************************************************************
* 函 数 名         : LED_Init
* 函数功能		   : LED初始化函数
* 输    入         : 无
* 输    出         : 无
* 说	明		   :无
*******************************************************************************/
void LED_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;			// LED0-->PB.5 端口配置
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	// 推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;	// IO口速度为50MHz
	GPIO_Init(GPIOB,&GPIO_InitStructure); 	   		// 根据设定参数初始化GPIOB.5
	GPIO_SetBits(GPIOB,GPIO_Pin_5);					// PB.5 输出高
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); // 使能PE端口时钟
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;			// LED1-->PE.5 端口配置
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	// 推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;	// IO口速度为50MHz
	GPIO_Init(GPIOE,&GPIO_InitStructure); 	   		// 根据设定参数初始化GPIOB.5
	GPIO_SetBits(GPIOE,GPIO_Pin_5);					// PE.5 输出高
}


/*******************************************************************************
* 函 数 名         : LED0_Level
* 函数功能		   : LED0——IO电平输出
* 输    入         : Level: 1 —— 输出高;	0 —— 输出低
* 输    出         : 无
* 说	明		   :无
*******************************************************************************/
void LED0_Level(unsigned char Level)
{
	if (Level == 1)
	{
		// PB.5 输出高
		GPIO_SetBits(GPIOB,GPIO_Pin_5);
	}
	else if (Level == 0)
	{
		// PB.5 输出低
		GPIO_ResetBits(GPIOB,GPIO_Pin_5);
	}
}


/*******************************************************************************
* 函 数 名         : LED1_Level
* 函数功能		   : LED1——IO电平输出
* 输    入         : Level: 1 —— 输出高;	0 —— 输出低
* 输    出         : 无
* 说	明		   :无
*******************************************************************************/
void LED1_Level(unsigned char Level)
{
	if (Level == 1)
	{
		// PB.5 输出高
		GPIO_SetBits(GPIOE,GPIO_Pin_5);
	}
	else if (Level == 0)
	{
		// PB.5 输出低
		GPIO_ResetBits(GPIOE,GPIO_Pin_5);
	}
}


  • key.h
#ifndef __KEY_H
#define __KEY_H	


#include "sys.h"
#include "delay.h"


enum E_KEY_PRES
{
	// 没按键按下
	E_KEY_PRES_NULL = 0,
	// KEY0 按下
	E_KEY_PRES_0,
	// KEY1 按下
	E_KEY_PRES_1,
	//KEY2 按下
	E_KEY_PRES_2,
	//KEY_UP 按下 (即WK_UP/KEY_UP)
	E_KEY_PRES_WK_UP
};


#define KEY0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) // 读取按键0
#define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) // 读取按键1
#define KEY2  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2) // 读取按键2 
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) // 读取按键3(WK_UP) 


void KEY_Init(void);
unsigned char KEY_Scan(void);	


#endif


  • key.c
#include "key.h"

								    
/*******************************************************************************
* 函 数 名         : KEY_Init
* 函数功能		   : KEY初始化函数
* 输    入         : 无
* 输    出         : 无
* 说	明		   :无
*******************************************************************************/
void KEY_Init(void)
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
	
	// KEY0
	// 使能 KEY0 时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
	// KEY0 按键的引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	// 设置按键的引脚为上拉输入
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	// 初始化 KEY0
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	
	
	// KEY1
	// 使能 KEY1 时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
	// KEY1 按键的引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	// 设置按键的引脚为上拉输入
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	// 初始化 KEY1
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	
	
	// KEY2
	// 使能 KEY2 时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
	// KEY2 按键的引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	// 设置按键的引脚为上拉输入
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	// 初始化 KEY2
	GPIO_Init(GPIOE, &GPIO_InitStructure);

	
	// WK_UP
	// 使能 WK_UP 时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	// WK_UP 按键的引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	// 设置按键的引脚为下拉输入
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	// 初始化 WK_UP
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}


/*******************************************************************************
* 函 数 名         : KEY_Scan
* 函数功能		   : KEY检测函数
* 输    入         : 无
* 输    出         : 
					E_KEY_PRES_NULL:没有按键被按下
					E_KEY_PRES_0:KEY0被按下
					E_KEY_PRES_1:KEY1被按下
					E_KEY_PRES_2:KEY2被按下
					E_KEY_PRES_WK_UP:WK_UP被按下
* 说	明		   :
					注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
*******************************************************************************/
unsigned char KEY_Scan(void)
{
	if ((0 == KEY0) || (0 == KEY1) || (0 == KEY2) || (1 == WK_UP))
	{
		// 去抖动
		Delay(0xff);
		if (0 == KEY0)
		{
			// 等待按键松手
			while(0 == KEY0);
			return E_KEY_PRES_0;
		}
		else if (0 == KEY1)
		{
			// 等待按键松手
			while(0 == KEY1);
			return E_KEY_PRES_1;
		}
		else if (0 == KEY2)
		{
			// 等待按键松手
			while(0 == KEY2);
			return E_KEY_PRES_2;
		}
		else if (1 == WK_UP)
		{
			// 等待按键松手
			while(1 == WK_UP);
			return E_KEY_PRES_WK_UP;
		}
	}
	return E_KEY_PRES_NULL;
}


  • main
#include "led.h"
#include "delay.h"
#include "key.h"


unsigned char Key_Status;


int main(void)
{	
	// LED GPIO 初始化
	LED_Init();
	// KEY GPIO 初始化
	KEY_Init();
	
	while(1)
	{
		Key_Status = KEY_Scan();
		
		switch (Key_Status)
		{
			case E_KEY_PRES_0:
			{
				LED0_Level(0);
				LED1_Level(0);
			}
			break;
			
			case E_KEY_PRES_1:
			{
				LED0_Level(1);
				LED1_Level(0);
			}
			break;
			
			case E_KEY_PRES_2:
			{
				LED0_Level(0);
				LED1_Level(1);
			}
			break;
			
			case E_KEY_PRES_WK_UP:
			{
				LED0_Level(1);
				LED1_Level(1);
			}
			break;
		}
	}	 
}


KEY GPIO 设置上拉模式、下拉模式或者浮空模式,这个取决于硬件。

当硬件有默认电平信号(非高阻态)时,只要按键按下时,会发生电平翻转,这种情况可以设置为浮空模式。

当硬件没有默认电平信号时,按下按键电平置 0 ,这种情况可以设置为上拉模式。
当硬件没有默认电平信号时,按下按键电平置 1 ,这种情况可以设置为下拉模式。

### 回答1: STM32是一款广泛使用的微控制器,具有丰富的GPIO(通用输入输出)口,可用于检测低电平的状态。 GPIO口有两种状态:输入和输出。 在输入模式下,GPIO口可以读取外部电平。 在输出模式下,GPIO口可以通过设置低电平来控制外部电路。要检测输入的低电平,需要先配置GPIO口为输入模式,然后读取该引脚的状态即可。 首先,需要在引脚模式设置寄存器(GPIOx_MODER)中将引脚模式设置为输入模式(00)。然后在GPIO输入数据寄存器(GPIOx_IDR)中读取引脚的状态。该寄存器的值将反映引脚的实际电平状态。 当读取该寄存器时,如果它返回的位(bit)是1,则表示电平。如果它返回的位是0,则表示低电平。 例如,检测GPIOB的引脚2是低电平还是电平的示例: 首先需要确保GPIOB口已启用,引脚2设置为输入模式 ``` RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //启用GPIOB的时钟 GPIOB->MODER &= ~(0x3 << (2*2)); //将GPIOB2的模式设置为输入模式 ``` 接着,就可以读取GPIOB_IDR寄存器,以获取该引脚的状态: ``` if(GPIOB->IDR & GPIO_IDR_2) { //GPIOB2是电平 } else { //GPIOB2是低电平 } ``` 这里使用位掩码(bitmask)GPIO_IDR_2来检测GPIOB2的状态。 在STM32中,要检测其他GPIO口的低电平也可以按照上述步骤进行。但请注意,如果引脚被配置为输出模式,GPIO_IDR寄存器中读取的状态将不准确。只有在引脚设置为输入模式时,GPIO_IDR寄存器才会返回正确的值。 ### 回答2: STM32是一系列基于ARM架构微控制器的处理器。其中的GPIO(General Purpose Input Output)引脚是用于与外部电路进行连接或者控制操作的通用输入输出引脚。通过对GPIO进行低电平检测,我们可以实现数字输入操作,同时也可以检测并处理外部设备信号。 在STM32GPIO模块中,我们可以通过几种不同的方式来检测低电平,包括轮询,中断和DMA(Direct Memory Access)等。以下是对每种方式的详细讲解: 1. 轮询 轮询是最基本的方式,也是最为常用的方式。在轮询模式下,处理器通过检测某个GPIO引脚所在的寄存器状态来实现对外部设备的状态监控。这种方式的优点是代码简单、易于实现,但是需要不断地进行轮询,会占用一定的CPU资源。 2. 中断 中断模式下,当GPIO检测到被监控的GPIO引脚状态发生改变时,会产生一个中断请求,让CPU去处理这个请求。这种方式节省了CPU资源,也能够及时响应异步事件发生,但是中断会有一定的响应延迟,且对程序的把握和安排要求比较。 3. DMA DMA模式下,我们通过DMA来监控GPIO引脚状态的变化,并将读取到的数据存储到指定的缓存区中。这种方式能够很好地解决数据传输的问题,具有很的效率和稳定性,但是实现较为复杂。 总之,STM32GPIO模块提供了多种方便的方式进行低电平检测。我们可以根据实际需要选择适用的方式来实现所需的操作。在实际项目中,我们可以根据具体情况灵活应用这些方式,来实现效、稳定、可靠的外部设备监控、数据处理、信号交互等应用。 ### 回答3: STM32是一种不同类型的嵌入式系统芯片,其包含了多个GPIO引脚以及具有丰富的外设,可用于实现各种嵌入式应用。可以通过按照编程规范并使用合适的GPIO寄存器和指令来检测STM32GPIO电平状态。 在最近几个硬件版本的STM32芯片处理器中,GPIO(Port)控制器的输入/输出和捕获引脚基本与软件GPIO而言相似。在STM32上使用GPIO检测低电平时,首先需要通过将PORT的相应位设置为输入模式来使用该引脚。这是通过对GPIO模式寄存器进行配置实现的。需要设置的寄存器名称可能会因芯片的型号而异,但通常都包括"Mode"、"Speed"和"PUPD"这三个参数。Mode参数设置为输入模式可启用该输入/输出引脚,详细配置方法请参考芯片的技术文档。 一旦输出引脚被设置为输入模式,可以使用GPIO访问寄存器来检测STM32芯片上输入引脚的状态。输入值可以使用GPIO输入数据寄存器来轮询,也可以使用GPIO输入数据寄存器中断来检测变化。轮询方式适用于需要读取输入状态的实时任务,而中断方法适用于需要响应输入变化的应用程序。 在轮询方法中,库函数中的GPIO_ReadInputDataBit可以用于读取GPIO引脚输入的实际状态。该函数将返回具有精度的1个TRUE / FALSE值,如果为真,则说明输入电平在ON状态,如果为假,则说明输入电平是OFF状态。通过调用GPIO_ReadInputDataBit以便轮询,可以很容易地在代码中检测输入电平,然后执行相应的操作。 以上就是 STM32 GPIO 检测低电平的基本方法及应用场景。需要注意的是,在STM32板上操作引脚时请仔细阅读数据手册并使用正确的GPIO模式寄存器和指令,在电路连接时,请充分注意输入电压范围及其他特殊设置需求,以保证系统的安全运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值