鸿蒙设备开发之Hello World

2023-11-03

引言

每当学习一门新的编程语言或者上手一款新的开发板,我们经常写的第一个程序要么是在终端窗口中打印输出“Hello World !”,要么就是驱动GPIO点亮开发板上的LED灯。本文是在学习鸿蒙设备开发过程中,带大家写的第一个程序,通过这个程序,我们可以对鸿蒙设备开发的整个流程有一个初步的体验。

注:本文中出现的“鸿蒙”指的是“OpenHarmony”。如果不清楚鸿蒙HarmonyOSOpenHarmony之间的关系和区别,可以去看我的另一篇文章:迈出学习鸿蒙操作系统的第一步

在阅读正文之前,建议大家先搭建好实验环境:

(1)按照《搭建鸿蒙设备开发环境:Ubuntu20.04+DevEco Device Tool Release 3.0》搭建鸿蒙开发环境。

(2)按照《获取OpenHarmony源码:从DevEco Marketplace获取(2)》创建一个鸿蒙项目。

(3)准备一块Hi3861处理器的开发板,我使用的是润和的Pegasus物联网开发套件。

建好的实验环境:

(1)Ubuntu20.04

(2)DevEco Device Tool Release 3.0(devicetool-linux-tool-3.0.0.401)

(3)用OpenHarmony发行版@ohos/hispark_pegasus 3.1.2创建了鸿蒙工程hispark_pegasus_312。

(4)润和的Pegasus物联网开发套件

一、编写源程序

1、新建文件夹experiment 。

单击DevEco Device Tool左侧工具栏中的Explore图标,打开鸿蒙工程hispark_pegasus_312的目录树,选中applications/sample/wifi-iot下的app文件夹,在其上单击鼠标右键,选择New Folder,新建一个文件夹experiment,以后每次实验的代码可以放在这个文件夹下。

在这里插入图片描述

2、新建文件夹B01_hello_world 。

在文件夹experiment中再新建文件夹B01_hello_world,用于存放本次实验的代码。

3、新建文件hello_world.c 。

选中文件夹B01_hello_world,在其上单击鼠标右键,选择New File,新建一个文件hello_world.c。

4、编写源程序。

在文件hello_world.c中编写本次实验的源程序。

(1)头文件

#include <stdio.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

(2)宏定义

#define TASK_STACK_SIZE     1024                  // 任务堆栈的大小,单位:字节     
#define TASK_PRIO           osPriorityNormal1     // 任务优先级

osPriorityNormal1是在头文件 cmsis_os2.h 中定义的枚举量,值为25。

(3)任务函数

可以把任务函数简单理解成主函数。本例程中的任务函数很简单,就是每隔2秒打印输出Hello world!

//任务函数
static void HelloTaskFun(const char *arg)
{
    (void)arg;
    unsigned int cnt = 0;

    printf("\n");
    while(1)
    {
        printf(">>>Hello world! cnt=%d \n", cnt);
        cnt++;
        osDelay(200);
    }
}

osDelay是在 cmsis_os2.h 中声明的函数。

(4)任务入口函数

任务入口函数的作用就是把任务函数创建成一个任务,并使之进入就绪状态,接受操作系统的调度。主要包括两个步骤:设置任务属性;创建任务。

//任务入口函数
static void HelloTaskEntry(void)
{
    //Step1:设置任务属性
    osThreadAttr_t attr;
    attr.name       = "HelloTask";      //任务名称
    attr.attr_bits  = 0U;
    attr.cb_mem     = NULL;
    attr.cb_size    = 0;
    attr.stack_mem  = NULL;
    attr.stack_size = TASK_STACK_SIZE;  //任务堆栈的大小,单位:字节
    attr.priority   = TASK_PRIO;        //任务优先级

    //Step2:创建任务
    if(osThreadNew((osThreadFunc_t)HelloTaskFun, NULL, &attr) == NULL)
    {
        printf(">>> Error!!! Falied to create HelloTask!\n");
    }
}

osThreadAttr_t 是在 cmsis_os2.h 中定义的结构体类型。通常只需要设置任务名称、任务堆栈的大小和任务优先级,其他属性设置为0或NULL即可。

osThreadNew 是在 cmsis_os2.h 中声明的函数,用于把任务函数创建成一个任务,并使之进入就绪状态,接受操作系统的调度。传给函数的第一个参数是指向任务函数的指针;第二个参数也是一个指针,指向要传给任务函数的参数;第三个参数是指向任务属性结构体的指针。如果任务创建成功,该函数返回任务的ID;否则,函数的返回值是NULL。

osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr);

(5)APP_FEATURE_INIT

