控制LED设备的两种方式
- 通过LED在/dev/下的设备节点控制
- sysfs 文件系统操作LED设备的属性文件控制 (LED设备驱动必须使用LED子系统实现)
sysfs 文件系统
sysfs 是一个基于内存的文件系统,同 devfs、proc 文件系统一样,称为虚拟文件系统,它的作用是将内核信息以文件的方式提供给应用层使用
sysfs 文件系统的主要功能便是对系统设备进行管理,它可以产生一个包含所有系统硬件层次的视图
…
…
简单概括来说就是内核通过sysfs文件系统将内核对象(例如驱动)的属性通过文件的方式映射到用户空间,用户可以通过这些文件直接操作内核对象的属性进而控制设备。
sysfs文件系统挂载在/sys
目录下,其目录内容:
c
查看ubuntu主机的led设备:
ls /sys/class/leds/
input1::capslock input1::numlock input1::scrolllock
查看开发板存在哪些led设备:
ls /sys/class/leds/
blue cpu green mmc0:: mmc1:: red
/sys/class/leds下的目录 | 对应的LED灯设备 |
---|---|
input2::capslock | 键盘大写锁定指示灯 |
input2::numlock | 键盘数字键盘指示灯 |
input2::scrolllock | 键盘ScrollLock指示灯 |
cpu | 开发板的心跳指示灯 |
red | 开发板RGB灯红色灯 |
green | 开发板RGB灯绿色灯 |
blue | 开发板RGB灯蓝色灯 |
mmc0:: | SD卡指示灯 |
查看led设备的属性:
ls /sys/class/leds/red
brightness device max_brightness power subsystem trigger uevent
属性 | 说明 |
---|---|
max_brightness | 最大亮度值,文件只可读 |
brightness | 亮度值,值范围为[0-max_brightness],不支持亮度等级则0为灭,大于0为亮,文件可读可写 |
trigger | 触发方式 |
常见触发方式:
触发方式 | 说明 |
---|---|
none | 无触发方式 |
disk-activity | 硬盘活动 |
nand-disk | nand flash活动 |
mtd | mtd设备活动 |
timer | 定时器 |
heartbeat | 系统心跳 |
应用程序编写
程序编写即是读写上述属性文件。
对led属性操作
led.h :
#ifndef __LED_H__
#define __LED_H__
#include "stdint.h"
enum {
LED_TRIG_NONE = 0x00,
LED_TRIG_DISK_ACTIVE,
LED_TRIG_NAND_DISK,
LED_TRIG_MTD,
LED_TRIG_TIMER,
LED_TRIG_HEARTBEAT,
};
typedef uint8_t led_trig_t;
int led_set_trigger(char *ledname, led_trig_t trig);
int led_set_brightness(char *ledname, int brightness);
int led_get_max_brightness(char *ledname);
#endif /* __LED_H__ */
led.c:
#include "led.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#ifndef ARR_COUNTOF
#define ARR_COUNTOF(a) (sizeof(a) / sizeof(a[0]))
#endif
/* 常见触发方式 */
#define TRIGGER_NONE "none" /* 无触发方式 */
#define TRIGGER_DISK_ACTIVITY "disk-activity" /* 硬盘活动 */
#define TRIGGER_NAND_DISK "nand-disk" /* nand flash活动 */
#define TRIGGER_MTD "mtd" /* mtd设备活动 */
#define TRIGGER_TIMER "timer" /* 定时器 */
#define TRIGGER_HEARTBEAT "heartbeat" /* 系统心跳 */
int led_set_trigger(char *ledname, led_trig_t trig)
{
int fd;
char path[256] = {0};
sprintf(path, "/sys/class/leds/%s/trigger", ledname);
fd = open(path, O_RDWR);
if (fd < 0) return -1;
char trigger_style[6][30] = {{TRIGGER_NONE}, {TRIGGER_DISK_ACTIVITY}, {TRIGGER_NAND_DISK},
{TRIGGER_MTD}, {TRIGGER_TIMER}, {TRIGGER_HEARTBEAT}};
led_trig_t trigger_index[6] = {LED_TRIG_NONE, LED_TRIG_DISK_ACTIVE, LED_TRIG_NAND_DISK,
LED_TRIG_MTD, LED_TRIG_TIMER, LED_TRIG_HEARTBEAT};
char trigger[20] = {0};
for (int i = 0; i < ARR_COUNTOF(trigger_index); i++)
{
if (trig == trigger_index[i])
{
sprintf(trigger, "%s", trigger_style[i]);
break;
}
}
int len = strlen(trigger);
if (len != write(fd, trigger, len)) return -1;
return 0;
}
int led_set_brightness(char *ledname, int brightness)
{
int fd;
char path[256] = {0};
sprintf(path, "/sys/class/leds/%s/brightness", ledname);
fd = open(path, O_RDWR);
if (fd < 0) return -1;
char brights[10] = {0};
sprintf(brights, "%d", brightness);
int len = strlen(brights);
if (len != write(fd, brights, len)) return -1;
return 0;
}
int led_get_max_brightness(char *ledname)
{
int fd;
int max_brightness;
char brights[20] = {0};
char path[256] = {0};
sprintf(path, "/sys/class/leds/%s/max_brightness", ledname);
fd = open(path, O_RDONLY);
if (fd < 0) return -1;
read(fd, brights, sizeof(brights));
max_brightness = atoi(brights); /* 将字符串数字转换成整数 */
return max_brightness;
}
控制led: led_sample.c
#include "stdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <stdint.h>
#include <sys/select.h>
#include "led.h"
#define RED_LED "red"
#define BLUE_LED "blue"
#define GREEN_LED "green"
void sleep_ms(unsigned int ms)
{
struct timeval delay;
delay.tv_sec = 0;
delay.tv_usec = ms * 1000;
select(0, NULL, NULL, NULL, &delay);
}
int main(int argc, char **argv)
{
led_set_trigger(RED_LED, LED_TRIG_NONE);
int max_brightness = led_get_max_brightness(RED_LED);
printf("Max brightness: %d\r\n", max_brightness);
int cnt = 0;
int brightness = 0;
while (1)
{
led_set_brightness(RED_LED, 0);
sleep_ms(500);
led_set_brightness(RED_LED, 255);
sleep_ms(500);
if (++cnt >= 40)
break;
}
led_set_brightness(RED_LED, 0);
return 0;
}