1.實驗目的
使用中斷的方法,震動傳感器檢測到震動時,LED1點亮2秒,之后熄滅。
2.硬件清單
- 震動傳感器
- STM32開發板
- ST-Link
3.硬件連接
STM32 | 震動傳感器 |
---|---|
PA4 | DO |
3V3 | VCC |
GND | GND |
4.代碼
4.1exti.c
#include "exti.h"
#include "sys.h"
#include "delay.h"
#include "led.h"uint8_t vibrate_flag = FALSE;void exti_init(void)
{__HAL_RCC_GPIOA_CLK_ENABLE();GPIO_InitTypeDef gpio_initstruct;//初始化GPIOgpio_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_GPIO_Init(GPIOA, &gpio_initstruct);//設置中斷線HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);HAL_NVIC_EnableIRQ(EXTI4_IRQn);}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_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 value)
{vibrate_flag = value;
}
4.2main.c
#include "sys.h"
#include "uart1.h"
#include "delay.h"
#include "exti.h"
#include "led.h"int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */led_init();exti_init();while(1){ if(vibrate_flag_get() == TRUE){led1_on();delay_ms(2000);led1_off();vibrate_flag_set(FALSE);}}
}
4.3exti.h
#ifndef __HAL_EXTI_H
#define __HAL_EXTI_H#include "stdint.h"#define TRUE 1
#define FALSE 0void exti_init(void);
uint8_t vibrate_flag_get(void);
void vibrate_flag_set(uint8_t value);#endif
exti_init這個函數就是中斷的相關配置,在之前的文章有講。
因為在中斷函數中最好不要出現延時函數,
所以這里是用了標志的方法,
在大型項目中一般就寫兩個函數uint8_t vibrate_flag_get(void);
和void vibrate_flag_set(uint8_t value);
來分別傳出標志符和修改標志符。
然后我在.h文件中宏定義了兩個符號TRUE和FALSE,使用vibrate_flag變量保存.
分別表示震動模塊的打開和關閉。
但是因為當震動模塊打開后,沒有將vibrate_flag變量復位為FALSE,
這樣就會造成main函數中的if一直成立燈就會一直亮,
所以就使用定義臨時變量temp來將vibrate_flag變量復位為FALSE。
還有一個問題就是當碰一下震動模塊,震動模塊會觸發很多上升沿和下降沿,
導致燈不會亮2秒,會亮很多秒,
所以在延時兩秒后又通過vibrate_flag_set函數將vibrate_flag手動復位為FALSE。