nrf52832驅(qū)動(dòng)溫濕度傳感器hts221

嘗試使用TWI讀取溫度濕度傳感器hts221

hts221的介紹不細(xì)說(shuō),誤差什么的去看手冊(cè)吧~只說(shuō)說(shuō)它支持SPI 及 IIC通信,感覺(jué)相對(duì)來(lái)說(shuō),在傳感器方面似乎iic用的更多.因?yàn)橐灿玫搅撕芏嗥渌鹖ic的設(shè)備,所以直接使用lps22hb的iic了~

IIC通信就不多說(shuō)了,直接來(lái)看hts221 iic通信的格式:
address:0x5f, 所以如果是read address為0xbf, 如果是write address為0xbe.
和一般的iic讀寫過(guò)程沒(méi)有什么區(qū)別~


hts221 IIC讀寫.png

注意:datasheet中有這樣一段話:

After the start condition (ST) a slave address is sent, once a slave acknowledge (SAK) has been returned, an 8-bit sub-address (SUB) will be transmitted: the 7 LSB represents the actual register address while the MSB enables address autoincrement. If the MSB of the SUB field is ‘1’, the SUB (register address) will be automatically increased to allow multiple data read/write.

也就是說(shuō),hts221并不想其他IIC設(shè)備一樣,連續(xù)讀寫時(shí)自動(dòng)增加register地址,而是在最開(kāi)始配置地址時(shí)如果bit7為1,才會(huì)自加,否則會(huì)一直讀/寫那一個(gè)寄存器地址.(最開(kāi)始沒(méi)看到,發(fā)現(xiàn)連續(xù)讀總是一個(gè)值,仔細(xì)看了文檔才發(fā)現(xiàn).)

為了后面讀寫方便,寫個(gè)iic讀寫子函數(shù):

static uint32_t buf_read(uint8_t reg_addr, uint8_t * p_buf, uint32_t size)
{
    uint8_t reg=reg_addr;
    if(size>1)reg|=0x80;
    return user_drv_twi_read(HTS221_ADDR,reg,p_buf,size);
}

static uint32_t reg_write(uint8_t reg_addr, uint8_t reg_val)
{
    return user_drv_twi_tx_byte(HTS221_ADDR,reg_addr,reg_val);
}

Register address Map

之后就是register的配置了:


hts221 register

為了方便使用宏定義:

#define HTS221_WHO_AM_I_REG                         0x0F
#define HTS221_AV_CONF_REG                          0x10
#define HTS221_CTRL_REG1                            0x20
#define HTS221_CTRL_REG2                            0x21
#define HTS221_CTRL_REG3                            0x22
#define HTS221_STATUS_REG                           0x27
#define HTS221_HUMIDITY_OUT_L_REG                   0x28
#define HTS221_HUMIDITY_OUT_H_REG                   0x29
#define HTS221_TEMP_OUT_L_REG                       0x2A
#define HTS221_TEMP_OUT_H_REG                       0x2B

#define HTS221_CALIBRATION_REGS                     0x30
#define HTS221_CALIBRATION_REGS_NUM                 16

WHO_AM_I為只讀艰亮,值必須為0xbc,感覺(jué)可以使用讀這個(gè)寄存器來(lái)檢測(cè)硬件是否正常.
AV_CONF娃圆、CTRL_REG[1..3]是配置寄存器,手冊(cè)很清楚,根據(jù)手冊(cè)配置吧.
需要注意的是CALIB_0..F,校準(zhǔn)寄存器,讀取出來(lái)的值需要根據(jù)這些寄存器里的值通過(guò)計(jì)算獲得最終結(jié)果.


Decoding the coefficients in the sensor Flash

hts221初始化過(guò)程就很簡(jiǎn)單了:
配置配置寄存器,讀取校準(zhǔn)寄存器;當(dāng)hts221準(zhǔn)備好數(shù)據(jù)時(shí)就可以讀取數(shù)據(jù),通過(guò)校準(zhǔn)數(shù)據(jù)校準(zhǔn)值.
配置就不多說(shuō),看看校準(zhǔn)相關(guān)的地方

