Linux应用层例程1 点亮LED灯

本文介绍Linux系统中控制LED灯的两种方法:通过设备文件及sysfs文件系统。重点讲解了如何利用sysfs文件系统下的brightness、max_brightness和trigger文件来控制LED的状态和触发模式,并给出了具体的编程实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应用层控制外设的两种不同的方式;

Linux 系统下,一切皆文件!

方法一:驱动层设备文件控制外设

        包括字符设备文件和块设备文件,设备文件便是各种硬件设备向应用层提供的一个接口,应用层通过对设备文件的 I/O 操作来操控硬件设备,譬如 LCD 显示屏、串口、按键、摄像头等等,所以设备文件其实是与硬件设备相互对应的。设备文件通常在/dev/目录下,我们也把/dev 目录下的文件称为设备节点。

方法二:sysfs文件系统控制外设

sysfs 是一个基于内存的文件系统,同 devfsproc 文件系统一样,称为虚拟文件系统;它的 作用是将内核信息以文件的方式提供给应用层使用。
sysfs 文件系统的主要功能便是对系统设备进行管理,它可以产生一个包含所有系统硬件层次的视图。
sysfs 文件系统挂载在/sys 目录下,
上图显示的便是 sysfs 文件系统中的目录,包括 blockbusclassdevdevicesfirmwarefskernel、 modules、power 等,每个目录下又有许多文件或子目录,对这些目录的说明如所示:

系统中所有的设备(对象)都会在/sys/devices 体现出来,是 sysfs 文件系统中最重要的目录结构;而 /sys/bus、/sys/class/sys/dev 分别将设备按照挂载的总线类型、功能分类以及设备号的形式将设备组织存放在这些目录中,这些目录下的文件都是链接到了/sys/devices 中。

⚫ 控制 LED

        Linux 内核中为了尽量降低驱动开发者难度以及接口标准化,就出现了设备驱动框架的概念;Linux 针对各种常见的设备进行分类,譬如 LED 类设备、输入类设备、FrameBuffer 类设备、video 类设备、PWM 设备等等,并为每一种类型的设备设计了一套成熟的、标准的、典型的驱动实现的框架,这个就叫做设备驱动框架。设备驱动框架为驱动开发和应用层提供了一套统一的接口规范,譬如对 LED 类设备来说,内核提供了 LED 设备驱动框架,驱动工程师编写 LED 驱动时,使用 LED 驱动框架来开发自己的 LED 驱动程序,这样做的好处就在于,能够对上层应用层提供统一、标准化的接口、同时又降低了驱动开发工程师的难度。
        
        编写 LED 驱动程序并不仅仅只能使用内核设计的 LED 设备驱动框架,不用内核的 LED 驱动框架也是可以开发出 LED 驱动程序的,但如果你这样写,使用这个驱动程序注册的 LED 那就不是标准设备了,因为该驱动程序向应用层提供的接口并不是统一、标准化接口
        (杂项类的由来)除此之外,还有很多硬件外设,尤其是嵌入式系统中所使用到的这些硬件外设,它们可能并不属于 Linux 系统所规划的设备分类当中的任何一种设备类型,譬如在 Linux 系统中,有一种设备类型叫杂散/杂项类设备(misc device),大家可以想一想为啥叫杂散类设备,说明这种设备既不属于这种设备类型、又不属于另一种设备类型,无奈只能把它归为杂项类。
        对于 ALPHA/Mini I.MX6U 开发板出厂系统来说,此 LED 设备使用的是 Linux 内核标准 LED 驱动框架注册而成,在/dev 目录下并没有其对应的设备节点,其实现使用 sysfs 方式控制。进入到/sys/class/leds 目录下
 
