自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用SHT3x-DIS溫濕度傳感器的I2C案例

網(wǎng)絡 通信技術(shù)
本文將介紹I2C總線、SHT3x DIS溫度傳感器的相關(guān)知識以及OpenHarmony的HDF驅(qū)動和NAPI框架的使用方法。

??想了解更多關(guān)于開源的內(nèi)容,請訪問:??

??51CTO 開源基礎軟件社區(qū)??

??https://ost.51cto.com??

前言

本文將介紹I2C總線、SHT3x DIS溫度傳感器的相關(guān)知識以及OpenHarmony的HDF驅(qū)動和NAPI框架的使用方法。

一、I2C總線原理

I2C總線是飛利浦公司開發(fā)的一種雙向二線制同步串行總線。只需要兩根線便可在連接于總線上的器件之間進行傳輸信息。I2C通信為點對點通信,存在主設備和從設備之分。主從設備通過兩根線進行通信,其中兩根線分別是SDA和SCL,其中SDA為數(shù)據(jù)線,SCL為時鐘線。

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

主器件用于啟動總線傳送數(shù)據(jù),并產(chǎn)生時鐘以開放傳送的器件,此時任何被尋址的器件均被認為是從器件.在總線上主和從、發(fā)和收的關(guān)系不是恒定的,而取決于此時數(shù)據(jù)傳送方向。如果主機要發(fā)送數(shù)據(jù)給從器件,則主機首先尋址從器件,然后主動發(fā)送數(shù)據(jù)至從器件,最后由主機終止數(shù)據(jù)傳送;如果主機要接收從器件的數(shù)據(jù),首先由主器件尋址從器件.然后主機接收從器件發(fā)送的數(shù)據(jù),最后由主機終止接收過程。在這種情況下,主機負責產(chǎn)生定時時鐘和終止數(shù)據(jù)傳送。

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

通信過程包含應答響應,時鐘同步。傳輸?shù)臄?shù)據(jù)字節(jié)格式有一定要求,每個字節(jié)必須為8位,每次發(fā)送的字節(jié)字數(shù)不受限制,每個字節(jié)后面必須跟一位校驗位。應答響應,數(shù)據(jù)傳輸必須有響應,由主機產(chǎn)生,在響應中發(fā)送器將時鐘線電平被拉高,接收器將電平拉低,保持穩(wěn)定的電壓差;時鐘同步,數(shù)據(jù)傳輸只發(fā)生在時鐘信號的高電平期間,所以需要同步雙方時鐘信號以確保數(shù)據(jù)的準確性;

二、傳感器SHT3X DIS

Sensirion SHT3x-DIS濕度和溫度傳感器基于CMOSens?傳感器芯片,更加智能、可靠,精度更高。SHT3x-DIS具有增強的信號處理能力、兩個獨特的用戶可選I2C地址,通信速度高達1MHz。SHT35-DIS的典型相對濕度 (RH) 精度為±1.5%,典型溫度精度為±0.1°C。SHT3x-DIS具有2.5mm x 2.5mm x 0.9mm(長x寬x高)占位面積,電源電壓范圍為2.4V至5.5V。

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

(1)特性

  • 完全校準、線性化和溫度補償?shù)臄?shù)字輸出
  • I2C接口,通信速度高達1MHz,具有兩個用戶可選地址
  • SHT35的典型精度為+/-1.5% RH和+/-0.1°C
  • 啟動和測量速度極快
  • 2.15V到5.5V的寬電源電壓范圍
  • 小型8引腳DFN封裝

(2)引腳介紹

主要引腳SDA,SCL,VCC,GND。

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

(3) 通信過程

  • 開始測量

在開始測量前,主設備必須先把開始測量的信號發(fā)送到傳感器。發(fā)送的信號被稱為I2C寫入標頭,由7比特的I2C設備地址和一個·0(0表示寫入,1表示讀取),再加上16比特的測量命令構(gòu)成。當傳感器接收到信號時,將會把SDA信號先拉低,響應信號ACK,在第八個時鐘信號下降沿時表示傳感器接收到了主設備的信號,開始測量。

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

  • 模式

