1.项目需求
点击遥控器A按键,系统进入警戒模式,一旦检测到震动(小偷偷车),则喇叭发出声响报警,吓退小偷。
点击遥控器B按键,系统退出警戒模式,再怎么摇晃系统都不会报警,否则系统一直发出尖叫,让车主尴尬。
2.硬件清单
- 震动传感器
- 继电器
- 高功率喇叭
- 433M无线接收发射模块
- 杜邦线
- STM32开发板
- ST-Link
3.硬件接线
STM32 | 震动传感器 | 继电器 | 433M |
---|---|---|---|
PA4 | D0 | ||
PB7 | I/O | ||
PB5 | D0 | ||
PA12 | D1 | ||
3V3 | VCC | VCC | |
5V | 5V | ||
GND | GND | GND | GND |
4.项目流程图

5.代码
alarm.c
c
#include "alarm.h"
#include "sys.h"
void alarm_init(void)
{
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
GPIO_InitTypeDef gpio_initstruct; //初始化GPIO函数中的结构体参数
gpio_initstruct.Mode =GPIO_MODE_OUTPUT_PP ; //推挽输出
gpio_initstruct.Pin = GPIO_PIN_7; //引脚7
gpio_initstruct.Pull = GPIO_PULLUP; //上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; //高速
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
alarm_off();
}
//打开继电器函数
void alarm_on(void)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET); //拉低PB7引脚打开继电器
}
//关闭继电器函数
void alarm_off(void)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET); //拉高PB7引脚关闭继电器
}
uint8_t alarm_status_get(void)
{
return (uint8_t)HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7);
}
这个代码是关于继电器的代码,其中uint8_t alarm_status_get(void)函数是用来检测继电器的状态的
exti.c
c
#include "exti.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
uint8_t buttonA_flag = FALSE; //检测A按键标志位
uint8_t buttonB_flag = FALSE; //检测B按键标志位
uint8_t vibrate_flag = FALSE; //检测到震动标志位
void exti_init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef gpio_initstruct;
//初始化GPIOA_12函数
gpio_initstruct.Mode =GPIO_MODE_IT_RISING; //上升沿触发
gpio_initstruct.Pin =GPIO_PIN_12; //按键B对应的引脚
gpio_initstruct.Pull =GPIO_PULLDOWN; //下拉
gpio_initstruct.Speed =GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
HAL_NVIC_SetPriority(EXTI15_10_IRQn,2,0); //设置EXTI15_10中断的优先级
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); //使能中断
//初始化GPIOB_5函数
gpio_initstruct.Mode =GPIO_MODE_IT_RISING; //上升沿触发
gpio_initstruct.Pin =GPIO_PIN_5; //按键A对应的引脚
gpio_initstruct.Pull =GPIO_PULLDOWN; //下拉
gpio_initstruct.Speed =GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB,&gpio_initstruct);
HAL_NVIC_SetPriority(EXTI9_5_IRQn,2,0); //设置EXTI9_5中断优先级
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); //使能中断
//初始化GPIOA_4
gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; //下降沿触发
gpio_initstruct.Pin = GPIO_PIN_4; //震动传感器对应的引脚
gpio_initstruct.Pull = GPIO_PULLUP; //上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_NVIC_SetPriority(EXTI4_IRQn,2,0); //设置EXTI4中断线的优先级
HAL_NVIC_EnableIRQ(EXTI4_IRQn); //使能中断
HAL_GPIO_Init(GPIOA,&gpio_initstruct);
}
void EXTI4_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
}
//回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_12) //检测按下B按键
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12) == GPIO_PIN_SET)
{
buttonB_flag = TRUE;
}
}
else if(GPIO_Pin == GPIO_PIN_5) //检测按下A按键
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5) == GPIO_PIN_SET)
{
buttonA_flag = TRUE;
}
}
else if(GPIO_Pin == GPIO_PIN_4) //检测震动传感器
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4) == GPIO_PIN_RESET)
{
vibrate_flag = TRUE;
}
}
}
uint8_t buttonA_flag_get(void)
{
uint8_t temp = buttonA_flag;
buttonA_flag = FALSE;
return temp;
}
void buttonA_flag_set(uint8_t value)
{
buttonA_flag = value;
}
uint8_t buttonB_flag_get(void)
{
uint8_t temp = buttonB_flag;
buttonB_flag = FALSE;
return temp;
}
void buttonB_flag_set(uint8_t value)
{
buttonB_flag = value;
}
uint8_t vibrate_flag_get (void)
{
uint8_t temp = vibrate_flag;
vibrate_flag = FALSE;
return temp;
}
void vibrate_flag_set (uint8_t value)
{
vibrate_flag = value;
}
这个代码是中断的代码,里面有两个按键和震动传感器的中断。
main.c
c
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "exti.h"
#include "alarm.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init();
exti_init();
alarm_init();
uint8_t alert_mode = FALSE;
while(1)
{
if(buttonA_flag_get() == TRUE )
{
alarm_on();
delay_ms(2000);
alarm_off();
alert_mode = TRUE;
}
if(buttonB_flag_get() == TRUE)
{
if(alarm_status_get() == ALARM_STATUS_ON)
{
alarm_off();
}
else
{
alarm_on();
delay_ms(1000);
alarm_off();
}
alert_mode = FALSE;
}
if(alert_mode == TRUE)
{
if(vibrate_flag_get() == TRUE)
{
alarm_on();
}
}
else
{
vibrate_flag_set(FALSE);
}
}
}
这个代码就是根据流程图的逻辑写的代码。
这里面有两个细节
1.就是vibrate_flag_set(FALSE);这行代码,当我们退出警戒模式后,要将震动的标志位一直处于FALSE状态。
2.就是 if(alarm_status_get() == ALARM_STATUS_ON)
{
alarm_off();
}
else
{
alarm_on();
delay_ms(1000);
alarm_off();
}
这段代码,当处于警戒模式并且报警时,按下退出警戒模式的按钮就可以直接退出警戒模式,不用再响一秒。