【单片机】人体感应模块
时间:2022-08-07 17:30:00
文章目录
- 前言
- 模块介绍(可跳)
- 模块使用
-
- 代码:h文件
- 代码:c文件
- 代码使用方法
- 补充介绍(可/不可重复触发)
- 代码获取
前言
大家好,我是林白柏;
希望看完能有所收获。请纠正不足!
PS:本文提到的所有模块都使用正点原子stm32开发板战舰某宝现成的模块驱动模块。
模块介绍(可跳)
该模块由菲涅尔透镜、热释电红外探头和放大电路组成。
用于提高探头灵敏度的菲涅尔透镜。
镜头在探头前产生交替变化的盲区和高灵敏区,使人体通过时,人体发射的红外线会不断交替通过盲区和高灵敏区,便于探头产生脉冲信号。
当热释电红外探头检测到人体发出的红外线时,会发出脉冲信号(脉冲宽度固定);有人时,人体产生的红外线会交替出现在盲区和高灵敏区,总会有脉冲信号输出(实测者静止时似乎不会输出)。
是通过放大器BISS001将脉冲信号转换为更直观的高低电平输出,有些人输出高,无人输出低。并在放大电路上设置电位器,调整输出信号的灵敏度(如探头产生n脉冲,模块输出高电平),调整高电平的持续时间。
模块使用
模块接口只有三脚,地面、电源、数据线;GND、VCC、OUT
探头检测到有人移动时,OUT=1;没人移动时,OUT=0;
所以我们可以把它作为一个独立的按钮,按下时(有人移动)为1,松开时(无人移动)为0。
我们将IO口初始化为外部中断和跳变沿触发,中断时,读取中断服务函数IO状态,IO=一是上升沿-有人移动,IO=0是下降边-无人移动。(见头文件human_body_induction.c部分)
将事件返回到事件回调函数。(见头文件human_body_induction.h部分)
代码:h文件
头文件*(为了一个按钮包装两个文件真的太仪式了,哈哈哈)*将两个事件定义为返回事件回调函数。
typedef enum {
HBI_NOBODY,//无人移动 HBI_PEOPLE_MOVING,//有人移动 }hbi_evt_t; typedef void ( * hbi_evt_handle_t )( hbi_evt_t * event );///事件回调函数类型 void hbi_init( hbi_evt_handle_t event_handle);///初始化函数声明
代码:c文件
源文件分为初始化和中断服务函数两部分。
初始函数,初始化io、中断并保存回调函数指针。
static hbi_evt_handle_t m_event_handle; ///保存用户传输的回调函数指针 void hbi_init( hbi_evt_handle_t event_handle) {
GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //[ 与硬件相关 ] //使外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PORTG口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); ///使能复用功能时钟 //将IO初始化为下拉输入(似乎可以上拉下拉) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructur.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOG, &GPIO_InitStructure);
//配置GPIOG.8为中断线EXTI_Line8的中断源(这部分需要去了解stm32中断相关知识)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOG,GPIO_PinSource8);
//EXTI_Line8初始化为跳变沿触发
EXTI_InitStructure.EXTI_Line = EXTI_Line8;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
//初始化中断分组
NVIC_InitStructure.NVIC_IRQChannel = HBI_EXTI_IRQ_CHANNEL;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
//[ 与硬件无关 ]
//保存用户传进来的回调函数指针,中断服务函数中使用
m_event_handle = event_handle;
}
中断服务函数中,根据中断类型返回相应的事件给用户
void EXTI9_5_IRQHandler(void)//stm32中,中断线5-9公用一个中断服务函数
{
if(EXTI_GetITStatus( EXTI_Line8 ) != RESET)
{
hbi_evt_t evt = HBI_NOBODY;
EXTI_ClearFlag( EXTI_Line8 ); //清除中断标志位
EXTI_ClearITPendingBit( EXTI_Line8 ); //清除EXTI线路挂起位
if( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_8) ) {
//上升沿
evt = HBI_PEOPLE_MOVING;
}
else {
//下降沿
evt = HBI_NOBODY;
}
m_event_handle( &evt );
}
}
代码使用方法
初始化时,应用程序注册一个回调函数,后续就只需要在回调函数中判断事件并执行相应操作即可
//以下使用演示
static void bi_evt_cb( hbi_evt_t * event ) {
//定义事件回调函数
switch ( *event ) {
case HBI_NOBODY : _LOG_DEBUG("[hbi] nobody\n\n"); break;
case HBI_PEOPLE_MOVING : _LOG_DEBUG("[hbi] people moving\n\n");; break;
}
}
int main(void){
hbi_init( hbi_evt_cb );//将回调函数指针传给初始化函数
while(1);
}
补充介绍(可/不可重复触发)
模块还有一个重复触发和不重复触发的概念,由BISS0001实现(具体实现方式查看BISS0001规格书),两者的区别如下图红色方框
不可重复触发,探头产生脉冲时,模块out脚输出高电平,时长Tx;在Tx结束前,探头产生的脉冲都无效。
可重复触发,探头产生脉冲时,模块out脚输出高电平,时长Tx;在Tx结束前,探头产生新的脉冲,则从新的脉冲处开始重新计时Tx。只要Tx结束前一直有脉冲产生,则模块高电平会一直持续下去。
可通过模块上跳线帽进行设置,L(不可重复触发)和H(可重复触发)
代码获取
共用代码:https://gitee.com/sumoting1629/mcu-practice/tree/master/common
驱动代码:https://gitee.com/sumoting1629/mcu-practice/tree/master/component