这里我们主要关注便是 brightnessmax_brightness 以及 trigger 三个文件,这三个文件都是 LED 设备的属性文件:
brightness翻译过来就是亮度的意思,该属性文件可读可写;所以这个属性文件是用于设置 LED 的亮度等级或者获取当前 LED 的亮度等级,譬如 brightness 等于 0 表示 LED 灭,brightness 为正整数表示 LED 亮,其值越大、LED 越亮;对于 PWM 控制的 LED 来说,这通常是适用的,因为它存在亮度等级的问题,不同的亮度等级对应不同的占空比,自然 LED 的亮度也是不同的;但对于 GPIO 控制(控制 GPIO 输出高低电平)的 LED 来说,通常不存在亮度等级这样的说法,只有 LED 亮(brightness 等于 0)和 LED 灭(brightness 为非 0 值的正整数)两种状态,ALPHA/Mini I.MX6U 开发板上的这颗 LED 就是如此,所以自然就不存在亮度等级一说,只有亮和灭两种亮度等级。
max_brightness该属性文件只能被读取,不能写,用于获取 LED 设备的最大亮度等级。
trigger触发模式,该属性文件可读可写,读表示获取 LED 当前的触发模式,写表示设置 LED 的触发模式。不同的触发模式其触发条件不同,LED 设备会根据不同的触发条件自动控制其亮、灭状态,通过 cat 命令查看该属性文件,可获取 LED 支持的所有触发模式以及 LED 当前被设置的触发模式:

        方括号([heartbeat])括起来的表示当前 LED 对应的触发模式,none 表示无触发,常用的触发模式包括 none(无触发)、mmc0(当对 mmc0 设备发起读写操作的时候 LED 会闪烁)、timerLED 会有规律的一亮一灭,被定时器控制住)、heartbeat(心跳呼吸模式,LED 模仿人的心跳呼吸那样亮灭变化)。(四种触发方式)
echo timer > trigger    //将 LED 触发模式设置为 timer
echo none > trigger    //将 LED 触发模式设置为 none
echo 1 > brightness    //点亮 LED echo 0 > brightness//熄灭 LED

编写 LED 应用程序  

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define LED_TRIGGER "/sys/class/leds/sys-led/trigger"
#define LED_BRIGHTNESS "/sys/class/leds/sys-led/brightness"
#define USAGE() fprintf(stderr, "usage:\n" \
 " %s <on|off>\n" \
 " %s <trigger> <type>\n", argv[0], argv[0])
int main(int argc, char *argv[])
{
 int fd1, fd2;

 /* 校验传参 */
 if (2 > argc) {
 USAGE();
 exit(-1);
 }

 /* 打开文件 */
 fd1 = open(LED_TRIGGER, O_RDWR);
 if (0 > fd1) {
 perror("open error");
 exit(-1);
 }
 fd2 = open(LED_BRIGHTNESS, O_RDWR);
 if (0 > fd2) {
 perror("open error");
 exit(-1);
 }

 /* 根据传参控制 LED */
 if (!strcmp(argv[1], "on")) {
 write(fd1, "none", 4); //先将触发模式设置为 none
 write(fd2, "1", 1); //点亮 LED
 }
 else if (!strcmp(argv[1], "off")) {
 write(fd1, "none", 4); //先将触发模式设置为 none
 write(fd2, "0", 1); //LED 灭
 }
 else if (!strcmp(argv[1], "trigger")) {
 if (3 != argc) {
 USAGE();
 exit(-1);
 }
 if (0 > write(fd1, argv[2], strlen(argv[2])))
 perror("write error");
 }
 else
 USAGE();
 exit(0);
}
        程序中定义了两个宏,LED_TRIGGER LED_BRIGHTNESS,分别对应/sys/class/leds/sys-led/trigger 和 /sys/class/leds/sys-led/brightness 属性文件,宏 USAGE()用于打印程序的使用方法;程序首先会调用 open()函数打开这两个属性文件,之后判断传入参数指向相应的动作,传入"on"表示点亮 LED,先调用 write()"none" 写入到 trigger 属性文件中,也就是设置为无触发,接着再向 brightness 属性文件中写入"1"点亮 LED;传入 "off"表示熄灭 LED,同样也是先调用 write()"none"写入到 trigger 属性文件设置 LED 为无触发,接着再向 brightness 属性文件中写入"0"熄灭 LED;传入"trigger"表示设置 LED 的触发模式,则需要传入第二个参数, 第二个参数表示需要设置的模式。

./testApp on   # 点亮 LED
./testApp off   # 熄灭 LED
./testApp trigger heartbeat   # 将 LED 触发模式设置为 heartbeat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值