傳感器數(shù)據(jù)采集模式多種多樣,我們可以選擇不同的方式進行測量以滿足不同的應用場景,這便是以上提到寫入表頭最后兩位字節(jié)表示的是測量命令,大類分為兩種采集模式。

  • 單次數(shù)據(jù)采集模式

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

  • 周期性數(shù)據(jù)采集模式

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

  • 其它命令

除此之外,傳感器里還設置了其它命令,可在傳感器說明文檔中查看。

  • 數(shù)據(jù)

當測量開始時,主設備便可以接收到信號,而此時標頭要使用讀取標頭,將0改為1。傳感器返回的后六位字節(jié)便是測量到的溫度和相對濕度的數(shù)據(jù)。其中六個字節(jié),高三位為兩位溫度和一位校驗位,低三位為兩位相對濕度和一位校驗位,采用CRC校驗。

數(shù)據(jù)轉(zhuǎn)換公式如下:

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

三、簡單實現(xiàn)

以下代碼只是簡單地演示如何使用傳感器,沒有過多的規(guī)范要求。

(1)接口定義

int SendCMD(char *devName, char addr, uint16_t command)
{
int fd = -1;
uint8_t cmdBuf[2L] = {0};
struct i2c_rdwr_ioctl_data i2c_data;
fd = open(devName, O_RDWR); //獲取I2C設備句柄
i2c_data.nmsgs = 1;
i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs * sizeof(struct
i2c_msg));
ioctl(fd, I2C_TIMEOUT, 1);
ioctl(fd, I2C_RETRIES, 2L);
cmdBuf[0] = command >> 8L; //對指令數(shù)據(jù)進行處理 高八位和低八位
cmdBuf[1] = command & 0xFF;
i2c_data.msgs[0].len = 2L;
i2c_data.msgs[0].addr = addr;
i2c_data.msgs[0].flags = 0;
i2c_data.msgs[0].buf = cmdBuf;
ioctl(fd, I2C_RDWR, (unsigned long)&i2c_data); //將數(shù)據(jù)寫入進行傳輸
free(i2c_data.msgs);
close(fd);
return 0;
}
// 再定義一些數(shù)據(jù)轉(zhuǎn)換函數(shù)和校驗函數(shù) 簡單的數(shù)據(jù)轉(zhuǎn)換 忽略
int ConvertTH(uint8_t tempRH, float *rawTemp, float *rawHum);
...

(2)主函數(shù)

int main(int argc, char *argv[])
{
char *dev_name = "/dev/i2c-5";
SendCMD(dev_name,ADDR,0x3093) //重啟
usleep(50L * 1000L);
SendCMD(dev_name,ADDR,0x202F) //開始測量
usleep(50L * 1000L);
int fd = -1;
struct i2c_rdwr_ioctl_data i2c_data;
uint8_t rawData[6L] = {0};
float rawTemp = 0, rawHum = 0;
fd = open(devName, O_RDWR);
i2c_data.nmsgs = 1;
i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs * sizeof(struct
i2c_msg));
i2c_data.msgs[0].len = 6L;
i2c_data.msgs[0].addr = addr;
i2c_data.msgs[0].flags = 1;
i2c_data.msgs[0].buf = rawData;
ioctl(fd, I2C_RDWR, (unsigned long)&i2c_data);
free(i2c_data.msgs);
close(fd);
ConvertTH(rawData, &rawTemp, &rawHum);
printf("Temp: %.2f°C\nHum: %.2f°F",rawTemp,rawHum);
return 0;
}

四、采用標準系統(tǒng)HDF驅(qū)動實現(xiàn)

使用到:九聯(lián)科技unionpi_tiger開發(fā)板,SHT3x-DIS溫濕度傳感器,OpenHarmony源碼。

(1)配置產(chǎn)品驅(qū)動(一般廠商都會配置好,若沒配置可以跳轉(zhuǎn)至官方文檔查看詳細教程)

實例化驅(qū)動入口:

  • 實例化HdfDriverEntry結(jié)構(gòu)體成員。
  • 調(diào)用HDF_INIT將HdfDriverEntry實例化對象注冊到HDF框架中。

配置屬性文件:

  • 在device_info.hcs文件中添加deviceNode描述。
