Skip to content

LV075-点亮LED实例

一、代码实例

1. 代码编写

这一部分就是通过open、close、read、write、ioctl等函数来操作LED驱动,进而控制LED灯。代码可以看这里:linux-dev-org/imx6ull-app-demo

c
#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 的触发模式,则需要传入第二个参数,第二个参数表示需要设置的模式。

2. 编译

由于我们是在 ALPHA I.MX6U开发板上运行程序,所以需要 I.MX6U 平台对应的交叉编译工具来编译测试代码,这样编译得到的可执行文件才能在开发板上运行。 这里使用的交叉编译工具是:

shell
sumu@sumu-virtual-machine:~/5imx6ull/imx6ull-app-demo$ arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Linaro GCC 4.9-2017.01) 4.9.4
Copyright © 2015 Free Software Foundation, Inc.
本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;
包括没有适销性和某一专用目的下的适用性担保。

然后编写Makefile文件,其实这里只有一个文件,不需要Makefile也行。

makefile
CROSS_COMPILE 	?= arm-linux-gnueabihf-
TARGET		  	?= app_demo
NFS_APP_DEMO    ?= ~/4nfs/app

OBJ_DIR         ?= ./
CC 				:= $(CROSS_COMPILE)gcc
LD				:= $(CROSS_COMPILE)ld
OBJCOPY 		:= $(CROSS_COMPILE)objcopy
OBJDUMP 		:= $(CROSS_COMPILE)objdump

CFLAGS 		    := -Wall

INCDIRS 		:= ./	   			   
SRCDIRS			:= ./			   
				   
INCLUDE			:= $(patsubst %, -I %, $(INCDIRS))
CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

SFILENDIR		:= $(notdir  $(SFILES))
CFILENDIR		:= $(notdir  $(CFILES))

COBJS			:= $(patsubst %, $(OBJ_DIR)%, $(CFILENDIR:.c=.o))
OBJS			:= $(COBJS)

VPATH			:= $(SRCDIRS)
.PHONY: clean
	
$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) $(INCLUDE) $(OBJS) -o $@

$(COBJS) : $(OBJ_DIR)%.o : %.c
	$(CC) $(CFLAGS) -c  $(INCLUDE) $< -o $@
	
clean:
	rm -rf $(TARGET) $(COBJS)

install:
	@cp -vf $(TARGET) $(NFS_APP_DEMO)

uninstall:
	@rm -rvf $(NFS_APP_DEMO)/$(TARGET)

我们执行make命令就会完成编译,生成可执行文件:

image-20240903074504297

我们使用file命令查看文件格式可以知道这是一个32位ARM架构下的可执行文件。

二、开发板测试

启动开发板进入 Linux 系统,将上小节编译得到的可执行文件 app_demo 拷贝到开发板根文件系统中,我是前面设置了NFS开发环境,直接挂在了ubuntu中的目录:

image-20240903074645817

可以执行以下命令来进行测试:

shell
./testApp on     # 点亮 LED
./testApp off    # 熄灭 LED
./testApp trigger heartbeat # 将 LED 触发模式设置为 heartbeat