锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

【单片机】人体感应模块

时间:2022-08-07 17:30:00 05n感应传感器

文章目录

  • 前言
  • 模块介绍(可跳)
  • 模块使用
    • 代码:h文件
    • 代码:c文件
    • 代码使用方法
    • 补充介绍(可/不可重复触发)
  • 代码获取

前言

大家好,我是林白柏;

希望看完能有所收获。请纠正不足!

PS:本文提到的所有模块都使用正点原子stm32开发板战舰某宝现成的模块驱动模块。


模块介绍(可跳)

该模块由菲涅尔透镜、热释电红外探头和放大电路组成。

用于提高探头灵敏度的菲涅尔透镜。

镜头在探头前产生交替变化的盲区和高灵敏区,使人体通过时,人体发射的红外线会不断交替通过盲区和高灵敏区,便于探头产生脉冲信号。

当热释电红外探头检测到人体发出的红外线时,会发出脉冲信号(脉冲宽度固定);有人时,人体产生的红外线会交替出现在盲区和高灵敏区,总会有脉冲信号输出(实测者静止时似乎不会输出)。

是通过放大器BISS001将脉冲信号转换为更直观的高低电平输出,有些人输出高,无人输出低。并在放大电路上设置电位器,调整输出信号的灵敏度(如探头产生n脉冲,模块输出高电平),调整高电平的持续时间。

image-20220419210118203

模块使用

模块接口只有三脚,地面、电源、数据线;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

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章