GPIO输入-外电检测

前言

(1)本系列是基于STM32的项目笔记,内容涵盖了STM32各种外设的使用,由浅入深。

(2)小编使用的单片机是STM32F105RCT6,项目笔记基于小编的实际项目,但是博客中的内容适用于各种单片机开发的同学学习和使用。

学习目标

  1. 外电检测电路原理的分析。
  2. 外电检测程序代码的开发,掌握GPIO口输入模式的配置。
  3. 实验效果:外电连接LED1亮,外电断开 LED1灭。

外电检测硬件原理图

原理分析

外电的状态是通过PB1端口来检测的。 那分别分析PB1 在没有外电输入和有外电输入的状态。

(1)外电断开

PB1 通过下拉电阻R55 接地,PB1输入低电平。

(2)外电输入端口连接5V供电

R55/(R54+R55) = VR55(A点) / 5V (VR54+R55)

PB1的电压值为:VR55 =5*200 /(100+200) = 3.33V,高电平。

程序实现--外电状态检测

外电检测GPIO的初始化

端口定义: 外电检测的端口是PB1
// AC Check Pin
#define CHECK_ACSTATE_PORT       GPIOB
#define CHECK_ACSTATE_PIN           GPIO_Pin_1

PB1的初始化GPIO的初始化:

void hal_GpioConfig_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE); 	
	
	GPIO_InitStructure.GPIO_Pin = CHECK_ACSTATE_PIN;     
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //浮空输入
	GPIO_Init(CHECK_ACSTATE_PORT, &GPIO_InitStructure);	
	
        AcState = (en_AcLinkSta)hal_GPIO_GetACState();  /// 
} 

上拉,下拉,悬空方式的选择:

选择浮空输入模式

typedef enum
{ GPIO_Mode_AIN = 0x0,//模拟输入
  GPIO_Mode_IN_FLOATING = 0x04,//浮空输入
  GPIO_Mode_IPD = 0x28,//上拉输入
  GPIO_Mode_IPU = 0x48,//下拉输入
  GPIO_Mode_Out_OD = 0x14,//通用开漏输出
  GPIO_Mode_Out_PP = 0x10,//通用推挽输出
  GPIO_Mode_AF_OD = 0x1C,//复用开漏输出
  GPIO_Mode_AF_PP = 0x18//复用推挽输出
}GPIOMode_TypeDef;

如果GPIO模式选择: 上拉输入, 则在外电掉电的状态下 PB1 也是高电平。

GPIO模式选择上拉输入时,Rdo不存在,此时电路中只有其他3个电阻,不论外电连接或断开,PB1均被上拉电阻拉高,为高电平。

如果GPIO模式选择: 下拉输入, 则在外电连接的状态下 PB1的电平会变小。

GPIO模式选择下拉输入时,Rup不存在,此时电路中只有其他3个电阻,R55 和RDO 并联之后整体的阻值变小, R54不变。根据串联电路分压, PB1的电压会变小。

常用的GPIO输入库函数

GPIO 常用输入函数
//读取单个输入端口的数据
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

//读取单个输入端口的数据
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

//读取单个输入端口的数据
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

//读取单个输入端口的数据
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

定义外电状态枚举类型变量

typedef enum
{
	 STA_AC_BREAK = 0,
	  STA_AC_LINK,
}en_AcLinkSta;

外电检测函数

// 获取PB1端口状态(高低电平)
static unsigned char hal_GPIO_GetACState(void)
{
	return (GPIO_ReadInputDataBit(CHECK_ACSTATE_PORT,  CHECK_ACSTATE_PIN ));		
}
void delay_1msTest(void)
{
	unsigned int i=0;
	i = 72000;
	while(i--);   
}

外电检测函数任务
返回值   外电的状态
en_AcLinkSta hal_Gpio_AcStateCheck(void)
{
	en_AcLinkSta state;
	static unsigned char times = 0;	//静态延时计数
	state = (en_AcLinkSta)hal_GPIO_GetACState();//记录第一次检测到的外电状态
	delay_1msTest();
	if(state == AcState)
	{如果本次获取的状态和上次一样,则清零延时计数
		times	= 0;
	}
	else if(state != AcState)
  {///如果状态有变化
		times	++; //计数增加
		if(times > 20)
		{如果不一样的状态计数超过20次  则更新 AcState 状态。
			times = 0;
			AcState = state;
		}
	}
	return AcState;///
}
///