校準(zhǔn)

校準(zhǔn)參數(shù)存在寄存器0x30-0x3f,自然需要讀出.為了方便使用這些參數(shù),根據(jù)寄存器創(chuàng)建了一個(gè)結(jié)構(gòu)體(為了簡(jiǎn)單,直接copy自Nordic Thingy:52官方FW):

typedef struct
{
    uint8_t  H0_rH_x2;
    uint8_t  H1_rH_x2;
    uint16_t T0_degC_x8;
    uint16_t T1_degC_x8;
    int16_t  H0_T0_OUT;
    int16_t  H1_T0_OUT;
    int16_t  T0_OUT;
    int16_t  T1_OUT;
}drv_hts221_calib_t;

drv_hts221_calib_t p_calib;
    uint8_t  calib_raw[HTS221_CALIBRATION_REGS_NUM];
    err_code = user_drv_twi_read(HTS221_ADDR,HTS221_CALIBRATION_REGS,calib_raw,HTS221_CALIBRATION_REGS_NUM);
    if(err_code!=NRF_SUCCESS) return err_code;

    p_calib->H0_rH_x2   = calib_raw[0];
    p_calib->H1_rH_x2   = calib_raw[1];
    p_calib->T0_degC_x8 = (uint16_t)calib_raw[2] + ((uint16_t)(calib_raw[5] & 0x03) << 8);
    p_calib->T1_degC_x8 = (uint16_t)calib_raw[3] + ((uint16_t)((calib_raw[5] >> 2) & 0x03) << 8);
    p_calib->H0_T0_OUT  = (int16_t)calib_raw[6]  + ((int16_t)calib_raw[7]  << 8);
    p_calib->H1_T0_OUT  = (int16_t)calib_raw[10] + ((int16_t)calib_raw[11] << 8);
    p_calib->T0_OUT     = (int16_t)calib_raw[12] + ((int16_t)calib_raw[13] << 8);
    p_calib->T1_OUT     = (int16_t)calib_raw[14] + ((int16_t)calib_raw[15] << 8);

校準(zhǔn)參數(shù)獲取后就是獲取實(shí)際值計(jì)算了.
實(shí)際上就是個(gè)求解線性方程y=kx+b而已,給出的校準(zhǔn)值其實(shí)就是線性方程的兩個(gè)解,使用這兩個(gè)解求得線性方程的k b,將讀取出的值帶入求出即可.
官方給出的說(shuō)明與例子:


已知兩點(diǎn)坐標(biāo)(x1,y1)(x2,y2),已知(x,y)中的x求y
使用(y2-y1)/(x2-x1)=(y-y1)/(x-x1) ===>y= (y2-y1)*(x-x1)/(x2-x1)+y1.
注意,最后的結(jié)果中,溫度擴(kuò)大了8倍,濕度擴(kuò)大了2倍.
由于溫度精確到了小數(shù)點(diǎn)1位,所以擴(kuò)大了10倍后右移3位(相當(dāng)于除8)
濕度通常只需要精確到個(gè)位,所以直接右移1位(相當(dāng)于除2)

    uint32_t err_code;
    NRF_LOG_DEBUG("HTS221 handler:%d,%d",pin,action);
    uint8_t sample_data[4];
    err_code=buf_read(HTS221_HUMIDITY_OUT_L_REG,sample_data,4);
        APP_ERROR_CHECK(err_code);
        Humidity=(int16_t)sample_data[0]  + ((int16_t)sample_data[1]  << 8);
    Temperature=(int16_t)sample_data[2]  + ((int16_t)sample_data[3]  << 8);
    NRF_LOG_INFO("humidity:0x%x%x",sample_data[1],sample_data[0]);
    NRF_LOG_INFO("Temperature:0x%x",Temperature);


    int16_t tep=((((int16_t)Temperature-(int16_t)p_calib.T0_OUT)*((int16_t)p_calib.T1_degC_x8-(int16_t)p_calib.T0_degC_x8)/((int16_t)p_calib.T1_OUT-(int16_t)p_calib.T0_OUT)+(int16_t)p_calib.T0_degC_x8)*10)>>3;
    int16_t hum=(((int16_t)Humidity-(int16_t)p_calib.H0_T0_OUT)*((int16_t)p_calib.H1_rH_x2-(int16_t)p_calib.H0_rH_x2)/((int16_t)p_calib.H1_T0_OUT-(int16_t)p_calib.H0_T0_OUT)+(int16_t)p_calib.H0_rH_x2)>>1;
        //Humidity range
        if(hum>100)hum=100;
        else if(hum<0) hum=0;
    
    NRF_LOG_INFO("Temperature:%d.%d     Humidity:%d",tep/10,tep%10,hum);

