详解Node.js API系列C/C++ Addons(4) Javascript也能搞嵌入式?

释放双眼,带上耳机,听听看~!

回忆一下,我们已经完成了addon的相关学习了
详解Node.js API系列C/C++ Addons(1) API文档
详解Node.js API系列C/C++ Addons(2) Google V8引擎
详解Node.js API系列C/C++ Addons(3) 程序实例

利用这些知识,让我们做一些疯狂的事情吧,
利用Node.js控制嵌入式系统硬件。

工作原理

利用Node.js的Addon模块作为调用硬件控制C库的中间件,Node.js异步的特性,非常适合处理各种硬件的IO。本次实践使用的是cubieboard的开发板,Node.js将会控制板子的GPIO的PD0,让它1000ms产生一个高低电平,使LED灯能够一闪一闪的样子。

执行代码

vi run.js


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1var GPIO = require('./build/Release/gpio');
2
3var LED = GPIO.PD0;
4var status = 0;
5GPIO.init();
6
7GPIO.setcfg(LED, GPIO.OUT);
8
9// 让led 一闪一闪
10var blink = function(){
11    if(status){
12        GPIO.output(LED, GPIO.LOW);
13        status = 0;
14    } else {
15        GPIO.output(LED, GPIO.HIGH);
16        status = 1;
17    }
18}
19
20setInterval(blink, 1000);
21

