当前位置:首页>Linux>嵌入式Linux通用版:GPIO 控制补光灯(含硬件环境排查)

嵌入式Linux通用版:GPIO 控制补光灯(含硬件环境排查)

  • 2026-10-11 07:28:08
嵌入式Linux通用版:GPIO 控制补光灯(含硬件环境排查)
Hello,大家好,我是程序媛MM。

本文约1800字,今天调试外设功能, 完成对白光灯/红外灯/IR-CUT的控制,本文整理了一套通过复用GPIO控制外设功能的通用方法,可适用日常普通的外设功能调试。

关注公众号, 即可获得与Linux相关的电子书籍以及常用开发工具,文末有文档清单。

本文主要分析外设(如白光灯、红外灯)通过复用GPIO实现相关功能的通用原理、通用流程、通用命令、通用排查,任何用 GPIO 控制补光灯/白光灯的设备都能直接用。以爱芯AX615为例分析。


一 白光灯为什么能用 GPIO 控制?

1. 核心原理

白光灯本质是 LED 补光灯,由 GPIO 输出高低电平控制开关管(MOS/三极管)导通/截止,实现亮灭。

  • GPIO 输出高电平 → 灯亮
  • GPIO 输出低电平 → 灯灭

2. 复用 GPIO 控制的通用逻辑

很多摄像头/IPC 会把红外灯、白光灯、喇叭、ICR共用同一套 GPIO 驱动框架,只换引脚编号即可复用:

  1. 导出 GPIO(export)
  2. 配置方向为输出(out)
  3. 写电平控制亮灭
  4. 取消导出(unexport)

二 通用实现:应用层 GPIO 控制白光灯标准流程

首先:确认白光灯的引脚复用关系

从硬件工程师整理的AX615*_PIN_OUT.xlsx 引脚功能复用关系表中可查到白光灯/红外灯的引脚复用关系和对应寄存器地址,如下图所示:

可在硬件原理图上再次进行确认:

最终我们可知道红外灯引脚是GPIO1_A23,白光灯引脚是GPIO1_A24。

axera系列uboot/kernel/riscv等都统一使用pinmux.h里面定义的引脚配置: 将白光灯/红外灯对应寄存器的功能配置不对的根据上面确认的信息进行修改,修改后如下所示:

查询SDK文档中的《AX 外围设备驱动开发指南》可知GPIO引脚值转换后的GPIO控制值为: 

GPIO1_23: 32x1+23 = 55 

GPIO1_24: 32x1+24 = 56

下面的步骤均以白光灯(gpio56)为例:

步骤 1:导出 GPIO(把引脚开放给用户态)

echo 56 > /sys/class/gpio/export

56 是白光灯 GPIO 编号(设备是多少就改多少)

步骤 2:配置为输出模式

echo out > /sys/class/gpio/gpio56/direction

步骤 3:控制亮灭

# 开灯echo 1 > /sys/class/gpio/gpio56/value# 关灯echo 0 > /sys/class/gpio/gpio56/value

步骤4:用完释放 GPIO

echo 56 > /sys/class/gpio/unexport

三 通用代码实现

#include<stdio.h>#include<fcntl.h>#include<unistd.h>#include<string.h>#define GPIO_NUM 56  // 白光灯GPIO// 导出GPIOintgpio_export(int gpio){char buf[64];int fd = open("/sys/class/gpio/export", O_WRONLY);if (fd < 0) return-1;sprintf(buf, "%d", gpio);    write(fd, buf, strlen(buf));    close(fd);return0;}// 设置方向 out/inintgpio_set_dir(int gpio, constchar *dir){char path[64];int fd;sprintf(path, "/sys/class/gpio/gpio%d/direction", gpio);    fd = open(path, O_WRONLY);    write(fd, dir, strlen(dir));    close(fd);return0;}// 写值 1/0intgpio_set_value(int gpio, int val){char path[64];int fd;sprintf(path, "/sys/class/gpio/gpio%d/value", gpio);    fd = open(path, O_WRONLY);    dprintf(fd, "%d", val);    close(fd);return0;}// 使用示例voidwhite_light_ctrl(int on){    gpio_export(GPIO_NUM);    gpio_set_dir(GPIO_NUM, "out");    gpio_set_value(GPIO_NUM, on ? 1 : 0);}

四 重点新增:白光灯不亮?全套硬件环境排查方法

从软件 → 硬件 → 驱动一步步查,绝大部分问题都能定位。

1. 先查 GPIO 是否被占用

ls /sys/class/gpio/
  • 看不到 gpio56 → 没导出
  • 已存在 → 被其他进程占用,先 unexport

2. 检查方向是否正确

cat /sys/class/gpio/gpio56/direction

必须是:out

3. 检查电平是否能写入

# 写1echo 1 > /sys/class/gpio/gpio56/valuecat /sys/class/gpio/gpio56/value
  • 输出 1 → 软件正常
  • 一直是 0 → GPIO 被锁/被驱动占用

4. 检查硬件供电

  • 白光灯供电是否正常(12V/5V)
  • 灯珠是否烧坏
  • 开关管(MOS 管)是否击穿

5. 检查 GPIO 硬件引脚对应关系

  • 软件 GPIO 编号 ≠ 芯片引脚号
  • 必须对照硬件原理图确认:
    • GPIO56 = GPIO1_A24(我这台设备)
    • 确认该引脚确实接到白光灯驱动电路

6. 检查是否被内核驱动占用

dmesg | grep gpio

看到 gpio56 被其他设备注册 → 冲突,需修改设备树或关闭对应驱动。

7. 最简验证:直接用命令控制

echo 56 > /sys/class/gpio/exportecho out > /sys/class/gpio/gpio56/directionecho 1 > /sys/class/gpio/gpio56/value
  • 灯不亮 → 硬件问题
  • 灯亮 → 上层应用逻辑问题

五 复用 GPIO 控制多外设的通用设计思路

红外灯、白光灯、喇叭、警灯,都可以用同一套 GPIO 函数,只换编号:

// 统一接口typedefstruct {int gpio;int active_level;  // 高/低有效} GPIO_DEV;GPIO_DEV white_light = {56, 1};GPIO_DEV ir_light    = {55, 1};GPIO_DEV speaker     = {27, 1};// 统一控制voiddev_on(GPIO_DEV dev){    gpio_export(dev.gpio);    gpio_set_dir(dev.gpio, "out");    gpio_set_value(dev.gpio, dev.active_level);}

好处:

  • 一套代码控制所有外设
  • 新增外设只加配置,不改逻辑
  • 方便跨平台、跨设备移植

六 总结

  1. 原理:GPIO 电平控制开关管 → 白光灯亮灭
  2. 通用流程:export → dir out → write value
  3. 排查顺序:导出 → 方向 → 电平 → 硬件 → 占用
  4. 复用思路:统一 GPIO 接口 + 外设配置表

往期文章(欢迎订阅技术分享栏目全部文章):


【从零开始撸内核驱动源码】:以ttyserial(串口驱动)为例,串联字符设备驱动基础知识点的学习计划
Linux内核源码顶层 Makefile分析并单独编译调试内核自带的驱动
【从零开始撸内核驱动源码】:ttynull驱动
Linux内核驱动安装失败问题调试及解决方法
Linux内核驱动源码走读之编译内核及外部驱动实操指南

“谢谢你看到这里”

这里是女程序员的笔记本

 15年+嵌入式软件工程师兼二胎宝妈

分享读书心得、工作经验,自我成长和生活方式。

希望我的文字能对你有所帮助

最新文章

随机文章