到此基本就結(jié)束了,不過(guò)因?yàn)槭褂昧薶ts221的DRDY,所以在nrf52832中,讀取溫濕度時(shí)只是啟動(dòng)hts221了,在DRDY的事件中進(jìn)行讀取溫濕度值.
以下為主要的初始化及讀取溫濕度值代碼,與上面的有部分重復(fù).

void user_hts221_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    uint32_t err_code;
    NRF_LOG_DEBUG("HTS221 handler:%d,%d",pin,action);
    uint8_t sample_data[4];
    err_code=buf_read(HTS221_HUMIDITY_OUT_L_REG,sample_data,4);
        APP_ERROR_CHECK(err_code);
        Humidity=(int16_t)sample_data[0]  + ((int16_t)sample_data[1]  << 8);
    Temperature=(int16_t)sample_data[2]  + ((int16_t)sample_data[3]  << 8);
    NRF_LOG_INFO("humidity:0x%x%x",sample_data[1],sample_data[0]);
    NRF_LOG_INFO("Temperature:0x%x",Temperature);


    int16_t tep=((((int16_t)Temperature-(int16_t)p_calib.T0_OUT)*((int16_t)p_calib.T1_degC_x8-(int16_t)p_calib.T0_degC_x8)/((int16_t)p_calib.T1_OUT-(int16_t)p_calib.T0_OUT)+(int16_t)p_calib.T0_degC_x8)*10)>>3;
    int16_t hum=(((int16_t)Humidity-(int16_t)p_calib.H0_T0_OUT)*((int16_t)p_calib.H1_rH_x2-(int16_t)p_calib.H0_rH_x2)/((int16_t)p_calib.H1_T0_OUT-(int16_t)p_calib.H0_T0_OUT)+(int16_t)p_calib.H0_rH_x2)>>1;
        //Humidity range
        if(hum>100)hum=100;
        else if(hum<0) hum=0;
    
    NRF_LOG_INFO("Temperature:%d.%d     Humidity:%d",tep/10,tep%10,hum);
    user_ble_gatts_notify(tep);
}

