使用STM32 再实现电动车防盗钥匙扣

实现目标

1. 点击遥控器 A 按键,系统进入警戒模式,一旦检测到震动(小偷偷车),则喇叭发出声响报警

2. 点击遥控器 B 按键,系统退出警戒模式,再怎么摇晃系统都不会报警

硬件介绍

1. 震动传感器

使用STM32 再实现电动车防盗钥匙扣_第1张图片

产生震动时,会输出低电平,绿色指示灯亮(开关信号指示灯)

2. 继电器模块

 (VCC 3.3V)当左侧IN输入低电平时,右侧的ON 和 COM会导通,左上的绿灯会亮

3. 遥控收发 433M

使用STM32 再实现电动车防盗钥匙扣_第2张图片使用STM32 再实现电动车防盗钥匙扣_第3张图片

发送端按下ABCD会在接收端被芯片调制解调,最终解析成不同的信号来识别,接收端的D0, D1, D2, D3 对应A,B,C,D,收到哪个对应的信号,相应的引脚就会给出高电平。

CubeMX配置

1. 惯例配置使用STM32 再实现电动车防盗钥匙扣_第4张图片

使用STM32 再实现电动车防盗钥匙扣_第5张图片 

2. 由于震动传感器的DO口接到了PA4,所以将PA4配置成中断模式,且由于DO口拉低代表有震动,所以将模式改为下降沿触发

 使用STM32 再实现电动车防盗钥匙扣_第6张图片

 3. 配置其他需要使用到的GPIO口, 433M的D0和D1都是上升沿触发无需修改

使用STM32 再实现电动车防盗钥匙扣_第7张图片

使用STM32 再实现电动车防盗钥匙扣_第8张图片

4. 在NVIC中打开中断: 

 

5. 惯例设置并生成代码

使用STM32 再实现电动车防盗钥匙扣_第9张图片使用STM32 再实现电动车防盗钥匙扣_第10张图片

Keil5 代码实现

打开stm32f1xx_it.c --> EXTI4(9_5)_IRQHandler() --> HAL_GPIO_EXTI_IRQHandler() --> HAL_GPIO_EXTI_Callback( )

 使用STM32 再实现电动车防盗钥匙扣_第11张图片

 HAL_GPIO_EXTI_Callback()就是中断处理程序,将他在main.c中重写

注意,如果直接在中断服务函数里调用 HAL_Delay 函数,则会造成系统卡死。 

原因:程序初始化时默认把滴答定时器的中断优先级设为最低,其它中断源很容易打断它导致卡死,也就是说当Delay函数在进行中的时候,如果又发生了震动触发了外部中断,就会又立刻执行这个中断处理程序,导致喇叭一直在响无法停下。

解决办法:

在 main 函数里使用以下函数提高滴答定时器的中断优先级(提升至0);

HAL_NVIC_SetPriority(SysTick_IRQn,0,0); //必须写在" SystemClock_Config() "后面!!!

并且在CubeMX中将 EXTI4 的中断优先级设置比滴答定时器的中断优先级高,比如 2; 将433M的 D0和D1的抢占优先级设为1

  

然后重新生成代码,Keil中此时会自动弹出这个对话框问是否要重载,选择

使用STM32 再实现电动车防盗钥匙扣_第12张图片

此时会将刚刚Cube中做出的修改反映到Keil中,并保留之前在Keil中自己写的代码!

//代码仅展示需要自己写的部分,其他自动生成的部分没有展示!
#define secure_ON 1
#define secure_OFF 0

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //外部中断的处理函数
{
	static int status = secure_OFF; //此处一定要加static,不然每次调用这个函数都要再赋值一遍
	
	//一根中断线上接有多个中断源,判断中断源是否来自PA4
	if((GPIO_Pin == GPIO_PIN_4) && (status == secure_ON)){
	//如果检测到PA4被拉低,且模式为警戒模式,则继电器打开,喇叭响;没有检测到则不响
		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET){
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET); //继电器导通
			HAL_Delay(1000); //延时1秒
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET); //继电器断开
		}else{
			HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET); //继电器断开
		}
	}
	
	if(GPIO_Pin == GPIO_PIN_6){ //D0,对应按键A,按下进入禁戒模式
		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) == GPIO_PIN_SET){
			status = secure_ON;
		}
				
	}
	
	if(GPIO_Pin == GPIO_PIN_7){ //D1,对应按键B,按下退出禁戒模式
		if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) == GPIO_PIN_SET){
			status = secure_OFF;
		}
	}
}


实现效果

可见,在按下A键后,系统进入警戒模式,继电器会对震动有反应,当按下B键后,解除警报,继电器对震动无反应。 

你可能感兴趣的:(stm32,单片机,c语言)