旭日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派,开启你的嵌入式开发之旅」,欢迎正在阅读的你申请试用,一起交流开发心得