//device_info.hcs 配置參考
root {
device_info {
match_attr = "hdf_manager";
device_i2c :: device {
device0 :: deviceNode {
policy = 2;
priority = 50;
permission = 0644;
moduleName = "HDF_PLATFORM_I2C_MANAGER";
serviceName = "HDF_PLATFORM_I2C_MANAGER";
deviceMatchAttr = "hdf_platform_i2c_manager";
}
device1 :: deviceNode {
policy = 0; // 等于0,不需要發(fā)布服務
priority = 55; // 驅(qū)動啟動優(yōu)先級
permission = 0644; // 驅(qū)動創(chuàng)建設備節(jié)點權(quán)限
moduleName = "hi35xx_i2c_driver";
//【必要】用于指定驅(qū)動名稱,需要與期望的驅(qū)動Entry中的moduleName一致;
serviceName = "HI35XX_I2C_DRIVER"; //【必要】驅(qū)動對外發(fā)布服務的名稱,必須唯一
deviceMatchAttr =
"hisilicon_hi35xx_i2c";//【必要】用于配置控制器私有數(shù)據(jù),要與i2c_config.hcs中對應控制器保持一致
// 具體的控制器信息在 i2c_config.hcs 中
}
}
}
}
// i2c_config.hcs 配置參考 (需要根據(jù)使用的開發(fā)板配置)
root {
platform {
i2c_config {
match_attr =
"hisilicon_hi35xx_i2c";//【必要】需要和device_info.hcs中的deviceMatchAttr值一致
template i2c_controller { //模板公共參數(shù),繼承該模板的節(jié)點如果使用模板中的默認值,則節(jié)點字段可以缺省
bus = 0; //【必要】i2c 識別號
reg_pbase = 0x120b0000; //【必要】物理基地址
reg_size = 0xd1; //【必要】寄存器位寬
irq = 0; //【可選】根據(jù)廠商需要來使用
freq = 400000; //【可選】根據(jù)廠商需要來使用
clk = 50000000; //【可選】根據(jù)廠商需要來使用
}
controller_0x120b0000 :: i2c_controller {
bus = 0;
}
controller_0x120b1000 :: i2c_controller {
bus = 1;
reg_pbase = 0x120b1000;
}
...
}
}
}

實例化I2C控制器對象:

初始化I2cCntlr成員。

實例化I2cCntlr成員I2cMethod和I2cLockMethod。

p.s 使用到的九聯(lián)開發(fā)板已有相關(guān)配置,以上配置無需做更改或添加。

(2)一個結(jié)構(gòu)三個接口

I2cMsg結(jié)構(gòu)體:用于傳輸數(shù)據(jù)載體,由地址addr,緩存buf,緩存長度len,信號標記flags組成。

struct I2cMsg {
/** Address of the I2C device */
uint16_t addr;
/** Address of the buffer for storing transferred data */
uint8_t *buf;
/** Length of the transferred data */
uint16_t len;
/**
* Transfer Mode Flag | Description
* ------------| -----------------------
* I2C_FLAG_READ | Read flag
* I2C_FLAG_ADDR_10BIT | 10-bit addressing flag
* I2C_FLAG_READ_NO_ACK | No-ACK read flag
* I2C_FLAG_IGNORE_NO_ACK | Ignoring no-ACK flag
* I2C_FLAG_NO_START | No START condition flag
* I2C_FLAG_STOP | STOP condition flag
*/
uint16_t flags;
};

三個接口分別為I2cOpen()、I2cClose()、I2cTransfer()。

//number指I2C所掛載的總線號
DevHandle I2cOpen(int16_t number);
//handle是I2cOpen()返回的設備句柄
void I2cClose(DevHandle handle);
//msgs所要傳輸?shù)臄?shù)據(jù)結(jié)構(gòu)體,count是傳輸結(jié)構(gòu)體的大小
int32_t I2cTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t
count);

(3) 代碼

  • 頭文件
#include //標準輸入輸出
#include //使用到usleep()進程掛起函數(shù)
#include "i2c_if.h" //HDF i2c 接口
#include "hdf_log.h" //日志打印頭文件
  • 結(jié)構(gòu)體與接口
