地平线旭日X3派试用-玩转led_blinks

旭日X3开发板系统默认预置了GPIO操作,同时在X3派上有一个LED指示灯(如下图 10号绿色灯),默认情况下上电后常亮。

在旭日X3派用户手册中描述了使用 /usr/bin/led_blinks控制LED的闪烁状态。

参考链接:https://developer.horizon.ai/api/v1/fileData/documents_pi/Quick_Start/Quick_Start.html#led

led_blinks是一个shell脚本程序,通过控制LED指示绿灯的GPIO管脚来使绿灯亮和灭。除了不带参数的运行外,它还支持以下三个参数选项:

  • normal:与不加参数是的效果一样,指示灯亮灭间隔1秒钟
  • fast:指示灯亮灭间隔300毫秒,闪烁较快
  • slowly:指示灯亮灭间隔2秒钟,闪烁较慢

我们能不能自己编写一个程序库,用来提供对LED的操作、方便后期集成到产品项目中(用作软件故障指示灯或软件升级状态指示灯/...)呢?

首先我们先来学习一下,led_blinks 脚本

#!/bin/bash

# 控制LED的gpio管脚
gpio_pin=26
# 闪烁间隔时间
intervals=1

# 处理程序运行参数
# 支持设置 "normal", "fast", "slowly" 三种闪烁速度
if [ $# == 1 ];then
 case $1 in
 "normal")
 intervals=1
 ;;
 "fast")
 intervals=0.3
 ;;
 "slowly")
 intervals=2
 ;;
 "*")
 intervals=1
 ;;
 esac
fi

# 运行前先释放一下
echo ${gpio_pin} > /sys/class/gpio/unexport

# 申请 LED 灯的控制管脚,设置功能为GPIO功能
echo ${gpio_pin} > /sys/class/gpio/export
if [ $? -ne 0 ]; then
 echo "Failed to request LED control pin"
 exit 1
fi
echo "Request LED control pin successfully"

# 设置控制管脚为输出模式
echo out > /sys/class/gpio/gpio${gpio_pin}/direction
if [ $? -ne 0 ]; then
 echo "Failed to set LED control pin to output mode"
 exit 1
fi
echo "Set LED control pin to output mode successfully"

echo "Let the LED into cycle on and off mode"

# 开始控制LED循环亮灭,1秒钟变化
while [ true ];
do
 echo 1 > /sys/class/gpio/gpio${gpio_pin}/value
 sleep ${intervals}
 echo 0 > /sys/class/gpio/gpio${gpio_pin}/value
 sleep ${intervals}
done

地平线的小哥哥在led_blinks脚本中的注释还是非常到位的,这点必须点赞!

简单来说,就是导出gpio控制文件,设置引脚输出属性,最后通过控制引脚电平实现LED点亮和熄灭。

现在我的需求是对LED操作进行封装,实现为一个动态链接库、提供通用的API供后期产品开发使用。

Step1:设计API

//pin_driver.h

/** 
 * @dscription:export pin ctronl files
 * @param[in]: pin_id pin id number
 * @return: 0=succ, others is failed
 * */
int export_pin(int pin_id);

/**
 * @description: unexport pin ctronl files
 * @param[in]: pin_id pin id number
 * @return: 0=succ, others is failed
 * */
int unexport_pin(int pin_id);

/**
 * @description: set pin direction
 * @param[in]: pin_id pin id number
 * @param[ind]: direction 1=out, 0=in
 * @return: 0=succ, other is failed
 * */
int set_pin_direction(int pin_id, int direction);

/**
 * @description: set pin value
 * @param[in]: pin_id pin id number
 * @param[in]: value 1=high level, 0=low level
 * */
int set_pin_value(int pin_id, int value);

//Step2: 实现API

//pin_driver.c

int write_command(const char* file, const char *cmd)
{
    if (!file || file[0] == '\0' || !cmd || cmd[0] == '\0')
    {
        return -1;
    }

    int fd = open(file, O_WRONLY);
    if (-1 == fd)
    {
        perror("open");
        return -2;
    }

    int size = write(fd, cmd, strlen(cmd));
    if (size != strlen(cmd))
    {
        perror("write");
        close(fd);
        return -3;
    }

    close(fd);

    return 0;
}

int export_pin(int pin_id)
{
    char buf[16];
    snprintf(buf, sizeof(buf), "%d", pin_id);
    return write_command("/sys/class/gpio/export", buf);
} 

int unexport_pin(int pin_id)
{
    char buf[16];
    snprintf(buf, sizeof(buf), "%d", pin_id);
    return write_command("/sys/class/gpio/unexport", buf);
}

int set_pin_direction(int pin_id, int direction)
{
    char filename[64];
    char buf[8];
    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/direction", pin_id);
    snprintf(buf, sizeof(buf), 1 == direction ? "out" : "in");
    return write_command(filename, buf); 
}

int set_pin_value(int pin_id, int value)
{
    char filename[64];
    char buf[8];
    snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", pin_id);
    snprintf(buf, sizeof(buf), "%d", value);
    return write_command(filename, buf);
}

//Step3: 测试API

//led_blinks.c

void msleep(int ms)
{
    usleep(ms * 1000);
}

int main(int argc, char *argv[])
{
    unexport_pin(26);
    export_pin(26);
    set_pin_direction(26, 1);
 
    while (1)
    {
        set_pin_value(26, 1);
        msleep(500);

        set_pin_value(26, 0);
        msleep(500);
    }

    return 0;
}

//Step4:封装动态库

//CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(led_blinks)
set(CMAKE_BUILD_TYPE "Debug")
add_library(pin_driver SHARED pin_driver.c)
add_executable(led_blinks led_blinks.c)
target_link_libraries(led_blinks pin_driver)

经过测试验证,可以完美控制X3派 LED 任意周期闪烁和熄灭。文中所有文件,均已打包在附件中。欢迎大家来一起玩转led_blinks

「地平线旭日X3派,开启你的嵌入式开发之旅」,欢迎正在阅读的你申请试用,一起交流开发心得

led_blinks_20220712234542.rar

赞!期待我们新品体验官更多的产出呀~?

大佬的代码可以重新编辑下,使用代码格式,不然拍板看起来有点,可以在个人中心里面进行重新编辑哈

?

?