void user_hts221_init()
{
    uint32_t err_code;
    uint8_t  calib_raw[HTS221_CALIBRATION_REGS_NUM];


    err_code=user_drv_twi_tx_byte(HTS221_ADDR,0x20,0x80);   //active mode   One-shot
    err_code=user_drv_twi_tx_byte(HTS221_ADDR,0x22,0x84);   //active low

    uint8_t reg_val;
    err_code=user_drv_twi_read_byte(HTS221_ADDR,HTS221_WHO_AM_I_REG,&reg_val);
    if(err_code!=NRF_SUCCESS) NRF_LOG_ERROR("HTS221 user_drv_twi_read_byte error:%x",err_code);

    if(reg_val!=HTS221_WHO_AM_I_VAL)
    {
        NRF_LOG_ERROR("HTS221 verify error:%x",reg_val);
    } else  NRF_LOG_INFO("HTS221 verify ok");

    buf_read(HTS221_CALIBRATION_REGS,calib_raw,HTS221_CALIBRATION_REGS_NUM);
    p_calib.H0_rH_x2   = calib_raw[0];
    p_calib.H1_rH_x2   = calib_raw[1];
    p_calib.T0_degC_x8 = (uint16_t)calib_raw[2] + ((uint16_t)(calib_raw[5] & 0x03) << 8);
    p_calib.T1_degC_x8 = (uint16_t)calib_raw[3] + ((uint16_t)((calib_raw[5] >> 2) & 0x03) << 8);
    p_calib.H0_T0_OUT  = (int16_t)calib_raw[6]  + ((int16_t)calib_raw[7]  << 8);
    p_calib.H1_T0_OUT  = (int16_t)calib_raw[10] + ((int16_t)calib_raw[11] << 8);
    p_calib.T0_OUT     = (int16_t)calib_raw[12] + ((int16_t)calib_raw[13] << 8);
    p_calib.T1_OUT     = (int16_t)calib_raw[14] + ((int16_t)calib_raw[15] << 8);

    if(!nrf_gpio_pin_read(HT_INT))
    {
        user_hts221_handler(HT_INT,NRF_GPIOTE_POLARITY_HITOLO);
    }

    if(!nrfx_gpiote_is_init())
    {
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);

    }

    nrf_drv_gpiote_in_config_t in_config =
    {
        .is_watcher = false,
        .hi_accuracy = true,
        .sense = NRF_GPIOTE_POLARITY_HITOLO,
        .pull = NRF_GPIO_PIN_PULLUP,
    };


    err_code = nrf_drv_gpiote_in_init(HT_INT, &in_config, user_hts221_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_gpiote_in_event_enable(HT_INT, true);
        
}

void user_hts221_conversion_start()
{
    uint32_t err_code;
    NRF_LOG_DEBUG("HTS221 conversion start");
    err_code=user_drv_twi_tx_byte(HTS221_ADDR,0x21,0x01);
    APP_ERROR_CHECK(err_code);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蔫慧,一起剝皮案震驚了整個(gè)濱河市挠乳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖睡扬,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盟蚣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡卖怜,警方通過(guò)查閱死者的電腦和手機(jī)屎开,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)马靠,“玉大人奄抽,你說(shuō)我怎么就攤上這事∷” “怎么了逞度?”我有些...
    開(kāi)封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)妙啃。 經(jīng)常有香客問(wèn)我档泽,道長(zhǎng),這世上最難降的妖魔是什么揖赴? 我笑而不...
    開(kāi)封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任馆匿,我火速辦了婚禮,結(jié)果婚禮上燥滑,老公的妹妹穿的比我還像新娘甜熔。我一直安慰自己,他們只是感情好突倍,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布腔稀。 她就那樣靜靜地躺著,像睡著了一般羽历。 火紅的嫁衣襯著肌膚如雪焊虏。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天秕磷,我揣著相機(jī)與錄音诵闭,去河邊找鬼。 笑死澎嚣,一個(gè)胖子當(dāng)著我的面吹牛疏尿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播易桃,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼褥琐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了晤郑?” 一聲冷哼從身側(cè)響起敌呈,我...
    開(kāi)封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎磕洪,沒(méi)想到半個(gè)月后吭练,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡析显,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年鲫咽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谷异。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡分尸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晰绎,到底是詐尸還是另有隱情寓落,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布荞下,位于F島的核電站伶选,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏尖昏。R本人自食惡果不足惜仰税,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抽诉。 院中可真熱鬧陨簇,春花似錦、人聲如沸迹淌。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)唉窃。三九已至耙饰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纹份,已是汗流浹背苟跪。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔓涧,地道東北人件已。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像元暴,于是被迫代替她去往敵國(guó)和親篷扩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

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