APP_FEATURE_INIT(HelloTaskEntry);

APP_FEATURE_INIT是一个在头文件 ohos_init.h 中定义的带参数的宏,这个宏的作用就是指示编译器把某个函数(如:本例程中的 HelloTaskEntry ),编译到某个代码段中,系统启动之后,会遍历这个代码段中的所有函数并执行。

二、编写编译脚本

除了编源程序之外,我们还需要通过编译脚本告诉鸿蒙工程的编译构建子系统,如何处理我们在本文第二部分编写的源程序。关于鸿蒙工程的编译构建子系统,我准备专门开一个专栏写一些文章,敬请期待。

1、在B01_hello_world文件夹中新建一个BUILD.gn文件,填入以下内容:

static_library("B01_hello_world") {
    sources = [
        "hello_world.c",
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//device/hisilicon/hispark_pegasus/hi3861_adapter/kal/cmsis",
    ]
}

注:这个编译脚本的文件名必须是BUILD.gn,不要用其他名字,这是由编译构建子系统决定的。

这个BUILD.gn文件中的static_library是告诉编译构建子系统,将应用程序编译生成一个静态库,主要内容包括三部分:

(1)在static_library后面的括号中,指定要编译生成的静态库的目标名称,例如:B01_hello_world。在本文第三部分编译工程之后,会在 out/hispark_pegasus/wifiiot_hispark_pegasus/libs 路径下生成一个静态库文件:libB01_hello_world.a(在指定的静态库目标名称前会默认加上lib)。

(2)在sources列表中,列出编译生成静态库所需要用到的源文件,多个文件之间用逗号隔开。

(3)在include_dirs列表中,列出源文件中所引用的头文件的路径,多个路径之间用逗号隔开。

无论是sources列表中的文件,还是include_dirs列表中的路径,若包含"//“则表示使用绝对路径(”//“代表鸿蒙项目根目录的全路径名),若不包含”//"则表示使用相对路径(相对于当前这个文件所在的文件夹)。

2、修改app文件夹下的BUILD.gn文件。

在这个BUILD.gn文件的features列表中,添加一项,如下图红框中所示:

在这里插入图片描述

我们知道,鸿蒙系统是按照“系统(子系统集)”、“子系统(Subsystem)”、“组件/模块(Component)”逐次展开的,详见:《迈出学习鸿蒙操作系统的第一步》中的“鸿蒙操作系统的技术架构”。其实,一个组件/模块(Component)也可以进一步分成若干个Feature。在本文中,由源程序 hello_world.c 生成的静态库B01_hello_world 就被作为一个feature加入到了名为app的Component中;app这个Component又是子系统applications 里面的。

这个BUILD.gn文件就是告诉编译构建子系统怎么去构建一个模块(Component)。

第14行中的import语句类似于C程序中的#include,因为第16行用到的 lite_component 是在这个.gni文件中定义的。

第16行,lite_component后面的括号中是要构建生成的模块的目标名称(Target Name)。

在feature列表中列出参与构建这个Component的目标(Target),这个列表中的每个目标都可以被看作构成这个Component的一个Feature,其中就包括由源程序hello_world.c生成的目标:静态库B01_hello_world。

冒号后面是要参与构建这个Component的目标。冒号前面是目标的路径,里面没有包含"//",所以这是一个相对路径。在编译构建时,编译构建子系统会到这个路径下寻找名为 BUILD.gn 的文件,再根据这个 BUILD.gn将源程序 hello_world.c 编译成一个目标,即:静态库 B01_hello_world 。

注1:冒号前后不能有空格。

注2:如果冒号后面的目标名字与目标的BUILD.gn文件所在文件夹名字相同,可以省略冒号和其后面的目标名称,如下图所示:

在这里插入图片描述

现在,我们基本上知道了,如何通过编写BUILD.gn文件,指示编译构建子系统构建一个Feature,以及将Feature加入到Component中,构建一个Component。那么,怎么把Component加入到Subsystem中,以及怎么让某个Subsystem参与整个鸿蒙系统的构建呢?在编译构建子系统专栏中,我会把这些问题讲清楚。

三、编译工程

点击左侧工具栏中的DevEco图标,在“PROJECT TASKS”–鸿蒙工程hispark_pegasus_312–hi3861下,单击Build按钮,开始编译。

在这里插入图片描述

编译成功后,终端(TERMINAL)窗口的输出如下图所示。可以在工程的out目录下,查看编译生成的文件,用于后续的Hi3861开发板烧录。

在这里插入图片描述

四、烧写程序

1、连接Hi3861开发板和开发主机。

