• Home
Name Date Size #Lines LOC

..--

DevEcoStudioProjects/12-May-2024-1,064855

figures/12-May-2024-

README.mdD12-May-202412.6 KiB411389

README.md

1# 一、**样例介绍**
2
3基于OpenHarmony NAPI框架和HDF框架实现控制设备端扩展板GPIO的LED灯的控制效果app
4
5## 1.1app页面效果
6![image](figures/UI.PNG)
7## 1.2app演示
8<a id="demo">演示目录</a>
9
10[1.选择并实时更新](#select)
11[2.开关灯(点个与全部)](#openClose)
12[3.闪烁效果和中断](#sparkle)
13[4.射点效果](#flow1)
14[5.波动效果](#flow2)
15[6.随机效果](#random)
16
17## 1.3app功能
181.gpio开关灯
192.可选择开关灯的灯号、延时、次数
203.有特殊效果:射点、波浪、随机、闪烁
214.可随时中断效果
225.实时同步显示状态
23
24
25
26# 二、文件说明
27## hcs文件
28在\vendor\unionman\unionpi_tiger\hdf_config\khdf\device_info\device_info.hcs文件里添加下面代码,让HDF的gpio接口可以正常调用
29```
30device_gpio :: device {
31                device0 :: deviceNode {
32                    policy = 2;
33                    priority = 10;
34                    permission = 0644;
35                    moduleName = "HDF_PLATFORM_GPIO_MANAGER";
36                    serviceName = "HDF_PLATFORM_GPIO_MANAGER";
37                }
38                device1 :: deviceNode {
39                    policy = 0;
40                    priority = 10;
41                    permission = 0644;
42                    moduleName = "linux_gpio_adapter";
43                    deviceMatchAttr = "linux_gpio_adapter";
44                }
45            }
46```
47\vendor\unionman\unionpi_tiger\hdf_config\khdf\hdf.hcs文件里添加
48```
49#include "device_info/device_info.hcs"
50```
51## c/c++文件
52本项目使用的是unionpi_tiger\sample\napi\napisubsys\gpio_hdf目录下的c/c++文件
53主要文件包含:
54gpio_hdf.cpp ———— HDF接口处理业务逻辑和注册NPAPI驱动
55BUILD.gn ———— ohos_shared_library编译成so文件
56<br></br>
57本项目用到的HDF接口函数为
58```
59GpioSetDir(gpioNum, direction);
60GpioSetDir(gpioNum, direction);
61GpioRead(gpioNum, &getValue);
62```
63## ts文件
64本项目使用的是unionpi_tiger\sample\napi\napisubsys目录下的@ohos.gpio_hdf.d.ts文件
65编写接口定义@ohos.**nameX**.d.ts文件,放到OpenHarmony SDK目录ets\\${ets_version}\\api目录下。使用SDK 8则${ets_version}为3.1.6.6,SDK 7则为3.0.0.0。
66
67## so文件
68本地编译输出到out\\${device}\\lib.unstripped文件夹,,命名规则为lib**nameX**.z.so,**nameX**与ohos_shared_library中的命名有关
69可通过打包镜像img烧录到开发板上,若已经烧录过系统,可直接通过串口传输工具或者u盘等传输方式来发送so文件,复制so文件到系统下/system/lib/module/中
70注意@ohos.**nameX**必须和NAPI模块的BUILD.gn文件中ohos_shared_library("**nameX**")指定的动态库名一致。
71
72## 整体思路
73![image](figures/flowChart%20(1).png)
74
75# 四、编写app
76## 查看gpioNum
77进入到hdc_std.exe目录打开cmd
78```
79hdc_std.exe shell
80```
81若想查看gpioNum可执行下面代码进行查看
82```
83cd sys/kernel/debug
84cat gpio
85```
86![image](figures/1.PNG)
87## DevEco Studio 引用ts文件
88```
89import prompt from '@ohos.prompt';
90import gpio_hdf from '@ohos.gpio_hdf';
91```
92## 代码说明
93### 1.数据变量
94```
95data: {
96        pin: 380,                       //pinNum;[380,389]
97        status: [0,0,0,0,0,0,0,0,0,0],  //灯号状态
98        delay: 100,                     //间隔
99        time: 10,                       //次数
100        full: false,                    //是否全选
101        blank: " ",                     //空格
102        timerID1: null,                 //setTimeout返回值
103        timerID2: null,                 //setTimeout返回值
104        type: "无",                      //效果运行类型
105        temp: 0,                        //临时变量
106        isinf: true,                    //是否无穷次数
107    },
108```
109### 2.开启软件执行的函数
110关闭全部灯
111```
112//初始化
113    onInit() {
114        //进入程序灭掉全部灯,保证与初始状态全为0相同
115        for(var i = 380; i <= 389; i++){
116            this.pin = i
117            this.removeLedEffect()//因IDE不能调用接口,使previewer试图变空白,注释掉即可正常预览试图
118        }
119
120    },
121```
122### 3.改变数据变量数值
123```
124
125    //改变gpio口
126    changeGpio(pinNum) {
127        this.full = false
128        this.pin = pinNum + 380
129        prompt.showToast({
130            message: "选择" + this.pin
131        })
132    },
133    //改变间隔时间
134    changeDelay(delay) {
135        this.delay = delay
136        prompt.showToast({
137            message: "选择" + this.delay + "ms"
138        })
139    },
140    //改变次数
141    changeTime(time) {
142        this.isinf = false
143        this.time = time
144        prompt.showToast({
145            message: "选择" + this.time + "次"
146        })
147    },
148    //改变是否全选
149    changeFull() {
150        this.full = true
151        prompt.showToast({
152            message: "全选"
153        })
154    },
155    //改变次数是否无穷
156    changeIsinf() {
157        this.isinf = true
158        prompt.showToast({
159            message: "选择∞"
160        })
161    },
162```
163<a id="select">选择并实时更新</a>
164![image](figures/select.gif)
165[返回演示目录](#demo)
166### 4.开关灯函数
167#### 开灯函数接口执行流程图
168![image](figures/flowChart%20(2).png)
169
170```
171//开灯
172    addLedEffect() {
173        //若全选执行全开灯
174        if(this.full){
175            this.fullAddLedEffect()
176            this.full = true
177        }
178        //单个pin开灯,使用napi接口
179        gpio_hdf.setLedStatus(this.pin, gpio_hdf.LED_ON).then((result) => {
180                if (result === 0) {
181                console.info("Turned on LED." + result)
182                    this.status.splice(this.pin - 380,1,1)  //更新状态
183                    prompt.showToast({
184                        message: "pin."+this.pin+"开灯"
185                    })
186                } else {
187                    console.info("Turned on LED failed." + result)
188                    prompt.showToast({
189                        message: "pin."+this.pin+"开灯失败" + result
190                    })
191                }
192        })
193
194    },
195
196    //关灯
197    removeLedEffect() {
198        //若全选执行全关灯
199        if(this.full){
200            this.fullRemoveLedEffect()
201            this.full = true
202        }
203        //单个pin关灯,使用napi接口
204        gpio_hdf.setLedStatus(this.pin, gpio_hdf.LED_OFF).then((result) => {
205                if (result === 0) {
206                    console.info("Turned off LED." + result)
207                    this.status.splice(this.pin - 380,1,0)  //更新状态
208                    prompt.showToast({
209                        message: "pin."+this.pin+"关灯"
210                    })
211                } else {
212                    console.info("Turned off LED failed." + result)
213                    prompt.showToast({
214                        message: "pin."+this.pin+"关灯失败" + result
215                    })
216                }
217            })
218    },
219    fullAddLedEffect() {
220        for(var i = 0; i <= 9; i++){
221            this.changeGpio(i)
222            this.addLedEffect()
223            this.status.splice(i,1,1)   //更新状态;若删除则只有i = 9更新
224        }
225    },
226    fullRemoveLedEffect() {
227        for(var i = 0; i <= 9; i++){
228            this.changeGpio(i)
229            this.removeLedEffect()
230            this.status.splice(i,1,0)   //更新状态;若删除则只有i = 9更新
231        }
232    },
233```
234<a id="openClose">开关灯(点个与全部)</a>
235![image](figures/openClose.gif)
236[返回演示目录](#demo)
237### 5.中断
238```
239//中断
240    shutdown(){
241        this.type = "无"
242        clearInterval(this.timerID1)
243        clearInterval(this.timerID2)
244        prompt.showToast({
245            message: "关闭程序"
246        })
247    },
248```
249### 6.特殊效果
250#### 函数接口流程图
251sparkle()闪烁函数执行及shutdown()中断过程
252![image](figures/flowChart%20(3).png)
253#### 代码实现
254```
255//效果
256   //效果
257    sparkle(){
258        //清除setTimeout
259        clearInterval(this.timerID1)
260        clearInterval(this.timerID2)
261        /*!this.isinf表示选择的是次数有限
262        当1.次数小于0;2.次数有限;不执行函数*/
263        if(this.time <= 0 && !this.isinf){
264            this.type = "无"
265            prompt.showToast({
266                message: "次数为0"
267            })
268            return
269        }
270        //若不是无穷次数,次数减少1
271        if(!this.isinf){
272            this.time--
273        }
274        //type更新
275        this.type = "闪烁"
276        //执行开灯
277        this.addLedEffect()
278        //delay时间后执行关灯
279        this.timerID1 = setTimeout(() => {
280            this.removeLedEffect()
281        },this.delay)
282        //2 * delay时间后执行递归
283        this.timerID2 = setTimeout(() => {
284            this.sparkle()
285        },this.delay * 2)
286    },
287```
288<a id="sparkle">闪烁特效和中断</a>
289![image](figures/sparkle.gif)
290[返回演示目录](#demo)
291```
292    flow() {
293        //清除setTimeout
294        clearInterval(this.timerID1)
295        clearInterval(this.timerID2)
296        /*!this.isinf表示选择的是次数有限
297        当1.次数小于0;2.次数有限;不执行函数*/
298        if(this.time <= 0 && !this.isinf){
299            this.type = "无"
300            prompt.showToast({
301                message: "次数为0"
302            })
303            return
304        }
305        //若不是无穷次数,次数减少1
306        if(!this.isinf){
307            this.time--
308        }
309        //type更新
310        if(this.type != "射点")   this.temp = 9
311        if(this.type == "射点" && this.temp == -1)   this.temp = 9    //更新temp取代while循环,用if判断变量和递归
312        this.type = "射点"
313        if(this.temp >= 0){
314            this.changeGpio(this.temp)
315            this.addLedEffect()
316            this.timerID1 = setTimeout(() => {
317                this.removeLedEffect()
318            },this.delay)
319            this.timerID2 = setTimeout(() => {
320                this.flow()
321            },this.delay * 2)
322            this.temp--
323        }
324
325
326    },
327```
328
329<a id="flow1">射点效果</a>
330![image](figures/flow1.gif)
331[返回演示目录](#demo)
332
333```
334    flow2() {
335        //清除setTimeout
336        clearInterval(this.timerID1)
337        clearInterval(this.timerID2)
338        /*!this.isinf表示选择的是次数有限
339        当1.次数小于0;2.次数有限;不执行函数*/
340        if(this.time <= 0 && !this.isinf){
341            this.type = "无"
342            prompt.showToast({
343                message: "次数为0"
344            })
345            return
346        }
347        //若不是无穷次数,次数减少1
348        if(!this.isinf){
349            this.time--
350        }
351        //type更新
352        if(this.type != "波浪")   this.temp = 9
353        if(this.type == "波浪" && this.temp == -11)   this.temp = 9   //更新temp取代while循环,用if判断变量和递归
354        this.type = "波浪"
355        if(this.temp >= 0){
356            this.changeGpio(this.temp)
357            this.addLedEffect()
358            this.timerID1 = setTimeout(() => {
359                this.flow2()
360            },this.delay)
361            this.temp--
362        }
363        else{
364            this.changeGpio(this.temp + 10)
365            this.removeLedEffect()
366            this.timerID1 = setTimeout(() => {
367                this.flow2()
368            },this.delay)
369            this.temp--
370        }
371
372
373    },
374```
375<a id="flow2">波动效果</a>
376![image](figures/flow2.gif)
377[返回演示目录](#demo)
378```
379    random() {
380        //清除setTimeout
381        clearInterval(this.timerID1)
382        clearInterval(this.timerID2)
383        /*!this.isinf表示选择的是次数有限
384        当1.次数小于0;2.次数有限;不执行函数*/
385        if(this.time <= 0 && !this.isinf){
386            this.type = "无"
387            prompt.showToast({
388                message: "次数为0"
389            })
390            return
391        }
392        //若不是无穷次数,次数减少1
393        if(!this.isinf){
394            this.time--
395        }
396        this.type = "随机"
397        var i = Math.floor(Math.random()*10)
398        this.changeGpio(i)
399        this.addLedEffect()
400        this.timerID1 = setTimeout(() => {
401            this.removeLedEffect()
402        },this.delay)
403        this.timerID2 = setTimeout(() => {
404            this.random()
405        },this.delay * 2)
406
407    },
408```
409<a id="random">随机效果</a>
410![image](figures/random.gif)
411[返回演示目录](#demo)