当前位置:网站首页>LED的C语言应用程序
LED的C语言应用程序
2022-08-04 19:36:00 【随遇而安的dandelion】
引言
在本文中,用C语言编写一个LED灯的应用程序,对文章《基于HDF的LED驱动程序开发》(1)、(2)中开发的LED灯的驱动程序进行测试。
另外,在编写LED灯的应用程序时,我们会用到很多由HDF框架提供的API。为了便于查阅这这些API的用法,建议大家在阅读本文的同时,打开文章《HDF驱动框架的API》(1)、(2)、(3)。在这几篇文章中汇集了本文所用到的API。当然,你也可以直接去阅读这些API的源码和官方说明文档。
本文参考了小熊派BearPi-HM_Micro_Small开发板的部分教程。
https://gitee.com/bearpi/bearpi-hm_micro_small
在阅读本文之前,确保已阅读了《小熊派BearPi-HM_Micro_Small之Hello_World》。
一、编写源程序
首先,在路径applications/BearPi/BearPi-HM_Micro/samples/dandelion下新建一个文件夹:my_led_app。
然后,在文件夹my_led_app中新建一个文件:my_led_app.c,接下来我们在这个文件中编写源程序。
这个应用程序没有用户图形界面,只能以命令行的形式运行:./my_led 参数 ,命令参数有三种取值:0、1、2,分别控制LED关闭、打开和状态切换。
在源程序my_led_app.c中,除了一些头文件和宏定义之外,主要包括以下两个函数:
| 函数 | 描述 |
|---|---|
| int main(int argc, char **argv) | 应用程序的主函数 |
| static int LedWriteRead(struct HdfIoService *serv, uint8_t sendData, uint8_t *recvData) | 向驱动程序发送数据,然后接收驱动程序的响应。 |
1.1 头文件、宏定义
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"
#define LED_WRITE_READ 1 //应用程序下发给LED驱动的命令字。1:写;0:读。
#define LED_SERVICE "hdf_led" //LED驱动对外提供的服务的名称,与驱动配置中的名称一致。
1.2 主函数
int main(int argc, char **argv)
{
int i;
// 打印输出在终端中输入的命令行
for (i=0; i < argc; i++)
{
printf("\r\nArgument %d is %s.\r\n", i, argv[i]);
}
// 获取驱动提供的服务
struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE);
if (serv == NULL)
{
printf("fail to get service %s!\r\n", LED_SERVICE);
return HDF_FAILURE;
}
// 向驱动发送LED的控制数据,从驱动接收LED当前的状态
uint8_t replyData = 0;
LedWriteRead(serv, atoi(argv[1]), &replyData);
printf("\r\nGet reply is: %d\r\n", replyData);
// 回收资源
HdfIoServiceRecycle(serv);
// 退出程序
printf("exit");
return HDF_SUCCESS;
}
在main函数中,使用到了HDF提供的接口函数:HdfIoServiceBind、HdfIoServiceRecycle,以及结构体HdfIoService。
1.3 LedWriteRead函数
LedWriteRead函数在主函数main中被调用,用于与内核态的驱动程序交换数据。第1个参数serv:指向驱动服务对象(HdfIoService结构体)的指针;第2个参数sendData:向驱动程序下发的数据;第3个参数recvData:指向一个变量的指针,该变量用于存放从驱动函数收到的应答数据。
static int LedWriteRead(struct HdfIoService *serv, uint8_t sendData, uint8_t *recvData)
{
int ret = HDF_SUCCESS;
// 创建一个缓冲区,用于向驱动发送数据
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
if (data == NULL)
{
printf("fail to obtain sbuf data!\r\n");
return HDF_FAILURE;
}
// 创建一个缓冲区,用于从驱动接收响应
struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (reply == NULL)
{
printf("fail to obtain sbuf reply!\r\n");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
}
// 把要下发给驱动的数据写入缓冲区
if (!HdfSbufWriteUint8(data, sendData))
{
printf("fail to write sbuf!\r\n");
ret = HDF_FAILURE;
goto out;
}
// 调用应用态的Dispatch函数与驱动交互
ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS)
{
printf("fail to send service call!\r\n");
goto out;
}
// 从缓冲区中读取驱动的响应数据
if (!HdfSbufReadUint8(reply, recvData))
{
printf("fail to get service call reply!\r\n");
ret = HDF_ERR_INVALID_OBJECT;
goto out;
}
out:
// 回收缓冲区
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
}
在main函数中,使用到了HDF提供的接口函数:HdfSBufObtainDefaultSize、HdfSbufWriteUint8、HdfSbufReadUint8、HdfSBufRecycle,以及结构体HdfSBuf、HdfIoService。
二、编写/修改编译脚本
1、在文件夹my_led_app下新建一个文件:BUILD.gn,在这个文件中编写源程序my_led_app.c的编译脚本:
import("//build/lite/config/component/lite_component.gni")
HDF_FRAMEWORKS = "//drivers/framework"
executable("my_led_exe") {
output_name = "my_led"
sources = [
"my_led_app.c",
]
include_dirs = [
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/master/include",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"//drivers/adapter/uhdf/posix/include",
"//third_party/bounds_checking_function/include",
"//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
]
deps = [
"//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
"//drivers/adapter/uhdf/manager:hdf_core",
"//drivers/adapter/uhdf/posix:hdf_posix_osal",
]
}
executable("my_led_exe")用于声明一个名为my_led_exe的、类型为executable的目标(target),指示编译构建子系统将源码my_led_app.c编译成名为my_led的可执行文件。
output_name用于指定编译生成的可执行文件的名称。
sources列表中是编译构建所需要的源码文件。
include_dirs列表中是源码文件中引用的头文件的路径。
deps列表中是编译构建时需要依赖的其他库。
2、修改文件夹dandelion下的编译脚本文件:BUILD.gn。
import("//build/lite/config/component/lite_component.gni")
lite_component("dandelion_app") {
features = [
"hello_world:hello_world_exe",
"my_led_app:my_led_app",
]
}
lite_component是在build/lite/config/component/lite_component.gni中定义的一个template,用于将上面那个名为my_led_exe的target纳入到名为my_led_app的编译构建目标里面。
三、编译、烧写
参考《小熊派BearPi-HM_Micro_Small之Hello_World》第五、六部分。
四、测试
待系统启动完毕后,在串口终端中依次执行以下命令:
./bin/my_led 1
./bin/my_led 0
./bin/my_led 2
将分别控制小熊派BearPi-HM_Micro_Small开发板上的LED点亮、熄灭、状态切换,串口终端终端输出入下图所示:

边栏推荐
猜你喜欢
随机推荐
切换node版本和切换npm源工具
Query the published version records of the APP Store
SAP 电商云 Accelerator 和 Spartacus UI 的工作机制差异
MogDB学习笔记-环境准备及单实例安装
前3名突然变了,揭秘 7 月编程语言最新排行榜
JS: 数组和树的相互转换
基于YOLOV5行人跌倒检测实验
《支付宝体验设计精髓》一书,跟测试相关性知识记录
Seata source code analysis: various message processing processes of seata server
指静脉识别-matlab
Force KouTi (5), the longest text string back
zynq records
TritonVM——基于Recursive STARK的虚拟机
A complete cross-compilation environment records the shell scripts generated by peta
SAP UI5 确保控件 id 全局唯一的实现方法
蚂蚁集团时序数据库CeresDB正式开源
如何搭建 RADIUS 云服务器?
How to use the Chrome DevTools performance tab
getBoundingClientRect
SAP UI5 视图控制器 View Controller 的生命周期方法 - Lifecycle methods








