前言
(1)本系列是基于STM32的项目笔记,内容涵盖了STM32各种外设的使用,由浅入深。
(2)小编使用的单片机是STM32F105RCT6,项目笔记基于小编的实际项目,但是博客中的内容适用于各种单片机开发的同学学习和使用。
学习目标
- 外电检测电路原理的分析。
- 外电检测程序代码的开发,掌握GPIO口输入模式的配置。
- 实验效果:外电连接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_1typedef 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); }}
}