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;
//初始化GPIO
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_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 0
void 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。