// 重新定義結(jié)構(gòu)體方便使用
typedef struct
{
struct I2cMsg * i2cMsg;
uint8_t msgLen; //i2cMsg的長度
} I2cMessage;
//定義命令發(fā)送函數(shù)
int32_t SendCMD(DevHandle handle,uint16_t command)
{
int32_t ret;
I2cMessage i2cMessage;
i2cMessage.msgLen = 1;
i2cMessage.i2cMsg = new I2cMsg[1]; //申請內(nèi)存
uint8_t cmdBuf[2L] = {0};
cmdBuf[0] = command >> 8L; //將命令拆分成高低位分別保存
cmdBuf[1] = command & 0xFF;
i2cMessage.i2cMsg[0].len = 2L;
i2cMessage.i2cMsg[0].addr = ADDR;
i2cMessage.i2cMsg[0].flags = WRITE_FLAGS;
i2cMessage.i2cMsg[0].buf = cmdBuf;
ret = I2cTransfer(handle,i2cMessage.i2cMsg,i2cMessage.msgLen);
if(ret < 0){
LOGE("%s: SendCommend faided",__func__);
delete i2cMessage.i2cMsg;
return -1;
}
delete i2cMessage.i2cMsg; //釋放內(nèi)存
usleep(50L * 1000L); //等待發(fā)送完成
return 1;
}
  • 主函數(shù)
int main(int argc, char** argv)
{
/**
* 數(shù)據(jù)初始化
*/
DevHandle i2cHandle;
/**
* 獲取句柄
*/
i2cHandle = I2cOpen(BUSID);
if(i2cHandle == NULL){
LOGE("%s:get handle failed",__func__);
I2cClose(i2cHandle);
return 0;
}
/**
* 發(fā)送命令
*/
SendCMD(i2cHandle,0x3093); //關(guān)閉reset命令
SendCMD(i2cHandle,0x202F); //發(fā)送命令 repeatability=Low mps=0.5
/**
* 接收數(shù)據(jù)
*/
I2cMessage i2cMessage;
i2cMessage.msgLen = 1;
i2cMessage.i2cMsg = new I2cMsg[1];
uint8_t regData[6L] = {0};
i2cMessage.i2cMsg[0].len = 6L;
i2cMessage.i2cMsg[0].addr = ADDR;
i2cMessage.i2cMsg[0].flags = READ_FLAGS;
i2cMessage.i2cMsg[0].buf = regData;
I2cTransfer(i2cHandle,i2cMessage.i2cMsg,i2cMessage.msgLen);
delete i2cMessage.i2cMsg;
/**
* 數(shù)據(jù)處理
*/
uint16_t value = 0;
value = regData[0] << 8;
value = value | regData[1];
printf("Temperature: %.2f C\n",175.0f * (float)value / 65535.0f - 45.0f);
value = 0;
value = regData[3] << 8;
value = value | regData[4];
printf("Humidity: %.2f H\n",100.0f * (float)value / 65535.0f);
/**
* 關(guān)閉設備
*/
I2cClose(i2cHandle);
return 0;
}

至此,成功通過OpenHarmony的HDF驅(qū)動來獲取傳感器的值。

五、實現(xiàn)NAPI

(1)模塊定義與注冊

/**
* 模塊定義
*/
static napi_module i2cHDF_demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = registerI2cHDF_DemoApis,
.nm_modname = "i2chdf_demo",
.nm_priv = ((void *)0),
.reserved = {0},
};
/**
* 模塊注冊
*/
extern "C" __attribute__((constructor)) void RegisterI2cHDFoModule(void)
{
napi_module_register(&i2cHDF_demoModule);
}

(2)接口定義與注冊

