立创泰山派linux------(led流水灯)
1、触发器使得LED闪烁
有些开发板的 LED 会硬件层面被配置成呼吸灯或心跳灯,通过 PWM 或定时器直接驱动 GPIO,不需要任何用户程序。即使你kill掉所有进程,它还是会闪。
你可以查看 LED 的触发器状态:
bash
cat /sys/class/leds/rgb-led-r/trigger cat /sys/class/leds/rgb-led-g/trigger cat /sys/class/leds/rgb-led-b/trigger
如果输出里有heartbeat或timer,说明 LED 被内核的 LED 触发器控制着,所以一直在闪烁。
root@RK356X:/# cat /sys/class/leds/rgb-led-r/trigger none rfkill-any rfkill-none kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock mmc2 mmc0 [timer] rfkill0 mmc1 rfkill1 rfkill2
2、内核已经注册好了 LED 设备,可以直接操作。
当你执行ls /sys/class/leds/看到下面这行时:
rgb-led-b rgb-led-g rgb-led-r
这就代表内核已经成功注册了 LED 设备。它干了三件事:
识别了硬件:内核知道 GPIO 40、41、42 这三个引脚上接着 LED。
创建了标准接口:在
/sys/class/leds/下为你创建了三个“控制面板”(目录),里面包含brightness和trigger等文件。提供了操作方法:你往这些文件里写
1或0,内核驱动就会自动去翻转 GPIO 引脚的电平,点亮或熄灭 LED。
你完全不需要关心 GPIO 编号是怎么计算的(比如 GPIO1_B0 对应 40),也不需要用echo 40 > export手动去申请这个引脚——因为内核已经帮你把这一切都做好了。
🆚 对比一下“没注册”是什么感觉
如果你把 LED 接在一个内核不认识的 GPIO 引脚上(比如某个空闲的引脚),那就没有注册这回事。你需要做的流程是:
用
echo 100 > /sys/class/gpio/export手动申请。用
echo out > direction设置方向。再用
echo 1 > value控制电平。
而现在因为内核“注册”了它,前两步都给你省了,直接跳到第三步,甚至能用none和timer这种高级模式。
分别实现点亮和关闭led的命令:
可以看到led返回值:
3、实现led交通闪烁:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define LED_RED "/sys/class/leds/rgb-led-r" #define LED_GREEN "/sys/class/leds/rgb-led-g" #define LED_BLUE "/sys/class/leds/rgb-led-b" void disable_trigger(const char *led_path); void set_led(const char *led_path, int on); void write_file(const char *path, const char *value); int main(void) { int i; const char *leds[] = {LED_RED, LED_GREEN, LED_BLUE}; const char *colors[] = {"红色", "绿色", "蓝色"}; printf("RGB LED 流水灯启动!按 Ctrl+C 停止。\n"); // 先禁用所有 LED 的触发器,停止闪烁 for (i = 0; i < 3; i++) { disable_trigger(leds[i]); set_led(leds[i], 0); // 先全部熄灭 } while (1) { for (i = 0; i < 3; i++) { // 点亮当前 LED set_led(leds[i], 1); printf("点亮 %s LED\n", colors[i]); // 熄灭其他两个 LED int j; for (j = 0; j < 3; j++) { if (j != i) { set_led(leds[j], 0); } } usleep(500000); // 延时 500ms } } return 0; } // 设置 LED 触发器为 none(停止自动闪烁) void disable_trigger(const char *led_path) { char path[256]; snprintf(path, sizeof(path), "%s/trigger", led_path); write_file(path, "none"); } // 设置 LED 亮灭 void set_led(const char *led_path, int on) { char path[256]; snprintf(path, sizeof(path), "%s/brightness", led_path); write_file(path, on ? "1" : "0"); } // 写入文件函数 void write_file(const char *path, const char *value) { FILE *fp = fopen(path, "w"); if (fp == NULL) { perror("fopen"); return; } fprintf(fp, "%s", value); fclose(fp); }