hal_GPIO.h代码

#ifndef ____HAL_GPIO_H_
#define ____HAL_GPIO_H_
 
// AC Check Pin
#define CHECK_ACSTATE_PORT       GPIOB
#define CHECK_ACSTATE_PIN        GPIO_Pin_1

typedef enum
{
		STA_AC_BREAK = 0,
	  STA_AC_LINK,
}en_AcLinkSta;

void hal_GpioConfig_init(void);
en_AcLinkSta hal_Gpio_AcStateCheck(void);

#endif
//

hal_GPIO.c代码

#include "stm32F10x.h"
#include "hal_GPIO.H"

static unsigned char hal_GPIO_GetACState(void);

static en_AcLinkSta AcState;// 外电的状态静态全局变量

/GPIO 初始化函数
void hal_GpioConfig_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE); 	
	
	GPIO_InitStructure.GPIO_Pin = CHECK_ACSTATE_PIN;     
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //浮空输入
	GPIO_Init(CHECK_ACSTATE_PORT, &GPIO_InitStructure);	
	
  AcState = (en_AcLinkSta)hal_GPIO_GetACState();  ///上电获取外电的状态   
}

// 获取PB1端口状态(高低电平)
static unsigned char hal_GPIO_GetACState(void)
{
	return (GPIO_ReadInputDataBit(CHECK_ACSTATE_PORT, GPIO_Pin_1));		
}
void delay_1msTest(void)
{
	unsigned int i=0;
	i = 7200;
	while(i--);   
}


en_AcLinkSta hal_Gpio_AcStateCheck(void)
{
	en_AcLinkSta state;
	static unsigned char times = 0;	//静态延时计数
	
	state = (en_AcLinkSta)hal_GPIO_GetACState();
	
	delay_1msTest();
	if(state == AcState)
	{如果本次获取的状态和上次一样,则清零延时计数
		times	= 0;
	}
	else if(state != AcState)
  {///如果状态有变化
		times	++; //计数增加
		if(times > 20)
		{如果不---样的状态计数超过20次 则更新 Acstate 状态。
			times = 0;
			AcState = state;
		}
	}
	return AcState;///
}
///

修改main函数

#include "stm32f10x.h"
#include "hal_timer.h"
#include "hal_led.h"
#include "hal_gpio.h"

int main(void)
{
	hal_LedInit();
	hal_GpioConfig_init();
//	hal_timerInit();
  while (1)
  {		
		if(hal_Gpio_AcStateCheck() == STA_AC_BREAK)
		{
			GPIO_ResetBits(LED7_PORT,LED7_PIN);
		}
		else
		{	
			GPIO_SetBits(LED7_PORT,LED7_PIN);			
		}
  }
}
相关推荐
Qingniu012 小时前
【青牛科技】GC3901,强势替代 A3901/ALLEGRO应用于摇头机等产品中
科技·单片机·打印机·摇头机·白色家电
顶点元3 小时前
STM32 ADC --- DMA采样
stm32·adc
Kasen's experience3 小时前
STM32 串口输出调试信息
stm32·单片机·嵌入式硬件·串口
Darkwanderor3 小时前
插入排序——希尔排序
c语言·算法·排序算法·希尔排序
沐泽Mu4 小时前
嵌入式学习-C嘎嘎-Day04
c语言·开发语言·c++·学习
(●'◡'●)知4 小时前
详细解析STM32 GPIO引脚的8种模式
stm32·单片机·嵌入式硬件
谏书稀5 小时前
Keil基于ARM Compiler 5的工程迁移为ARM Compiler 6的工程
arm开发·单片机
挥剑决浮云 -5 小时前
Linux 网络编程
linux·运维·c语言·网络·笔记
析木不会编程5 小时前
【数据结构】【线性表】循环链表(附C语言源码)
c语言·数据结构·链表
写bug的小屁孩5 小时前
基于HTTP编写ping操作
服务器·c语言·网络·c++·网络协议·http·qt6.3