目录
一、震动传感器介绍及实战
二、编程代码实现
1、gpio.c---------初始化GPIO口引脚函数
2、编写中断服务函数
3、用外部中断共用入口函数,来调用外部中断处理回调函数
4、编写外部中断处理回调函数(在这里编写项目设计的逻辑)
5、把上述的外部中断处理回调函数,放入main主函数里
6、结果演示
三、继电器介绍及实战
单片机供电VCC GND接单片机
产品不震动,输出高电平、模块上的DO口
产品震动,输出低电平,绿色指示灯亮
AO口不用
5V:代表正极
GND:代表负极
DO口:do是一种模拟信号或者数字信号接口
需求:当振动传感器接收到振动信号时,使用中断方式点亮LED1。
#include "gpio.h"
void MX_GPIO_Init(void) //初始化GPIO口引脚函数
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; //初始化设置GPIO的结构体
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOD时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET); //GPIO引脚输出1或者0的函数
/*Configure GPIO pin : PA4 */
GPIO_InitStruct.Pin = GPIO_PIN_4; //配置GPIO口引脚:PA4
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; //下降沿触发检测的外部中断模式
GPIO_InitStruct.Pull = GPIO_NOPULL; //内部电阻既不拉高也不拉低
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); //根据上述内容,初始化GPIOA引脚
/*Configure GPIO pin : PB8 */
GPIO_InitStruct.Pin = GPIO_PIN_8; //配置GPIO口引脚:PB8
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出;推挽输出可以真正能真正的输出高电平
GPIO_InitStruct.Pull = GPIO_NOPULL; //内部电阻既不拉高也不拉低
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; //GPIO引脚输出的频率
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); //根据上述内容,初始化GPIOB引脚
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0); //配置EXTI4_IRQn中断,抢先优先级2,响应优先级0
HAL_NVIC_EnableIRQ(EXTI4_IRQn); //使能中断通道EXTI4_IRQn
}
#include "main.h"
#include "stm32f1xx_it.h"
void EXTI4_IRQHandler(void) //中断服务函数
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); //调用中断处理公用函数,根据输入的参数,来判断到底输入的是哪个按键
}
外部中断共用入口函数:void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
#include "stm32f1xx_hal.h"
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u) //确保是否产生了中断
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); //清除中断标志位
HAL_GPIO_EXTI_Callback(GPIO_Pin); //调用外部中断处理回调函数
}
}
void SystemClock_Config(void); //因为这个函数在main函数中,如果想要使用这个函数,需要提前声明
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //外部中断处理回调函数,如果检测到EXTI中断请求,则进入此函数
{
//一根中断线上接有多个中断源,判断中断源是否来自PA4
if(GPIO_Pin == GPIO_PIN_4)
{
//如果检测到PA4被拉低
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4) == GPIO_PIN_RESET) //读取GPIOA4引脚输入是否为0
{
//则点亮LED1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET); //指定GPIOB8引脚输出0
HAL_Delay(3000); //延时3000ms
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //指定GPIOB8引脚输出1
}
}else{
//如果未检测到PA4,则关闭LED1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //指定GPIOB8引脚输出1
}
}
#include "main.h"
#include "gpio.h"
void SystemClock_Config(void); //因为这个函数在main函数中,如果想要使用这个函数,需要提前声明
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //外部中断处理回调函数,如果检测到EXTI中断请求,则进入此函数
{
//一根中断线上接有多个中断源,判断中断源是否来自PA4
if(GPIO_Pin == GPIO_PIN_4)
{
//如果检测到PA4被拉低
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4) == GPIO_PIN_RESET) //读取GPIOA4引脚输入是否为0
{
//则点亮LED1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET); //指定GPIOB8引脚输出0
HAL_Delay(3000); //延时3000ms
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //指定GPIOB8引脚输出1
}
}else{
//如果未检测到PA4,则关闭LED1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //指定GPIOB8引脚输出1
}
}
int main(void)
{
HAL_Init(); //初始化HAL库函数
SystemClock_Config(); //初始化系统时钟函数
HAL_NVIC_SetPriority(SysTick_IRQn,0,0); //提高滴答定时器的中断优先级(提升至0)
MX_GPIO_Init(); //初始化GPIO引脚
}
void SystemClock_Config(void) //配置系统时钟函数
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
如果直接在中断服务函数里调用 HAL_Delay 函数,则会造成系统卡死。
原因:程序初始化时默认把滴答定时器的中断优先级设为最低,其它中断源很容易打断它导致卡
死。
解决:在 main 函数里使用以下函数提高滴答定时器的中断优先级(提升至0):
HAL_NVIC_SetPriority(SysTick_IRQn,0,0); //提高滴答定时器的中断优先级(提升至0)
并且将 EXTI4 的中断优先级设置比滴答定时器的中断优先级低,比如 2 。
简单的说继电器就是小电流、小电压控制大电流、大电压。这就是常见的继电器,这个是一路的。
继电器的IN口:接到单片机的IO口
IN口连接的作用是:IN连接上,单片机会给IN一个低电平信号,这个低电平信号,会让继电器两端的COM口和NO口连接起来上电
接线方式:
VCC:接3.3V(不可以接5V,接5V会工作异常)
GND:接GND
IN:接任何一个通用GPIO口即可
把继电器接到STM32开发板上,可以看到,一碰震动传感器,继电器上的绿灯会亮,而且STM32开发板上的LED小灯也会跟着亮