发表自话题:HarmonyOS 2
基于 Hi3861 平台的 HarmonyOS Device 开发体验
大家好,我是不务正业的非著名 Copy 攻城狮,此篇应是 Copy 攻城狮 2020 年最后一个”Hello,World“--基于 Harmony OS 的 Hi3861 开发板进行物联网应用开发实战。Copy 攻城狮的“Hello World”之路 [1]从来都不是一帆风顺的,此次尝试开(拷)发(贝)物联网应用也走了不少弯路,最后终于跑通了蜂鸣器版的《Jingle Bells》,预祝大家新年快乐!环境搭建篇
编程界有个传承了几十年的”规矩“--入门先从环境搭建开始,有的时候环境搭建比较简单,比如学习 HTML 编程,有浏览器就行;有时候又比较繁琐,比如 React Native 开发,需要安装 NodeJS、Python、Java、Android SDK……而 HarmonyOS Device 开发属于后者,环境搭建比较繁琐,比如需要 Linux 系统进行编译,烧录到设备时又需要用到 Windows。如果您还想体验 Wifi 模组或者“碰一碰”等其他功能,还需要提供热点及其他设备。HarmonyOS 官方提供了详细的环境搭建文档[2] 以及 Hi3861 开发板介绍[3],理论上跟着文档走一遍就能正常运行“Hello,HarmonyOS Device”。
尽管如此,不过每个人的开发习惯或者工具口味不一样,因此在实际搭建环境的时候还是会和官方文档有些不一样的地方。由于手头有点乞丐版的云主机资源,因此我选择将他们派上用场,用 Linux 的云主机作为编译机,在本地的 Window 10 电脑上安装 SFTP Drive 将 Linux 云主机挂载到本机,使得烧录的时候能直接读取到 Linux 上的文件;通过 VSCode 的 Remote SSH 扩展以及 HUAWEI DevEco Device Tool 扩展来开发调试代码,此外通过某大佬分享的 sscom 串口调试工具进行更加便捷的调试。如果您恰好和我一样的情况,或者您也想尝试一下我的搭建思路,那我们就开始吧!
1. Windows 环境(开发、调试、烧录)
在 Windows 上,因为涉及到开发调试,因此我们需要安装 VS Code 及扩展(也就是插件)、SFTP Drive(烧录时用来直接访问 Linux 上的文件)、CH341SER.EXE(USB 转串口驱动)、sscom(可选,方面连接串口调试)。我这边本地已经安装了 VS Code 就不过多赘述,相信大家都安装了,从我接触过的几个软硬件开发教程都推荐安装 VS Code,真香!
1.1 Remote - SSH[4]和 SFTP Drive
可能大家会有疑问,这两个玩意都是访问远程主机上文件的,装一个就行了吧?刚开始我也有同样的想法,后来在实操中发现:如果只安装 Remote - SSSH,烧录配置时无法读取远程文件;如果只安装 SFTP Drive,在编辑代码时访问远程文件非常慢;在座的给位大佬有好的方案的话一定要传授一下哦。我这里安装的是 Remote - SSH,如果您想体验更多的功能,可以直接安装 Remote Development,Remote 系列是巨硬公司针对远程开发而开发的扩展。安装完 Remote - SSH 之后,为了免密码登录 Linux(有风险需谨慎),我们需要操作一下 SSH 密钥配置。
在 VSCode 的 Remote 扩展和 SFTP Drive 中先通过账号密码访问远程主机,确保能正常访问到 Linux 主机中的代码和文件。
SSH 密钥配置的时候,我们可以在远程主机上生成密钥,也可以在本机生成密钥,最终将配置关联就可以。我们这里采用的是 Windows 机使用 PowerShell 执行ssh-keygen生成密钥到文件C:\Users\您的用户名\.ssh\id_rsa(私钥),同时会生成文件C:\Users\您的用户名\.ssh\id_rsa.pub(公钥),通过 SFTP Drive 拷贝公钥到远程主机的~/.ssh目录,在 VSCode 中连接远程主机执行命令cat id_rsa.pub >> authorized_keys追加到 authorized_keys 中,由于我本机已经有了公钥私钥,直接拿来用即可。 此步需注意的是:
cd ~/.ssh cat id_rsa.pub >> authorized_keys #追加公钥 sudo chmod 600 authorized_keys sudo chmod 700 ~/.ssh #文件及文件夹加权限 sudo vim /etc/ssh/sshd_config #准备修改sshd配置 # PubkeyAuthentication yes 确保此处注释放开 sudo service sshd restart #重启sshd完事之后关闭 VSCode 再打开,不出意外再连接远程主机就不需要输入访问密码了,彻底告别每次连接都要输密码的烦恼。
1.2 HUAWEI DevEco Device Tool 及依赖安装
HUAWEI DevEco Device Tool[5]可以理解为是 HarmonyOS Device 的开发工具,“HarmonyOS 智能设备一站式集成开发环境,支持 HarmonyOS 组件按需定制、一键编译和烧录、可视化调试、分布式能力集成等,帮助开发者高效开发和创新新硬件”。
官网:https://device.harmonyos.com/cn/ide[6],目前只支持 Windows,这也是为什么我们需要用到 Windows 本机的原因!另外 HUAWEI DevEco Device Tool 没有上架到 VSCode 扩展市场,只能通过从 VSIX 安装的方式进行安装,也就是说我们需要解压从官网下载的安装包,另外将.vsix文件后缀修改为.zip解压有惊喜哦 -- 在 DevEcoDeviceTool\extension\deveco\tool您能得到HiBurn.exe,这个程序就可以用来烧录(相当于不使用 VSCode 的扩展在程序中配置烧录参数直接烧录)。
根据官方文档的指引,我们还需要:
安装 Node.js(尽量别装最新的)安装 JDK安装 hpm安装 VSCode C/C++扩展安装 CH341SER.EXE安装 Jlink 工具(可选,V6.54c 及以上版本)安装 hcc_riscv32(这个我没装成功,所以调试全靠手打)鉴于前期跑过“Hello, HarmonyOS”(因此才获得的开发板),大部分环境我都有,不过在安装 Jlink 工具的时候卡了很久,主要是网络的问题,导致下载的文件不全,好在想方设法终于下好了,又在安装 hcc_riscv32 时卡住了,幸好不是关键,索性放弃!……费了九牛二虎之力,终于完成 Windows 部分的环境搭建,可以直接烧录别人编译好的程序了!
2. Linux 环境(编译)
相比 Windows 环境,HarmonyOS Device Linux 的环境搭建显得微不足道,跟着文档走一遍就完事了。不过,经过实操,如果您是 Ubuntu 18.04,我更加推荐润和许老师的文档--Harmony OS 开发指南——源码下载和编译[7]。如果您和我一样还想尝试一下在 CentOS 上搭建环境,那就推荐鸿蒙社区的文章--在 CentOS 中安装鸿蒙 LiteOS 编译环境-海思 Hi3861[8],同样的也只取我需要的--我只需要编译部分的环境搭建。我的云主机操作系统是 CentOS 7.6 64 位,和博主的大同小异,按照文章中的命令行逐个敲完再去编译就一把过。
老话说得好:"If I have seen further, it is by standing upon the shoulders of giants",于是我结合许老师和社区文章完成了 HarmonyOS 在 CentOS 上的编译环境搭建。
2.1 源码获取(可自行获取)
# 配置repo工具 mkdir ~/bin/ # sudo apt install curl # 如果没有curl命令需要先下载 curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > ~/bin/repo chmod +x ~/bin/repo echo 'export PATH=~/bin:$PATH' >> ~/.bashrc source ~/.bashrc2.2 安装编译基础环境
依赖 Python 3.7+ 以及SCons[9]安装,我这里通过自行编译安装的 Python 3.9.0。
# 下载Python源码包 wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz # 解压源码包 tar -xzvf Python-3.9.0.tgz # 安装依赖 yum groupinstall -y "Development tools" yum install -y openssl-devel yum install -y libffi libffi-devel yum install -y bzip2-devel yum install -y sqlite-devel yum install -y readline-devel yum install -y libuuid-devel yum install -y uuid-devel yum install -y xz-devel yum install -y gdbm-devel yum install -y tk-devel # 配置编译 cd Python-3.9.0 ./configure --prefix=/usr/local/python3 # 编译Python make -j8 && make install # 创建软链接 ln -s /usr/local/python3/bin/python3 /usr/bin/python3 ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3 # 验证 python3 --version pip3 --version # 安装编译时需依赖的Python 3组件 pip3 install setuptools pip3 install kconfiglib pip3 install pycryptodome pip3 install six --upgrade --ignore-installed six pip3 install ecdsa2.3 安装编译工具环境
我们需要用到的编译工具有交叉编译器 gcc_riscv32、 产生 ninja 编译脚本的 gn、执行 ninja 编译脚本的 ninja,虽然我并不知道她们是怎么工作的,但我坚信“Just Do IT”!
# 下载交叉编译工具 wget https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz # 解压工具链 tar -xvf gcc_riscv32-linux-7.3.0.tar.gz # 安装交叉编译工具 mv gcc_riscv32 /usr/local/ # 按照个人喜好存放 vi /etc/profile # 将环境变量配置进来export PATH=/usr/local/gcc_riscv32/bin:$PATH # 如果已存在PATH,需将:/usr/local/gcc_riscv32/bin:$PATH 追加到PATH source /etc/profile # 如果还是不生效,请尝试加到全局变量 vim ~/.bashrc 我这边就酱 # 验证 cd riscv32-unknown-elf-gcc --version2.4 编译测试
通过简单而又繁琐的 Ctrl C 和 Ctrl V 我们终于完成了 HarmonyOS Device 用于编译的 Linux 环境搭建。我已经迫不及待地想编译一次试试:
cd /root/harmonyos/openharmony python3 build.py wifiiot至此,完整的 HarmonyOS Device 环境算是搭建完毕,我们可以开始编写自己的程序进行编译、烧录了。接下来,我们尝试从 Hi3861 套件的一些基本功能中了解 HarmonyOS Device 的开发调试。
开发调试篇
具体的文档和教程请参考 HarmonyOS 官方文档以及厂商的开源教程如 HiHope 的《Harmony OS 物联网应用开发实战》配套视频和代码仓库、BearPi 的《HM Nano 鸿蒙·季 发布》配套视频及代码仓库。我们使用的是 HiHope 出品的 WI-FI IoT Hi3861 套件,涵盖了一个核心板(Hi3861 WLAN 模组)和七个扩展模块(交通灯板、炫彩灯板、OLED 板、NFC 板、机器人扩展板),包含了丰富的外设接口如 I2C(The Inter Integrated Circuit)、PWM(Pulse Width Modulation)、GPIO(General Purpose Input/Output)和多路 ADC(Analog to Digital Converter)等等,可玩性非常高。鸿蒙社区也有很多牛人创造了超多创意玩法,比如通过蜂鸣器演奏乐曲、通过 OLED 播放视频、俄罗斯方块小游戏、控制大疆无人机……您是不是也想来一套?接下来,请跟随 Copy 攻城狮本大狮一起探索一下 HarmonyOS Devic 开发调试吧!
3.1 从点灯开始
如果您留意到 HarmonyOS Device 官方文档中关于 Hi3861 的示例程序,除了“Hello,World”和 WLAN 模组联网,在设备开发章节还提供了一个 LED 外设控制的 Demo,通过调用 HarmonyOS 的 NDK 接口,实现对 GPIO 控制,达到 LED 闪烁的效果,也就是我们常说的“点灯”。源代码在我们下载的目录中:`harmonyos/openharmony/applications/sample/wifi-iot/app/iothardware/led_example.c`[10]。 在 Copy 代码之前,大概了解一下源码的目录:
. ├── applications # 应用程序样例,包括wifi-iot,camera等 │ └── sample │ ├──── camera # 摄像头类产品 │ └──── wifi-iot # WIFI连接类产品 ├── base # 基础软件服务子系统集&硬件服务子系统集 ├── build # 组件化编译、构建和配置脚本 │ └── lite ├── build.py # 编译脚本文件 ├── device # qemu模拟不同内核运行在不同的单板 ├── docs # OpenHarmony开发者文档 ├── domains # 增强软件服务子系统集 │ └── iot ├── drivers # 驱动子系统 │ ├── hdf │ └── liteos ├── foundation # 系统基础能力子系统集 ├── kernel # 内核子系统 ├── out # 编译输出 │ └── wifiiot # python3 build.py wifiiot的产物 ├── prebuilts # 编译器及工具链子系统 ├── test # 测试子系统 ├── third_party # 开源第三方组件 ├── utils # 常用的工具集 └── vendor # 厂商提供的软件 ├── hisi └── huawei再看看我们的开发目录applications/sample/wifi-iot:
├── app │ ├── BUILD.gn # 入口 │ ├── demolink # Hello,World │ │ ├── BUILD.gn │ │ └── helloworld.c │ ├── iothardware # 点灯Demo │ │ ├── BUILD.gn │ │ └── led_example.c │ ├── samgr # 服务框架子系统管理系统功能 │ │ ├── bootstrap_example.c │ │ ├── broadcast_example.c │ │ ├── BUILD.gn │ │ ├── example.h │ │ ├── feature_example.c │ │ ├── maintenance_example.c │ │ ├── service_example.c │ │ ├── service_recovery_example.c │ │ ├── specified_task_example.c │ │ └── task_example.c │ └── startup # 启动配置 │ └── BUILD.gn └── LICENSE # 许可证根据现有的代码,要想完成“点灯”实践,我们只需在 VSCode Remote 中修改入口文件BUILD.gn:
import("//build/lite/config/component/lite_component.gni") lite_component("app") { features = [ "iothardware:led_example" ] }然后新开一个 VSCode 窗口进行 DevEco Device Tool 配置及烧录,烧录完毕通过串口工具能查看开发板的输出,再 Reset 开发板之后,伴随着节奏声,LED 灯一闪一闪,有点转向灯的赶脚,按下左边按钮时提示闪烁。
为了简化操作,我安装了串口调试工具 sscom,因此在每次烧录前我先在 sscom 中关闭串口,烧录完毕之后,我就在 sscom 中打开串口,方便的点在于不必每次都输入串口,在发送操作指令时也更加快捷。值得注意的是烧录时一定要先关闭被占用的串口,不然会提示串口繁忙而无法正常烧录。
这里的点灯 Demo 通过 GPIO(General-purpose input/output,通用型输入输出)实现,同样的还可以实现交通灯板上的“红黄绿”LED 及蜂鸣器的操作,我们实现蜂鸣器版的《Jingle Bells》也基于 GPIO。
3.2 走向 Copy 之路
在万物互联的世界里,传感器承担了绝大部分的数据采集工作,在 WIFI-IoTHi3861 套件中的炫彩灯板包含了光敏、人体红外,环境检测板包含了温湿度传感器、燃气传感器。这部分主要涉及到 ADC 和 I2C,因此我们在进行传感器应用开发的时候,需要特别留意公共基础库中的wifiiot_adc.h和wifiiot_i2c.h,文件均位于[openharmony/base/iot_hardware/interfaces/kits/wifiiot_lite](https://gitee.com/openharmony/iothardware_interfaces_kits_wifiiot_lite "openharmony/base/iot_hardware/interfaces/kits/wifiiot_lite")目录下.另外就是如果使用了外设接口编译的时候要注意对应的配置是否已经设置正常,比如我用到了 I2C,那么在编译配置文件vendor\hisi\hi3861\hi3861\build\config\usr_config.mk中,我就需要将# CONFIG_I2C_SUPPORT is not set修改为CONFIG_I2C_SUPPORT=y……当然一开始我是不知道这些“门道”的,直到我在 HarmonyOS Device 开发中又走向了 Copy 之路,这条道也许永远难回头。我就像这些传感器,在既定的程序里采集“知识”……
秉着学习的态度,我直接 clone 的 HiHope 的仓库到我的harmonyos/openharmony目录中,当然,既然是 Copy,我一定会按照LICENSE的规则使用,万一没遵守也是仅个人学习使用,应该不会被“谴责”[11]吧。请开始 Copy 吧:
cd /root/harmonyos/openharmony/applications/sample/wifi-iot git clone https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development.git mv HarmonyOS-IoT-Application-Development/* ./于是乎,在司职前端开发的 Copy 攻城狮的票圈又多了些物联网开发的动态,“外行看热闹,内行看笑话”,不过扪心自问,这样的 Copy,我还是非常乐意尝试--零基础也能玩玩,真好!一顿 Copy 操作下来,我便开始尝试编译烧录每一个 Demo,尽管代码看的吃力(我是太白),但一些关键的代码还是能够勉强修改,比如“1 改为 2”……总体来说,我体验到了动手实践的乐趣。尤其是看到蜂鸣器版的《两只老虎》,我瞬间想到了那年平安夜,在陌生的城市,深夜加班之后,路灯下自己的影子被拉得长长的,我和往常一样扫了一辆共享单车,锁开的那一瞬间,音乐响起来的……
实战应用篇
说回我们今天的主要任务--蜂鸣器版的《Jingle Bells》。小的时候我们学过“声音是一种波。可以被人耳识别的声(频率在 20 Hz~20000 Hz 之间),我们称之为声音”。那声音的频率和我们听到的音调又有什么关系呢?刚好我找到了它--每个人都应该了解的音乐理论, 从表格中可以看出,“几”字型方向声音频率逐渐增大,我们听到的“哆唻咪”差不多是表中的“1046.50,1174.66,1318.51”。
在我所使用的 WIFI-IoT 套件中的蜂鸣器要想输出相同的频率,需要使用 PWM 接口来控制。根据社区大佬们的实测,通过hi_pwm_set_clock(PWM_CLK_XTAL);可以将时钟源设置为晶体时钟且时钟频率为 40MHz。根据 PWM 输出的方波频率的公式:
f = Fcs / freq其中,Fcs 是 PWM 时钟源频率,freq 是分频倍数,取值[1~65535];
我们通过简单的换算得出我所用的《铃儿响叮当》简谱中需要的音频:
static const uint16_t g_tuneFreqs[] = { 0, // 40M Hz 对应的分频系数: 38223, // 1046.50 1 34052, // 1174.66 2 30338, // 1318.51 3 28635, // 1396.91 4 25510, // 1567.99 5 22727, // 1760.00 6 40495, // 987.77 7- 36077, // 1108.73 1+ 51021, // 783.99 5- 45455 // 880.00 6- };索引从 0 开始,比如"1,2,3,4,5,6"分别对应”哆来咪发嗦啦“,因此简谱中的音符对应进来就如下图所示了:
当然要想出色的演奏,我们还需要掌握一定的节奏,不然都是一个节拍,平平淡淡没有跌宕起伏的感觉,怎么体现咱 Copy 攻城狮的人生历程呢?关于节拍,我简单做了总结,简谱中常见的节拍有下面几个,套用在代码里面就是停顿时间:
整明白这些之后,开始编(kao)程(bei),其核心实践如下:
# 音乐处理 static void *BeeperMusicTask(const char *arg) { (void)arg; printf("BeeperMusicTask start!\r\n"); hi_pwm_set_clock(PWM_CLK_XTAL); // 设置时钟源为晶体时钟(40MHz,默认时钟源160MHz) for (size_t i = 0; i < sizeof(g_scoreNotes)/sizeof(g_scoreNotes[0]); i++) { uint32_t tune = g_scoreNotes[i]; // 音符 uint16_t fre = g_tuneFreqs[tune]; uint32_t tuneInterval = g_scoreDurations[i] * (125*1000); // 音符时间 printf("%d %d %d %d\r\n", tune, (40*1000*1000) / fre, fre, tuneInterval); PwmStart(WIFI_IOT_PWM_PORT_PWM0, fre/2, fre); usleep(tuneInterval); PwmStop(WIFI_IOT_PWM_PORT_PWM0); } return NULL; }整完就是一顿编译、烧录,一套下来按下 Reaset 就崩出了那个似曾相识的声音:"Jingle bells, jingle bells,ingle all the way……"
突然又一个想法冒出来了:”八音盒“是不是可以整了?服务端提供音乐数据,Hi3861的通过请求网络获取数据,蜂鸣器演奏,然后OLED屏显示当前播放,再给交通灯板的按键加上功能,是不是齐活了~
后记
心心念念终于撸完这篇了,本来以为几个小时就能搞定的,结果一搞就是一个周末。最近发现效率太低了,有很多文章很多题材想写,也有很多事情要完成,却总是发现没时间,时间都去哪儿了?之前没在 CentOS 上搭这套环境,知道写文章的时候才发现同样是 Linux,CentOS 和 Ubuntu 还是有些差异的,幸好有坑也爬出来了,关键在于前人的经验分享。因此,希望此篇能给入门HarmonyOS的新人有所启发。
不算彩蛋的祝福:剩蛋快乐,新年快乐!
B站链接:https://www.bilibili.com/video/BV1X64y1f7j1#reply3814070004
标签组:[linux系统] [编译程序] [install] [android源码编译] [vscode] [python3] [yum]