一、硬件接线(核心步骤)

1. 元件准备
  • STM32 开发板(如 STM32F103C8T6)
  • 红外发射管模块(或单独的红外发射管 + 限流电阻)
  • 红外接收管模块(或单独的红外接收管)
  • OLED 显示屏(I2C 或 SPI,已适配驱动)
  • 杜邦线、面包板
2. 接线表
模块 引脚 连接到 STM32 的引脚 说明
红外发射管 VCC 3.3V 供电(不可接 5V,会烧毁)
红外发射管 GND GND 接地
红外发射管 信号端 PB5 由 STM32 控制,输出高电平点亮
红外接收管 VCC 3.3V 供电
红外接收管 GND GND 接地
红外接收管 信号端 PB1 输出电平信号到 STM32
OLED 显示屏 按已适配的引脚连接 (如 I2C:SCL 接 PB6,SDA 接 PB7) 参考你的 OLED 的 OLED 驱动接线
3. 关键硬件注意事项
  • 红外发射管和接收管正对对齐,间距 3-5cm(用支架固定,避免晃动);
  • 若接收管信号不稳定,在其信号端与 3.3V 之间接一个 10kΩ 上拉电阻(增强电平稳定性)。

二、STM32CubeIDE 配置(软件初始化)

1. 创建工程
  • 打开 STM32CubeIDE,新建工程,选择你的芯片型号(如 STM32F103C8T6)。
2. 配置系统时钟
  • 在 “Pinout & Configuration” 页面,左侧选择 “RCC”:
    • 勾选 “HSE Clock” 为 “Crystal/Ceramic Resonator”(外部晶振);
  • 切换到 “Clock Configuration”:
    • 配置系统时钟为 72MHz(HSE→PLL→72MHz,具体步骤参考 CubeIDE 自动计算)。
3. 配置 GPIO 引脚
  • PB5(红外发射端)
    • 点击 PB5,选择 “GPIO_Output”;
    • 右侧配置:GPIO mode 为 “Output push-pull”,GPIO pull-up/pull-down 为 “No pull-up and no pull-down”,Maximum output speed 为 “Low”。
  • PB1(红外接收端,外部中断)
    • 点击 PB1,选择 “GPIO_EXTI1”;
    • 右侧配置:GPIO mode 为 “External Interrupt Mode with Rising edge trigger detection detection”(上升沿触发);
    • GPIO pull-up/pull-down 为 “Pull-up”(上拉,确保无信号时为高电平)。
4. 配置 NVIC(中断优先级)
  • 在左侧 “System Core” 中选择 “NVIC”;
  • 勾选 “EXTI line1 interrupt”,优先级默认(Priority 0,Sub Priority 0)。
5. 生成代码
  • 点击菜单栏 “Project”→“Generate Code”,生成初始化代码;
  • 在弹出的对话框中点击 “OK”,CubeIDE 会自动创建工程框架。

三、编写核心代码(用户自定义部分)

1. 添加头文件和全局变量

main.c/* USER CODE BEGIN Includes *//* USER CODE BEGIN PV */中添加:

/* USER CODE BEGIN Includes */
#include "OLED.h"  // 包含OLED驱动头文件
#include <stdio.h>
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
uint32_t count = 0;  // 计数变量,初始为0
/* USER CODE END PV */
2. 实现 GPIO 初始化函数(若未自动生成完整)

main.c/* USER CODE BEGIN 4 */上方添加(若 CubeIDE 未自动生成):

/* USER CODE BEGIN PFP */
void MX_GPIO_Init(void);
/* USER CODE END PFP */

void MX_GPIO_Init(void) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  __HAL_RCC_GPIOB_CLK_ENABLE();  // 使能GPIOB时钟

  // 配置PB5(红外发射端,输出)
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  // 配置PB1(红外接收端,外部中断)
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;  // 上升沿触发
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  // 使能EXTI1中断
  HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI1_IRQn);
}
3. 编写中断回调函数(核心计数逻辑)

main.c/* USER CODE BEGIN 4 */中添加:

/* USER CODE BEGIN 4 */
// 外部中断回调函数:PB1触发时执行
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
  if (GPIO_Pin == GPIO_PIN_1) {  // 确认是PB1触发
    HAL_Delay(10);  // 消抖(避免信号抖动误触发)
    // 遮挡时,接收端输出高电平(上升沿触发后确认)
    if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_SET) {
      count++;  // 计数+1
      if (count > 9999) {  // 超过9999清零
        count = 0;
      }
    }
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);  // 清除中断标志,避免重复触发
  }
}
/* USER CODE END 4 */
4. 编写主函数(初始化与显示)

main函数中添加初始化和显示逻辑:

int main(void) {
  /* USER CODE BEGIN 1 */
  char display_buf[20];  // 显示缓冲区
  /* USER CODE END 1 */

  HAL_Init();
  SystemClock_Config();  // 配置系统时钟
  MX_GPIO_Init();        // 初始化GPIO

  /* USER CODE BEGIN 2 */
  OLED_Init();           // 初始化OLED
  OLED_Clear();          // 清屏
  // 开启红外发射(PB5输出高电平,点亮发射管)
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
  /* USER CODE END 2 */

  /* 主循环 */
  while (1) {
    // 格式化计数显示(如"Count: 123")
    sprintf(display_buf, "Count: %d", (int)count);
    // 在OLED的(1,1)位置显示(坐标根据OLED驱动调整)
    OLED_ShowString(1, 1, display_buf);
    HAL_Delay(100);  // 100ms刷新一次
    /* USER CODE END WHILE */
  }
}

四、下载与测试

  1. 将 STM32 开发板通过 USB 连接到电脑;
  2. 在 CubeIDE 中点击 “Build”(锤子图标)编译代码,确保无错误;
  3. 点击 “Run”(▶️图标)下载代码到开发板;
  4. 测试:
    • 无遮挡时,OLED 显示 “Count: 0”;
    • 用卡片遮挡红外发射管和接收管之间的光路,每次遮挡,计数 + 1,OLED 同步更新。

关键成功要点回顾

  1. 硬件对齐:发射管和接收管必须正对,信号稳定是计数的前提;
  2. 中断配置:PB1 必须设为 “上升沿触发”+“上拉电阻”,匹配遮挡时 “低→高” 的电平变化;
  3. 消抖处理:中断回调函数中的HAL_Delay(10)不可少,避免信号抖动误触发。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