一、功能实现

我手上有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 */
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