Linux应用-LED

Linux应用-LED

基础

在Linux下控制LED硬件。涉及到了SYSFS文件系统 Linux中的SYSFS文件系统

  • 设备树文件

    可知,LED被注册为了sys-led的label

    c 复制代码
    	leds {
    		compatible = "gpio-leds";
    		pinctrl-names = "default";
    		pinctrl-0 = <&pinctrl_gpio_leds
    			     &pinctrl_beep>;
    
    		led1{
    			label = "sys-led";
    			gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
    			linux,default-trigger = "heartbeat";
    			default-state = "on";
    		};
    
    		beep{
    			label = "beep";
    			gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
    			default-state = "off";
    		};
    	};

在正点原子的I.MX6ULL的出厂系统中,将LED设备以系统内核自带的驱动进行加载,故在dev目录下没有对应的文件可以访问。要操控可以通过设置到/sys/class/leds 目录下的文件来进行操控

bash 复制代码
root@ATK-IMX6U:/sys/class/leds/sys-led# ls
brightness  device  max_brightness  power  subsystem  trigger  uevent

重点关注以下三个文件

  • brightness: 可读可写的属性,用于设置当前的亮度。

  • max_brightness:只读文件,用于获取当前设备的最大亮度

  • trigger: 可读可写,用于设置触发模式。支持的属性有

    bash 复制代码
    root@ATK-IMX6U:/sys/class/leds/sys-led# cat ./trigger
    none rc-feedback nand-disk mmc0 mmc1 timer oneshot [heartbeat] backlight gpio


因此,可以直接执行指令来修改led的sysfs文件,例如

bash 复制代码
root@ATK-IMX6U:/sys/class/leds/sys-led# echo none > ./trigger
root@ATK-IMX6U:/sys/class/leds/sys-led# echo 1  > ./brightness
root@ATK-IMX6U:/sys/class/leds/sys-led# cat ./max_brightness
255
root@ATK-IMX6U:/sys/class/leds/sys-led# echo 0  > ./brightness
root@ATK-IMX6U:/sys/class/leds/sys-led#

