1.项目需求
按下遥控器 A 按键,系统进入警戒模式,一旦检测到震动(小偷偷车),则喇叭发出声响报警,吓退小偷。
按下遥控器 B 按键,系统退出警戒模式,再怎么摇晃系统都不会报警。
2.硬件
- STM32单片机最小系统
- 震动传感器模块
- 继电器模块
- 433M无线收发模块
- 蜂鸣器模块
硬件接线
STM32 | 震动传感器 | 继电器 | 433M |
---|---|---|---|
PA4 | DO | ||
PB7 | I/O | ||
PB5 | D0 | ||
PA12 | D1 | ||
3V3 | VCC | VCC | |
5V | 5V | ||
GND | GND | GND | GND |
3.项目流程
4.软件
#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(); /* 初始化LED灯 */
exti_init(); /* 初始化EXTI */
alarm_init(); /* 初始化继电器 */
uint8_t alert_mode = FALSE; //警戒模式标志
while(1)
{
//A按键是否按下? 按照流程图
if(buttonA_flag_get() == TRUE)
{
alarm_on();
delay_ms(2000);
alarm_off();
alert_mode = TRUE;//进入警戒模式
}
//B按键是否按下?
if(buttonB_flag_get() == TRUE)
{
if(alarm_status_get() == ALARM_STATUS_ON)//如果B按键按下时,喇叭在响,立即关闭喇叭
alarm_off();
else //如果B按键按下时,喇叭不响,则让喇叭响1s后关闭喇叭
{
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);//清除标志位,防止按下B按键退出后按A按键长响(一直处于TRUE状态)
}
}
- exti.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)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
//按键B中断配置
gpio_initstruct.Pin = GPIO_PIN_12; // 按键B对应的引脚
gpio_initstruct.Mode = GPIO_MODE_IT_RISING; // 上升沿触发
gpio_initstruct.Pull = GPIO_PULLDOWN; // 下拉
HAL_GPIO_Init(GPIOA, &gpio_initstruct);
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0); // 设置EXTI15_10中断线的优先级
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); // 使能中断
//按键A中断配置
gpio_initstruct.Pin = GPIO_PIN_5; // 按键A对应的引脚
gpio_initstruct.Mode = GPIO_MODE_IT_RISING; // 上升沿触发
gpio_initstruct.Pull = GPIO_PULLDOWN; // 下拉
HAL_GPIO_Init(GPIOB, &gpio_initstruct);
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 2, 0); // 设置EXTI9_5中断线的优先级
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); // 使能中断
//震动传感器中断配置
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); // 使能中断
}
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 EXTI4_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
}
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;
}
- exti.h程序
#ifndef __EXTI_H__
#define __EXTI_H__
#include "stdint.h"
#define TRUE 1
#define FALSE 0
void exti_init(void);
uint8_t buttonA_flag_get(void);
void buttonA_flag_set(uint8_t value);
uint8_t buttonB_flag_get(void);
void buttonB_flag_set(uint8_t value);
uint8_t vibrate_flag_get(void);
void vibrate_flag_set(uint8_t value);
#endif
- alarm.c
#include "alarm.h"
#include "sys.h"
//初始化GPIO函数
void alarm_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); // 使能GPIOB时钟
//调用GPIO初始化函数
gpio_initstruct.Pin = GPIO_PIN_7; // 继电器对应的引脚
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
alarm_off();
}
//闭合继电器的函数
void alarm_on(void)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); // 拉低LED1引脚,点亮LED1
}
//松开继电器的函数
void alarm_off(void)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET); // 拉高LED1引脚,熄灭LED1
}
//获取继电器状态的函数
uint8_t alarm_status_get(void)
{
return (uint8_t)HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
}
- alarm.h
#ifndef __ALARM_H__
#define __ALARM_H__
#include "stdint.h"
#define ALARM_STATUS_ON 0
#define ALARM_STATUS_OFF 1
void alarm_init(void);
void alarm_on(void);
void alarm_off(void);
uint8_t alarm_status_get(void);
#endif
5.实物效果
- BUG调试