将Hi3861开发板通过USB线与电脑连接后,Ubuntu虚拟机会弹出下图所示窗口,选择连接到虚拟机,选择虚拟机名称,单击“确定”。

在这里插入图片描述

2、配置工程的烧录选项(Upload Options)。

在这里插入图片描述

点击左侧工具栏中的DevEco图标;打开Projetc Settings页面;打开hi3861标签页;设置烧录选项(Upload Options),包括upload_partitions、upload_port和upload_protocol。

upload_partitions:选择待烧录的分区列表,默认选择 hi3861_app 。

upload_port:选择串口设备 /dev/ttyUSB0 。

upload_protocol:选择 hiburn-serial 。

最后,单击右上角的Save按钮,保存配置信息。

3、启动烧录

(1)点击左侧工具栏中的DevEco图标,在“PROJECT TASKS”–鸿蒙工程hispark_pegasus_312–hi3861下,单击Upload按钮。

在这里插入图片描述

(2)终端(TERMINAL)窗口的输出如下图所示:

在这里插入图片描述

根据提示信息,按开发板上的复位键,对开发板进行复位(注:如果终端窗口没反应,就再按一次),直到开始烧录。

(3)烧录完毕后,终端窗口如下图所示:

在这里插入图片描述

单击终端窗口,看到实心白色光标块后,根据最后一行提示,按任意键关闭终端窗口。

五、测试

(1)点击左侧工具栏中的DevEco图标,在“PROJECT TASKS”–鸿蒙工程hispark_pegasus_312–hi3861下,单击Monitor按钮。
在这里插入图片描述

终端窗口如下图所示。

在这里插入图片描述

(2)按开发板上的复位键,对开发板进行复位,烧录到开发板上的程序开始执行,在终端窗口中打印输出一些信息,如下图所示:

在这里插入图片描述

单击终端窗口,看到实心白色光标块后,按ctrl+c结束程序,然后按任意键可关闭终端窗口。

本文在CSDN、公众号、头条号和知乎同步发布,感谢关注。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

鸿蒙设备开发之Hello World 的相关文章

  • AD设置某个焊盘铺铜连接方式

    AD设置某个焊盘铺铜连接方式 在规则中创建个别焊盘铺铜连接方式 目的 PCB布板时 将表贴焊盘与铺铜连接方式设置为花焊盘 十字连接 将螺钉孔与铺铜连接方式设置为全连接 步骤一 所有焊盘与铜皮默认为十字连接 单独设置螺钉孔与铜皮全连接 步骤二

