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
#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; //引腳7gpio_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
#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_4gpio_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
#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();
}
這段代碼,當處于警戒模式并且報警時,按下退出警戒模式的按鈕就可以直接退出警戒模式,不用再響一秒。