STM32—一文搞定震动传感器
目录
震动传感器简介:
SW-18010P的主要特点:
SW-18010P接线如下:
SW-18010P的工作原理:
编写代码驱动震动传感器:
代码部分:
led.c
led.h
exti.c
exti.h
main.c
震动传感器简介:
SW-18010P:这是一个振动传感器,用于检测外部的振动。它能够通过内部的金属触点的微小位移来感应振动,并转化为电信号。
SW-18010P的主要特点:
1.高灵敏度:传感器的灵敏度可以通过电位器进行调节,适用于各种强度的振动检测场景。
2. 简单易用:模块设计简洁,直接提供3针输出接口(VCC、GND、DO),便于与单片机等控制设备连接。
3. 数字信号输出:传感器检测到振动后,会输出一个高低电平信号,非常适合用于简单的开关信号检测。
4. LED状态指示:
电源指示灯显示模块是否正常通电。
信号指示灯在检测到振动时亮起,便于调试与观察。
5. 适用电压范围宽:支持3.3V至5V电源供电,兼容多种常见开发板和微控制器(如Arduino、ESP8266等)。
6. 体积小巧:模块设计紧凑,便于嵌入各种设备或系统中,尤其适用于便携式或空间有限的应用场景。
7. 低功耗:在没有振动信号输入时,模块功耗非常低,适合电池供电的设备。
SW-18010P接线如下:
SW-18010P | STM32 |
---|---|
VCC | 3.3或5V |
GND | GND |
DO | 任意 GPIO 口 |
AO | 模拟输出,无效,不接 |
SW-18010P的工作原理:
传感器感应到振动 → 信号传递到处理电路 → 超过灵敏度阈值时输出高电平 → LED指示灯点亮 → 数字信号传递给外部控制器。
SW-18015P 在静止时为开路 OFF 状态, 当受到外力碰触而达到相应震动力时,或者移动速度达到适当离(偏)心力时,导电接脚会产生瞬间导通呈瞬间 ON 状态;当外力消失時,开关恢复为开路 OFF 状态。
所以,SW-18015P 在无震动或者震动强度达不到设定阈值时,DO 口输出高电平,当外界震动强度超过设定阈值时,模块 D0 输出低电平。
编写代码驱动震动传感器:
我们本次实验为震动传感器震动点灯实验。
首先我们要明确的是我们将采用中断法来对震动传感器的信号进行判断然后再点亮灯,因此我们需要开启中断、调用中断服务函数和中断回调函数。并且我们需要初始化相应的GPIO口。
中断线,我们选择的引脚是PA4,因此中断线是EXTI4(EXTI4对应所有结尾为4的引脚:PB4、PC4)
中断中的延时处理:
在中断中我们尽量不要加上延时的函数,这样会导致导致一系列的问题:
1.影响中断服务的实时性要求——会导致中断函数执行时间过长,从而影响系统的实时性,进而导致其他重要任务的延迟或丢失。
2. 占用系统资源——延时函数通常通过计数器或忙等待的方式来实现,这样会占用CPU资源。在中断函数中使用延时函数,可能会导致CPU长时间被阻塞,其他的中断和任务无法及时执行。
3. 嵌套中断问题——如果某个中断函数执行时间过长,其他优先级较高的中断可能无法及时被处理,导致优先级倒置或者中断丢失,严重影响系统的正常运行。
所以我们在中断里面去设置一个标志位—— vibrate_flag,当中断触发的时候,就将标志位vibrate_flag设置为TRUE。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_4) //检查中断触发的引脚是否是 GPIOA 的引脚 4
{
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET)
vibrate_flag = TRUE ;
}
}
然后,我们再在主函数里面去判断标志位的情况,以此来做出相应的反应,这样能够合理利用中断,不至于在中断中停留太多的时间,提高代码的整体运行效率,减少CPU资源的占用。
if(vibrate_flag_get()==TRUE)
{
led2_on();
delay_ms(2000);
led2_off();
vibrate_flag_set(FALSE);
}
代码部分:
led.c
#include "led.h"
#include "sys.h"
//初始化GPIO函数
void led_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
//调用GPIO初始化函数
gpio_initstruct.Pin = GPIO_PIN_9; // 两个LED对应的引脚
gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOB, &gpio_initstruct);
//关闭LED
led1_off();
led2_off();
}
//点亮LED2的函数
void led2_on(void)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET); // 拉低LED2引脚,点亮LED2
}
//熄灭LED2的函数
void led2_off(void)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET); // 拉高LED2引脚,熄灭LED2
}
//翻转LED2状态的函数
void led2_toggle(void)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
}
led.h
#ifndef __LED_H__
#define __LED_H__
void led2_on(void);
void led2_off(void);
void led2_toggle(void);
#endif
exti.c
#include "exti.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
uint8_t vibrate_flag = FALSE ;
void exti_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
//调用GPIO初始化函数
gpio_initstruct.Pin = GPIO_PIN_4; // 按键对应的引脚
gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOA, &gpio_initstruct);
HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0); // 设置EXTI0中断线的优先级
HAL_NVIC_EnableIRQ(EXTI4_IRQn); // 使能中断
}
/* EXTI4 的中断服务函数(ISR)。当 GPIOA 引脚 4 触发中断时,该函数会被调用*/
void EXTI4_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
}
/*HAL 库定义的外部中断回调函*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_4) //检查中断触发的引脚是否是 GPIOA 的引脚 4
{
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET)
vibrate_flag = TRUE ;
}
}
/*设置一个标志位——这样就不用在中断里面去延时*/
uint8_t vibrate_flag_get(void)
{
uint8_t temp= vibrate_flag;
vibrate_flag = FALSE;
return temp;
}
void vibrate_flag_set(uint8_t vlue)
{
vibrate_flag = vlue;
}
exti.h
#ifndef __EXTI_H__
#define __EXTI_H__
#include "stdint.h"
#define TRUE 1
#define FALSE 0
void exti_init(void);
uint8_t vibrate_flag_get(void);
void vibrate_flag_set(uint8_t vlue);
#endif
main.c
#include "delay.h"
#include "led.h"
#include "exti.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
exti_init(); /* 初始化EXTI */
while(1)
{
if(vibrate_flag_get()==TRUE)
{
led2_on();
delay_ms(2000);
led2_off();
vibrate_flag_set(FALSE);
}
}
}
作者:庆庆知识库