程序控制

  • 代码

    c 复制代码
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <string.h>
    #include <stdbool.h>
    
    #define LED_Trigger "/sys/class/leds/sys-led/trigger"
    #define LED_Brightness "/sys/class/leds/sys-led/brightness"
    
    
    
    int main(int argc, char *argv[]) {
    
        int fd_trigger = -1, fd_brightness = -1;
        int ret = -1;
        //检查参数数量
        if (argc != 3) {
            printf("错误用法:需要3个参数,但提供了%d个\n", argc);
            exit(-1);
        }
        bool isSetBrightness = false;
        //检查参数
        if(strcmp(argv[1], "none")  == 0){
            isSetBrightness = true;
        }
    
    
    
        //打开文件
        fd_trigger = open(LED_Trigger, O_RDWR);
        if(fd_trigger < 0) {
            perror("打开LED触发文件失败");
            exit(-1);
        }
    
        fd_brightness = open(LED_Brightness, O_RDWR);
        if(fd_brightness < 0) {
            perror("打开LED亮度文件失败");
            goto out1;
        }
    
    
        //设置LED触发模式
        ret = write(fd_trigger, argv[1], strlen(argv[1]));
    
        if(ret < 0) {
            perror("写入LED触发模式失败");
            goto out2;
        }
    
        if(ret != strlen(argv[1])) {
            fprintf(stderr, "Warning: Expected to write %zu bytes, but wrote %d bytes\n",
                    strlen(argv[1]), ret);
        }
    
    
        if(isSetBrightness){
            if(strcmp(argv[2], "1") == 0) {
                //设置LED亮度为1
                ret = write(fd_brightness, "1", strlen("1"));
            } else if(strcmp(argv[2], "0") == 0) {
                //设置LED亮度为0
                ret = write(fd_brightness, "0", strlen("0"));
            } else {
                printf("无效的亮度值。请使用'1'(开启)或'0'(关闭)。\n");
                goto out2;
            }
            if(ret < 0) {
                perror("写入LED亮度失败");
                goto out2;
            }
            if(ret != strlen(argv[2])) {
                fprintf(stderr, "警告:预期写入%zu字节,但实际写入%d字节\n",
                        strlen(argv[2]), ret);
            }
        }
    
        printf("LED配置更新成功。\n");
    
        out2:
            close(fd_brightness);
        out1:
            close(fd_trigger);
    
        return 0;
    }
  • CMakeList.txt

    cmake 复制代码
    cmake_minimum_required(VERSION 3.10)
    project(led_control)
    
    # 设置C标准
    set(CMAKE_C_STANDARD 99)
    set(CMAKE_C_STANDARD_REQUIRED ON)
    
    # 交叉编译配置
    # ARM Cortex-A7 (armv7l) 架构
    set(CMAKE_SYSTEM_NAME Linux)
    set(CMAKE_SYSTEM_PROCESSOR arm)
    
    # 交叉编译器配置
    # 注意:在实际编译时,建议通过以下方式指定编译器:
    # cmake -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ ..
    # 或者设置环境变量:export CC=arm-linux-gnueabihf-gcc; export CXX=arm-linux-gnueabihf-g++
    
    # 如果没有通过命令行指定编译器,则尝试默认路径
    if(NOT DEFINED CMAKE_C_COMPILER)
        # 常见的ARM交叉编译器路径,可根据实际环境调整
        find_program(CMAKE_C_COMPILER
            NAMES arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc-9 arm-linux-gnueabihf-gcc-10
            PATHS /usr/bin /usr/local/bin /opt/toolchains
        )
    endif()
    
    if(NOT DEFINED CMAKE_CXX_COMPILER)
        find_program(CMAKE_CXX_COMPILER
            NAMES arm-linux-gnueabihf-g++ arm-linux-gnueabihf-g++-9 arm-linux-gnueabihf-g++-10
            PATHS /usr/bin /usr/local/bin /opt/toolchains
        )
    endif()
    
    # 设置根文件系统路径(用于查找库和头文件)
    # 可通过 -DCMAKE_FIND_ROOT_PATH= 参数指定
    set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
    set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
    set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
    
    # ARM编译标志
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -marm -mfpu=neon -mfloat-abi=hard")
    # 如果不需要硬浮点,可以用:-mfloat-abi=soft
    
    # 调试和优化标志(可选)
    # set(CMAKE_C_FLAGS_DEBUG "-g -O0")
    # set(CMAKE_C_FLAGS_RELEASE "-O2")
    
    # 启用详细编译输出(可选)
    # set(CMAKE_VERBOSE_MAKEFILE ON)
    
    message(STATUS "Build for: ${CMAKE_SYSTEM_PROCESSOR} (${CMAKE_SYSTEM_NAME})")
    message(STATUS "C compiler: ${CMAKE_C_COMPILER}")
    message(STATUS "C flags: ${CMAKE_C_FLAGS}")
    
    # 添加可执行文件
    add_executable(led_control led.c)
    
    # 链接到必要的库(如果需要)
    # target_link_libraries(led_control m)  # 数学库
  • cmake指令

    bash 复制代码
     cd /home/joe/Code/Embeed/ApplicationDevelop/MyImplement/Hardware/LED/build && cmake -DCMAKE_C_COMPILER=/   │
    │   usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc              │
    │   -DCMAKE_CXX_COMPILER=/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gn   │
    │   ueabihf-g++ -DCMAKE_FIND_ROOT_PATH=/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/ar   │
    │   m-linux-gnueabihf/libc ..   
  • 编译并通过scp传输到开发板上,进行验证

    c 复制代码
    root@ATK-IMX6U:~/AppDev# ./led_control none 1
    LED配置更新成功。
    root@ATK-IMX6U:~/AppDev# ./led_control none 0
    LED配置更新成功。