随机推荐

  • MYSQL相关问题解惑

    MYSQL如何查看默认存储引擎 方式1 使用show engines语句查看系统中所有的存储引擎 Support列的值表示某种引擎是否能使用 YES表示可以使用 NO表示不能使用 DEFAULT表示该引擎为当前默认存储引擎 方式2 也可以使
  • Linux基本操作指令

    Linnux课程框架学习 LINUX 初识阶段 常用操作 常用工具 1 Linux 系统编程阶段 1 gt 进程概念 2 gt 进程控制 3 gt 基础IO 4 gt 进程间通信 5 gt 进程信号 6 gt 多线程 2 LINUX 网络编
  • 魔兽怀旧服联盟服务器不稳定,魔兽世界怀旧服转服服务关闭最后一天,联盟部落新的对抗...

    魔兽世界这款经典了十几年的游戏有好多的话题可聊 不过恒古不变的热门话题中 联盟与部落的对抗永不过时 在经典怀旧服暂停转服服务即将到来的前一天 某知名论坛又出现了单边大服中阵营之争的唇枪舌战 具体是什么原因引起的 暂时还没有本服大佬出面解释
  • 最全的雅思8000词汇pdf_雅思剑桥1-14同义词汇总,屠鸭必备!(含剑14)

    剑14真题出来之后很多烤鸭私聊哥说什么时候有剑14的同义词替换啊 这不 哥这就来分享了 一个合格的雅思考生的词汇量要在7000左右 而在雅思考试中关于词汇的运用最重要的一部分是 同义词替换 同义词的考察贯穿了雅思考试听说读写的每一项 Lis
  • 【unity笔记】OnCollision和OnTrigger方法使用的一个误区【2D】

    最近在做2D游戏 所以经常使用到两个检测碰撞的方法 OnCollisionXX 方法或OnTriggerXX方法 两个方法的使用大致相同 传入的参数略有差别 void OnCollisionEnter2D Collision2D colli
  • 博弈论【算法】

    目录 定义 巴什博弈 减法博弈 威佐夫博弈 定义 博弈论主要研究公式化了的激励结构间的相互作用 是研究具有斗争或竞争性质现象的数学理论和方法 博弈论考虑游戏中的个体的预测行为和实际行为 并研究它们的优化策略 如囚徒困境 链接 在算法竞赛中出
  • 设计模式—单例模式

    文章目录 为什么使用单例模式 实现 预加载 懒加载 懒加载 线程安全 synchronized synchronized volatile 为什么使用单例模式 单例最有代表就是我们耳熟能详的 windows 任务管理器 无论我们创建多少次
  • 记录一下项目踩到的一些坑(不断更新)

    1 HTTPS 问题排查 相信大家PHP在做第三接口或者一些接口调用的时候都会用到curl 在本地部署开发没问题 但是部署到正式服务器的时候就会导致返回一些无知错误 解决方案排查 可以考虑一下是否在curl 的时候做了HTTPS的校验 2
  • Java中为什么要引入泛型

    优点1 没有使用泛型 向list集合中添加非字符串 运行时会报错 类型不匹配 ObjectList java package cn nxl2018 import java util ArrayList import java util Li
  • 解决 : ValidationError: Invalid options object. PostCSS Loader ......

    问题背景 使用 vue cli 5 x 脚手架工具搭建一个初始化项目架子 在 vue config js 里面 配置 移动端 的 适配性插件 postcss pxtorem 的代码时 运行启动项目时报错如下图 Compiled with p
  • openfeign get请求的正确写法

    openfeign 请求get自动变成post 这里试过很多方法都不行 比如 SpringQueryMap 使用如下方法可以方便解决 记录一下方便后人 RequestLine GET api daily param1 param1 para
  • 如何从技术岗位转为管理岗位呢?

    很多做技术的人 做多了几年总是担心自己的职业生涯发展道路 对自己的职业生涯发展缺乏方向和清晰的目标 而且 不少技术岗位的人员都认为技术不能干一辈子 总是希望有更好的机会 然而如何从技术岗位转型为管理岗位呢 这难倒了不少技术岗位的人 毕竟技术
  • X2000 SDK 开发笔记

    SDK编译 1 设置环境变量 在工程目录下执行命令 source build envsetup sh 2 选择 device 在工程目录下执行命令 lunch 根据硬件底板版本选择v10 v20 v30 根据开发板flash默认选择nand
  • 谷歌云平台及其产品介绍

    谷歌云平台 Google Cloud Platform 是谷歌所提供的一套公有云计算服务 该平台包括一系列在 Google 硬件上运行的用于计算 存储和应用程序开发的托管服务 软件开发人员 云管理员和其他企业 IT 专业人员可以通过公共互联
  • 每节课都是一个项目 手把手用STM32打造联网气象站-1-安装开发环境

    工欲善其事必先利其器 我们为了打造一个可以联网的智能气象站 先得把集成开发环境IDE整利索 亮点在最后 读完有惊喜 我们这个教程的集成开发环境包括了2部分 第一部分是常见的KEIL 本文会讲解KEIL的安装和使用 第二部分是更加常见的vsc
  • Apollo配置中心热加载mysql_一种Apollo配置中心的搭建方法与流程

    本发明涉及一种信息技术处理领域 特别涉及一种apollo配置中心的搭建方法 背景技术 随着分布式系统中程序功能的日益复杂 程序的配置日益增多 各种功能的开关 参数的配置 服务器的地址等的配置错综复杂 对程序配置的期望值也越来越高 配置修改后
  • Odoo服务器搭建——保姆级教程

    文章目录 一 工具准备 二 更新系统 三 添加系统工具 四 安装Postgresql数据库 1 下载Postgresql 2 启动Postgresql 3 创建数据库用户 4 在新用户中创建数据库 五 上传Odoo源码 1 创建目录 2 上
  • ESP32 LVGL使用外部FLASH字体BIN文件

    ESP32 LVGL使用外部FLASH字体BIN文件 生成字体文件 使用LvglFontTool 这个工具 生成类型勾选XBF字体 外部BIN文件 会生成两个文件 一个myFont c 和一个bin文件 然后把bin文件放到spiffs分区
  • nginx 代理 portainer 报 Unable to retrieve server settings and status

    一 nginx配置 location portainer proxy pass http localhost 19000 proxy set header Via nginx proxy set header Host host proxy
  • 鸿蒙设备开发之Hello World

    引言 每当学习一门新的编程语言或者上手一款新的开发板 我们经常写的第一个程序要么是在终端窗口中打印输出 Hello World 要么就是驱动GPIO点亮开发板上的LED灯 本文是在学习鸿蒙设备开发过程中 带大家写的第一个程序 通过这个程序