一柿隙、前言
近期因工作需求學(xué)習(xí)了一下 IOT.js 和 AWorks 平臺通用外設(shè)接口(包括:ADC骑疆、GPIO、I2C许布、PWM兴革、SPI 和 UART),并將它們逐一適配到 IOT.js 中蜜唾,為后續(xù) AWTK-MVMM 的 JS項目支持平臺外設(shè)調(diào)用奠定基礎(chǔ)杂曲,此處做筆記記錄一下。
- 【工作筆記】IOT.js適配AWorks平臺通用外設(shè)接口(1):ADC袁余;
- 【工作筆記】IOT.js適配AWorks平臺通用外設(shè)接口(2):GPIO擎勘;
- 【工作筆記】IOT.js適配AWorks平臺通用外設(shè)接口(3):I2C;
- 【工作筆記】IOT.js適配AWorks平臺通用外設(shè)接口(4):PWM颖榜;
- 【工作筆記】IOT.js適配AWorks平臺通用外設(shè)接口(5):SPI棚饵;
- 【工作筆記】IOT.js適配AWorks平臺通用外設(shè)接口(6):UART;
1.1 IOT.js
IOT.js 是三星開源的 JavaScript 物聯(lián)網(wǎng)開發(fā)平臺掩完。它為
JavaScript 應(yīng)用程序提供了訪問硬件噪漾、網(wǎng)絡(luò)、文件系統(tǒng)和異步化的能力且蓬,功能類似于 nodejs欣硼,但無論是代碼體積還是內(nèi)存需求,IOT.js 都要小很多恶阴,是用 JavaScript 開發(fā) IOT 設(shè)備應(yīng)用程序的首選诈胜。
備注: IOT.js 的 GitHub 倉庫:https://github.com/jerryscript-project/iotjs豹障。
1.2 AWorks
AWorks 是 ZLG 開發(fā)的 IOT 物聯(lián)網(wǎng)生態(tài)系統(tǒng),將MCU和OS的共性高度抽象為統(tǒng)一接口焦匈,支持平臺組件“可插拔沼填、可替換、可配置”括授,與硬件無關(guān)坞笙、與操作系統(tǒng)種類無關(guān)的方式設(shè)計,只需修改相應(yīng)的頭文件荚虚,即可實現(xiàn)“一次編程薛夜、終生使用、跨平臺”版述。
我們這里主要使用 AWorks M1052 開發(fā)板作為測試設(shè)備適配常見外設(shè)接口梯澜。
[圖片上傳失敗...(image-a78d96-1651554855179)]
二、A/D轉(zhuǎn)換器
2.1 模數(shù)信號轉(zhuǎn)換
ADC 即模擬信號轉(zhuǎn)數(shù)字信號渴析,我們經(jīng)常接觸的噪聲和圖像信號都是模擬信號晚伙,要將模擬信號轉(zhuǎn)換為數(shù)字信號,必須經(jīng)過采樣俭茧、保持咆疗、量化和編碼幾個過程。AWorks提供了A/D轉(zhuǎn)換接口母债,可以直接通過接口獲取相應(yīng)引腳輸入的模擬電壓大小午磁。
2.2 A/D 轉(zhuǎn)換接口
AWorks提供了的A/D轉(zhuǎn)換接口分為 3 大類:基礎(chǔ)配置接口、獲取采樣值接口(同步方式)和獲取采樣值接口(異步方式)毡们。
基礎(chǔ)配置接口:
- aw_adc_rate_get:獲取ADC通道的采樣率迅皇。
- aw_adc_rate_set:設(shè)置ADC通道的采樣率。
- aw_adc_vref_get:獲取基準(zhǔn)電壓衙熔。
- aw_adc_bits_get:獲取ADC通道的轉(zhuǎn)換位數(shù)登颓。
獲取采樣值接口(同步方式):
- aw_adc_sync_read:讀取指定通道的采樣值。
備注:這里的JS異步接口的適配主要是借助 IoT.js 中的 libtuv 實現(xiàn)红氯,因此就不詳細介紹AWorks提供的異步接口了框咙。
三、適配過程
3.1 AWorks演示代碼
首先來看看在AWorks上如何讀取指定ADC引腳的采樣數(shù)據(jù)脖隶。
步驟一:外設(shè)使能扁耐,在AWorks工程配置文件 aw_prj_params.h
中開啟以下宏定義使能對應(yīng)的ADC設(shè)備:
#define AW_DEV_IMX1050_ADC1 /**< \brief iMX1050 ADC */
步驟二:到外設(shè)文件中查看設(shè)備對應(yīng)的引腳,比如這里查看 awbl_hwconf_imx1050_adc1.h
文件产阱,找到 ADC1 設(shè)備通道 0 所對應(yīng)的引腳為 GPIO1_27婉称,通過查閱硬件設(shè)計圖得知該引腳在底板中絲印為串口8的RX,因此這里我們需要關(guān)閉串口8的功能,避免引腳復(fù)用的情況王暗。
步驟三:編寫例程悔据,首先定義 ADC 通道號和采樣次數(shù),之后讀取通道的 AD 值并將 AD 值轉(zhuǎn)換為電壓值打印顯示俗壹,循環(huán)操作科汗。示例代碼如下:
#include "aw_adc.h"
#define N_SAMPLES 1 //定義采樣次數(shù)為1次
#define CHANNEL 0 //轉(zhuǎn)換通道為通道0
int main()
{
uint16_t adc_val[N_SAMPLES]; /* ADC值 */
uint32_t vol_val[N_SAMPLES]; /* 電壓值 */
aw_err_t ret;
int i;
/* ADC值清0 */
memset(adc_val, 0, sizeof(adc_val));
/* 讀取通道的AD值 */
ret = aw_adc_sync_read(CHANNEL, adc_val, N_SAMPLES, FALSE);
if (ret != AW_OK) {
aw_kprintf("read fail\r\n");
} else {
aw_kprintf("read success\r\n");
}
/* 轉(zhuǎn)換為實際電壓值 */
aw_adc_val_to_mv(CHANNEL, adc_val, N_SAMPLES, vol_val);
/* 打印采樣值 */
for (i = 0; i < N_SAMPLES; i++) {
aw_kprintf("%d ", vol_val[i]);
}
return 0;
}
我們將底板上的 3.3V 電壓引腳與 RX8 短接,輸出結(jié)果如下:
read success
3300
備注:
aw_adc_val_to_mv
轉(zhuǎn)換接口得到的采樣值單位為 mv绷雏。
3.2 C語言適配層
在 IOT.js 中头滔,適配某個平臺的外設(shè)通常需要實現(xiàn) src/modules/iotjs_module_xxx.h
文件中的接口,比如這里我們需要實現(xiàn) iotjs_module_adc.h
中的相關(guān)接口:
#ifndef IOTJS_MODULE_ADC_H
#define IOTJS_MODULE_ADC_H
#include "iotjs_def.h"
#include "iotjs_module_periph_common.h"
// Forward declaration of platform data. These are only used by platform code.
// Generic ADC module never dereferences platform data pointer.
typedef struct iotjs_adc_platform_data_s iotjs_adc_platform_data_t;
typedef struct {
jerry_value_t jobject;
iotjs_adc_platform_data_t* platform_data;
int32_t value;
} iotjs_adc_t;
bool iotjs_adc_read(iotjs_adc_t* adc);
bool iotjs_adc_close(iotjs_adc_t* adc);
bool iotjs_adc_open(iotjs_adc_t* adc);
// Platform-related functions; they are implemented
// by platform code (i.e.: linux, nuttx, tizen).
void iotjs_adc_create_platform_data(iotjs_adc_t* adc);
void iotjs_adc_destroy_platform_data(iotjs_adc_platform_data_t* platform_data);
jerry_value_t iotjs_adc_set_platform_config(iotjs_adc_t* adc,
const jerry_value_t jconfig);
#endif /* IOTJS_MODULE_ADC_H */
適配層(src/modules/aworks/iotjs_module_adc-aworks.c
)代碼如下:
#if !defined(WITH_AWORKS)
#error "Module __FILE__ is for AWorks only"
#endif
#include "iotjs_def.h"
#include "aw_adc.h"
#include "modules/iotjs_module_adc.h"
struct iotjs_adc_platform_data_s {
uint32_t channel;
};
/* ADC通道 */
#define AWORKS_ADC_STRING_CHANNEL "channel"
/* 采樣次數(shù) */
#define AWORKS_ADC_SAMPLES_NUM 1
void iotjs_adc_create_platform_data(iotjs_adc_t* adc) {
adc->platform_data = IOTJS_ALLOC(iotjs_adc_platform_data_t);
adc->platform_data->channel = 0;
}
void iotjs_adc_destroy_platform_data(iotjs_adc_platform_data_t* platform_data) {
IOTJS_RELEASE(platform_data);
}
jerry_value_t iotjs_adc_set_platform_config(iotjs_adc_t* adc,
const jerry_value_t jconfig) {
JS_GET_REQUIRED_CONF_VALUE(jconfig, adc->platform_data->channel,
AWORKS_ADC_STRING_CHANNEL, number);
return jerry_create_undefined();
}
bool iotjs_adc_read(iotjs_adc_t* adc) {
uint32_t ch = adc->platform_data->channel;
int bits = aw_adc_bits_get(ch);
if (bits > 0) {
/* 儲存ADC值的緩沖區(qū)實際類型與ADC位數(shù)相關(guān) */
/* 1~8位:類型為 uint8_t */
/* 9~16位:類型為 uint16_t */
/* 17~32位:類型為 uint32_t */
int multiple = bits > 8 ? (bits > 16 ? 4 : 2) : 1;
char adc_v[AWORKS_ADC_SAMPLES_NUM * multiple]; /* ADC值 */
uint32_t vol_v[AWORKS_ADC_SAMPLES_NUM]; /* 電壓值 */
memset(adc_v, 0x00, sizeof(adc_v));
memset(vol_v, 0x00, sizeof(vol_v));
/* 讀取通道的AD值 */
if (aw_adc_sync_read(ch, (void*)adc_v, AWORKS_ADC_SAMPLES_NUM, AW_FALSE) <
0) {
return false;
}
/* 轉(zhuǎn)換為實際電壓值涎显,單位為:mV */
if (aw_adc_val_to_mv(ch, (void*)adc_v, AWORKS_ADC_SAMPLES_NUM, vol_v) < 0) {
return false;
}
adc->value = (int32_t)(*vol_v);
return true;
}
return false;
}
bool iotjs_adc_close(iotjs_adc_t* adc) {
return true;
}
bool iotjs_adc_open(iotjs_adc_t* adc) {
iotjs_adc_platform_data_t* platform_data = adc->platform_data;
int bits = aw_adc_bits_get(platform_data->channel);
int vref = aw_adc_vref_get(platform_data->channel);
// 檢查AWorks上對應(yīng)的ADC通道是否可用
if (bits < 0 || vref < 0) {
return false;
}
return true;
}
3.3 JS測試代碼
適配好后坤检,我們編寫 JS 代碼測試一下,此處同樣將底板上的 3.3V 引腳與 RX8 短接:
var adc = require('adc'); /* 導(dǎo)入adc模塊 */
var value = -1;
var configuration = {
channel: 0 /* 設(shè)置通道0 */
};
adcObj = adc.openSync(configuration);
console.log('ADC initialized');
value = adcObj.readSync();
console.log(value, 'mV');
adcObj .closeSync();
輸出結(jié)果:
ADC initialized
3300mV