int32_t SendCMD(DevHandle handle,uint16_t command)
{
int32_t ret;
struct I2cMsg * i2cMsg;
int msgLen = 1;
i2cMsg = new I2cMsg[msgLen];
uint8_t cmdBuf[2L] = {0};
cmdBuf[0] = command >> 8L;
cmdBuf[1] = command & 0xFF;
i2cMsg[0].len = 2L;
i2cMsg[0].addr = ADDR;
i2cMsg[0].flags = WRITE_FLAGS;
i2cMsg[0].buf = cmdBuf;
ret = I2cTransfer(handle,i2cMsg,msgLen);
delete i2cMsg;
usleep(50L * 1000L);
return 1;
}
/**
* 接口定義
*/
static napi_value readI2cBuf(napi_env env,napi_callback_info info)
{
napi_value ret;
DevHandle i2cHandle;
i2cHandle = I2cOpen(BUSID);
SendCMD(i2cHandle,0x3093);
SendCMD(i2cHandle,0x202F);
struct I2cMsg * i2cMsg;
int msgLen = 1;
i2cMsg = new I2cMsg[msgLen];
uint8_t regData[6L] = {0};
i2cMsg[0].len = 6L;
i2cMsg[0].addr = ADDR;
i2cMsg[0].flags = READ_FLAGS;
i2cMsg[0].buf = regData;
I2cTransfer(i2cHandle,i2cMsg,msgLen);
delete i2cMsg;
uint16_t value = 0;
double sHTTemp = 0;
value = regData[0] << 8;
value = value | regData[1];
sHTTemp = 175.0f * (double)value / 65535.0f - 45.0f;
//設計思路與上HDF大同小異,只不過將最后獲取的值通過轉(zhuǎn)換再返回
//此處只處理返回溫度的值,方便演示
NAPI_CALL(env, napi_create_double(env, sHTTemp, &ret));
return ret;
}
/**
* 接口注冊
*/
static napi_value registerI2cHDF_DemoApis(napi_env env, napi_value
exports)
{
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("readI2cBuf",readI2cBuf), //NAPI名字,上面的函數(shù)
};
NAPI_CALL(env,napi_define_properties(env,exports,sizeof(desc)/sizeof(desc[0]),desc));
return exports;
}

(3)北向接口

  • NAPI
function readI2cBuf(): number;
  • Index.ets
import i2chdf from '@ohos.i2chdf'
@Entry
@Component
struct Index {
@State message: string = 'Temperature: '+ i2chdf.readI2cBuf().toFixed(2) +
'°C';
aboutToAppear(): void{
var Id = setInterval(() =>{
this.message = 'Temperature: '+ i2chdf.readI2cBuf().toFixed(2) + '°C';
},1000)
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}

(4)效果演示

使用SHT3x-DIS溫濕度傳感器的I2C案例-開源基礎軟件社區(qū)

總結(jié)

整個案例整體思路都是圍繞著I2C通信流程和SHT3x溫度傳感器工作流程展開的。而在HDF驅(qū)動的使用中,我們會發(fā)現(xiàn),獲取設備句柄的方式我們只用一個數(shù)字就可以,相比之前的"/dev/i2c-5"更加簡易明了,這也是HDF的特性之一。NAPI的實現(xiàn),將整個OpenHarmoy南北向打通,使得北向程序可通過本地的接口就可以訪問傳感器的溫濕度。

??想了解更多關(guān)于開源的內(nèi)容,請訪問:??

??51CTO 開源基礎軟件社區(qū)??

??https://ost.51cto.com??

責任編輯:jianghua 來源: 51CTO 開源基礎軟件社區(qū)
相關(guān)推薦

2020-10-30 09:31:16

2G

2023-03-20 16:05:49

HDF傳感器驅(qū)動開發(fā)

2023-05-30 14:58:05

智能開發(fā)鴻蒙

2017-08-11 18:25:25

Linuxi2c

2022-06-13 09:21:45

I2C DriverI2C 子系統(tǒng)

2021-09-24 09:08:31

鴻蒙HarmonyOS應用

2022-06-12 07:30:13

I3C通訊協(xié)議

2017-03-16 08:30:19

Android ThAndroidI2C

2020-12-21 09:57:52

OLED溫濕度計hi3861

2023-04-17 16:21:58

操作系統(tǒng)鴻蒙

2023-03-03 13:45:00

數(shù)據(jù)中心傳感器

2010-06-08 16:25:35

I2C總線協(xié)議

2023-09-13 15:33:57

I2C鴻蒙

2022-04-07 15:28:16

HarmonyOS鴻蒙操作系統(tǒng)

2009-04-11 15:12:24

.Net MicroI2C總線模擬器

2020-11-03 09:55:33

嵌入式算法夾角

2021-05-06 11:40:54

MQTT物聯(lián)網(wǎng)網(wǎng)關(guān)開發(fā)物聯(lián)網(wǎng)

2023-04-24 15:11:51

系統(tǒng)開發(fā)鴻蒙

2010-07-01 16:45:05

I2C總線協(xié)議

2022-05-27 09:00:09

I2C子系統(tǒng)協(xié)議
點贊
收藏

51CTO技術(shù)棧公眾號