vi gpio.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
1#include <node.h>
2// 调用cubieboard的硬件控制库
3extern "C"{
4#include "gpio_lib.h"
5}
6// 定义一些工具宏
7#define WIRING_DEFINE_CONSTANT(NAME, VALUE) (target)->Set( \
8        v8::String::NewSymbol(NAME), \
9        v8::Integer::New(VALUE), \
10        static_cast<v8::PropertyAttribute>(v8::ReadOnly|v8::DontDelete) \
11);
12#define PD0 SUNXI_GPD(0)
13using namespace v8;
14// 初始化gpio的寄存器
15Handle<Value> GPIO_init(const Arguments& args) {
16    HandleScope scope;
17    int32_t result;
18    result = sunxi_gpio_init();
19    if(result == SETUP_DEVMEM_FAIL){
20    return ThrowException(
21            Exception::TypeError(String::New("SETUP_DEVMEM_FAIL Error"))
22        );
23    }
24    if(result == SETUP_MALLOC_FAIL){
25        return ThrowException(
26            Exception::TypeError(String::New("SETUP_MALLOC_FAIL Error"))
27        );
28    }
29    if(result == SETUP_MMAP_FAIL){
30        return ThrowException(
31            Exception::TypeError(String::New("SETUP_MMAP_FAIL Error"))
32        );
33    }
34    return scope.Close(Integer::New(SETUP_OK));
35}
36Handle<Value> GPIO_cleanup(const Arguments& args) {
37    HandleScope scope;
38    sunxi_gpio_cleanup();
39    return scope.Close(Undefined());
40}
41// 获取引脚当状态 IN,OUT,PRE?
42Handle<Value> GPIO_getcfg(const Arguments& args) {
43    HandleScope scope;
44
45    if (args.Length() < 1){
46        return ThrowException(
47            Exception::TypeError(String::New("Wrong number of arguments"))
48        );
49    }
50    if (!args[0]->IsNumber()){
51        return ThrowException(
52             Exception::TypeError(String::New("Wrong arguments"))
53        );
54    }
55    int32_t result;
56    int32_t gpio = args[0]->ToInteger()->Value();
57    result = sunxi_gpio_get_cfgpin(gpio);
58    return scope.Close(Integer::New(result));
59}
60// 读取的电平状态 HIGH?LOW?
61Handle<Value> GPIO_input(const Arguments& args) {
62    HandleScope scope;
63    if (args.Length() < 1){
64        return ThrowException(
65            Exception::TypeError(String::New("Wrong number of arguments"))
66        );
67    }
68    if (!args[0]->IsNumber()){
69        return ThrowException(
70             Exception::TypeError(String::New("Wrong arguments"))
71        );
72    }
73    int32_t result;
74    int32_t gpio = args[0]->ToInteger()->Value();
75    result = sunxi_gpio_input(gpio);
76    if(result == -1){
77        return ThrowException(
78             Exception::TypeError(String::New("Reading pin failed"))
79        );
80    }
81    return scope.Close(Integer::New(result));
82}
83
84// 输出电平
85Handle<Value> GPIO_output(const Arguments& args) {
86    HandleScope scope;
87    if (args.Length() < 2){
88        return ThrowException(
89            Exception::TypeError(String::New("Wrong number of arguments"))
90        );    
91    }
92    if (!args[0]->IsNumber() || !args[1]->IsNumber()){
93        return ThrowException(          
94         Exception::TypeError(String::New("Wrong arguments"))
95        );
96    }
97    int32_t gpio = args[0]->ToInteger()->Value();
98    int32_t value = args[1]->ToInteger()->Value();
99    if( value != 0 && value != 1) {
100        return ThrowException(                        
101         Exception::TypeError(String::New("Invalid output state"))
102        );
103    }
104    if(sunxi_gpio_get_cfgpin(gpio) != SUNXI_GPIO_OUTPUT) {
105    return ThrowException(
106             Exception::TypeError(String::New("Invalid output state"))
107        );
108    }
109    sunxi_gpio_output(gpio, value);
110    return scope.Close(Undefined());
111}
112// 设置GPIO功能 IN?OUT?PRE?
113Handle<Value> GPIO_setcfg(const Arguments& args) {
114    HandleScope scope;
115    if (args.Length() < 2){
116        return ThrowException(
117            Exception::TypeError(String::New("Wrong number of arguments"))
118        );
119    }
120    if (!args[0]->IsNumber() || !args[1]->IsNumber()){
121        return ThrowException(
122             Exception::TypeError(String::New("Wrong arguments"))
123        );
124    }
125    int32_t gpio = args[0]->ToInteger()->Value();
126    int32_t direction = args[1]->ToInteger()->Value();
127    if(direction != 0 && direction != 1 && direction != 2) {
128        return ThrowException(
129             Exception::TypeError(String::New("Invalid direction"))
130        );
131    }
132    sunxi_gpio_set_cfgpin(gpio, direction);
133    return scope.Close(Undefined());
134}
135void RegisterModule(Handle<Object> target) {
136    NODE_SET_METHOD(target, "init", GPIO_init);
137    NODE_SET_METHOD(target, "cleanup", GPIO_cleanup);
138    NODE_SET_METHOD(target, "output", GPIO_output);
139    NODE_SET_METHOD(target, "setcfg", GPIO_setcfg);
140    NODE_SET_METHOD(target, "input", GPIO_input);
141    NODE_SET_METHOD(target, "getcfg", GPIO_getcfg);
142    WIRING_DEFINE_CONSTANT("HIGH", HIGH)
143    WIRING_DEFINE_CONSTANT("LOW", LOW)
144    WIRING_DEFINE_CONSTANT("PD0", PD0)
145    WIRING_DEFINE_CONSTANT("IN", INPUT)
146    WIRING_DEFINE_CONSTANT("OUT", OUTPUT)
147    WIRING_DEFINE_CONSTANT("PER", PER)
148}
149NODE_MODULE(gpio, RegisterModule);
150

vi binding.gyp


1
2
3
1{
2  "targets": [ { "target_name": "gpio", "include_dirs": ["lib"], "sources": [ "gpio.cpp", "lib/gpio_lib.c", "lib/gpio_lib.h" ] } ] }
3

测试

利用万用表对准 GND 和 PD0,可以发现程序运行后,电压3V – 0V 每隔1000ms产生一次变化,如果接上LED,LED就会一闪一闪的样子。打算去买一块面包板,演示一下。

视频 演示

http://v.youku.com/v_show/id_XNjA5MzI0OTQ0.html

项目地址:https://github.com/youyudehexie/node-cubieboard-gpio

给TA打赏
共{{data.count}}人
人已打赏
安全技术

DES 加密 解密

2021-8-18 16:36:11

安全技术

C++ 高性能服务器网络框架设计细节

2022-1-11 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索