【工作筆記】IOT.js適配AWorks平臺通用外設(shè)接口(1):ADC

一柿隙、前言

近期因工作需求學(xué)習(xí)了一下 IOT.js 和 AWorks 平臺通用外設(shè)接口(包括:ADC骑疆、GPIO、I2C许布、PWM兴革、SPI 和 UART),并將它們逐一適配到 IOT.js 中蜜唾,為后續(xù) AWTK-MVMM 的 JS項目支持平臺外設(shè)調(diào)用奠定基礎(chǔ)杂曲,此處做筆記記錄一下。

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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末期吓,一起剝皮案震驚了整個濱河市早歇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌讨勤,老刑警劉巖箭跳,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異潭千,居然都是意外死亡谱姓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門脊岳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逝段,“玉大人,你說我怎么就攤上這事割捅。” “怎么了帚桩?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵亿驾,是天一觀的道長。 經(jīng)常有香客問我账嚎,道長莫瞬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任郭蕉,我火速辦了婚禮疼邀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘召锈。我一直安慰自己旁振,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拐袜,像睡著了一般吉嚣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹬铺,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天尝哆,我揣著相機與錄音,去河邊找鬼甜攀。 笑死秋泄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的规阀。 我是一名探鬼主播印衔,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼姥敛!你這毒婦竟也來了奸焙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤彤敛,失蹤者是張志新(化名)和其女友劉穎与帆,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體墨榄,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡玄糟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了袄秩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阵翎。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖之剧,靈堂內(nèi)的尸體忽然破棺而出郭卫,到底是詐尸還是另有隱情,我是刑警寧澤背稼,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布贰军,位于F島的核電站,受9級特大地震影響蟹肘,放射性物質(zhì)發(fā)生泄漏词疼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一帘腹、第九天 我趴在偏房一處隱蔽的房頂上張望贰盗。 院中可真熱鬧,春花似錦阳欲、人聲如沸舵盈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽书释。三九已至翘贮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間爆惧,已是汗流浹背狸页。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扯再,地道東北人芍耘。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像熄阻,于是被迫代替她去往敵國和親斋竞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容