STM32CubeMX实现中断方式使3144E霍尔传感器翻转LED灯(三)
·
一、功能实现
我手上有3144E霍尔传感器,两个上拉的LED灯,STM32F407ZET6。LED分别连接在PF9,PF10上,霍尔传感器输出脚连接在PC7上,霍尔传感器的输出引脚外接无磁场时输出高电平,有磁场时输出低电平,使用中断的方式通过霍尔传感器控制LED亮灭
霍尔传感器3144E特性
根据资料,3144E是单极开关型霍尔传感器:
-
无磁场时:输出高电平(需要外部上拉电阻)
-
有磁场时(S极靠近):输出低电平
-
输出类型:集电极开路(NPN),必须接上拉电阻
-
工作电压:4.5V-24V(检查你的供电是否满足)
连接情况
-
霍尔传感器OUT → PC7(已接外部上拉电阻)
-
LED1 → PF9(带上拉)
-
LED2 → PF10(带上拉)
-
触发条件:下降沿(高→低)
二、具体配置
1. 引脚配置
在Pinout视图中:
-
PC7:设置为
GPIO_EXTI7(外部中断) -
PF9:设置为
GPIO_Output -
PF10:设置为
GPIO_Output

2. GPIO详细设置
PC7(霍尔传感器):
text
GPIO mode: External Interrupt Mode with Falling edge trigger detection ← 下降沿触发(有磁场时低电平) GPIO Pull-up/Pull-down: No pull-up and no pull-down ← 因为外部已有上拉电阻 Maximum output speed: N/A User Label: HALL_SENSOR

PF9/PF10(LED):
text
GPIO mode: Output Push Pull GPIO Pull-up/Pull-down: Pull-up ← 使能内部上拉(配合你的LED连接方式) Maximum output speed: Low User Label: LED1 / LED2
3. NVIC设置
在NVIC设置中,勾选:
text
☑ EXTI line[9:5] interrupts
并设置优先级(如抢占优先级2,子优先级0)
重要说明:PC7属于EXTI7,对应中断线组 EXTI9_5_IRQn,因此必须使能该组中断。

三、HAL库代码实现
1. 在 main.c 的用户代码区添加变量
c
/* USER CODE BEGIN PV */ volatile uint8_t hall_triggered = 0; // 霍尔触发标志(用于主循环处理) /* USER CODE END PV */
2. 在主函数中初始化LED状态
c
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
// 初始化LED状态:熄灭(带上拉,高电平熄灭)
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
/* USER CODE END 2 */
while (1)
{
/* USER CODE BEGIN 3 */
if(hall_triggered)
{
hall_triggered = 0; // 清除标志
// 再次确认引脚状态(可选,提高可靠性)
if(HAL_GPIO_ReadPin(HALL_SENSOR_GPIO_Port, HALL_SENSOR_Pin) == GPIO_PIN_RESET)
{
// 翻转两个LED的状态
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
}
}
}
/* USER CODE END 3 */
}
3. 中断回调函数
在 main.c 末尾的 /* USER CODE BEGIN 4 */ 区域添加:
c
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
// 判断是否是PC7触发的中断
if(GPIO_Pin == HALL_SENSOR_Pin)
{
// 简单的消抖处理(使用时间戳方式避免HAL_Delay问题)
static uint32_t last_interrupt_time = 0;
uint32_t current_time = HAL_GetTick();
// 50ms消抖,避免重复触发
if((current_time - last_interrupt_time) > 50)
{
last_interrupt_time = current_time;
// 设置标志位,在主循环中处理LED翻转
hall_triggered = 1;
// 注意:不直接在中断中操作LED,而是通过标志位让主循环处理
// 这样可以减少中断处理时间,避免影响系统稳定性[citation:3]
}
}
}
/* USER CODE END 4 */更多推荐
所有评论(0)