IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> MM32F3277 I2C 访问 HTS221 温湿度传感器 -> 正文阅读

[嵌入式]MM32F3277 I2C 访问 HTS221 温湿度传感器

主控芯片:MM32F3277

传感器:HTS221 温湿度传感器

开发环境:IAR 7.80.4

I2C 原理

I2C 总线接口使用两条串行线,SDA 和 SCL,分别用于数据和时钟的传输,工作方式是半双工。I2C 分为主从模式,Master 和 Slave,每一个 I2C 设备都有一个固定的地址。

I2C 总线物理拓扑结构

主控作为 Master,总线上可以挂多个 Slave 设备,Master 通过寻址控制各个 Slave

SCL 和 SDA 在总线空闲时,由上拉电阻拉高,保持高电平

I2C line

I2C Start / Stop 条件

START 和 STOP 位由 Master 发送,

  • Start:SCL 为高时,SDA 从高到低
  • DATA:SCL 为高时获取稳定数据,SCL 为低时数据高低变化
  • Stop:SCL 为高时,SDA 从低到高

start

I2C 寻址

MM32F3277 支持 7 位和 10 位地址,Master 发送 START 位之后,发送 Slave 的地址,如果 Slave 地址匹配上,Slave 应答 SAK

Read 为 1,Write 为 0

  • 7 位地址

addr7

  • 10 位地址

addr10

I2C Master 发送

Master 发送 DATA 后,Slave 回应 SAK;Master 发送完 DATA 后,产生 STOP 信号

master_write

I2C Master 接收

Master 接收 DATA 后,回应 MAK;接收完所有的 DATA 后,回应 NMAK,产生 STOP 信号

master_read

HTS221 温湿度传感器

[ST HTS221 温湿度传感器资料][hts221]

Features

  • 16-bit humidity and temperature output data
  • Embedded 16-bit ADC
  • SPI and I2C interface
  • Humidity accuracy: ± 3.5% rH, 20 to +80% rH
  • Temperature accuracy: ±0.5℃, 15 to +40℃

Pin

  1. VDD: Power supply
  2. SCL / SPC: I2C serial clock / SPI serial port clock
  3. DRDY: Data Ready output signal
  4. SDA / SDI / SDO: I2C serial data / 3-wrie SPI serial data input or output
  5. GND: Ground
  6. CS: Set 1 when use I2C; Set 0 when use SPI

这里选择通过 I2C 进行通讯,所以 CS 管脚接 VDD (或者不接,内部可以上拉);若果选择 SPI 进行通讯,需要将 CS 管脚接地。

SCL 和 SDA 两个管脚必须是通过上拉电阻连接到 VDD!!!因为 START 信号是 SDA 由高到低,所以得先把 SDA 拉高。

HTS221 Address

HTS221 作为 I2C Slave,其地址为:

// HTS221 Address
#define SLAVE_ADDRESS                   0x5F
#define SLAVE_ADDRESS_WRITE             SLAVE_ADDRESS << 1				// 0xBE
#define SLAVE_ADDRESS_READ              (SLAVE_ADDRESS << 1) | 0x01		// 0xBF

Master write data to Slave

Steps

  1. Master 发送 START 信号(SCL hold high, SDA high to low)

  2. Master 发送 Slave 的 7 位地址 + 写信号

  3. Slave 进行地址匹配,匹配成功回应 SAK

  4. Master 发送 SubAddress,即 Slave 内部寄存器地址

    如果一次 I2C 数据传输只操作一个寄存器

    #define HTS221_CTRL_REG1                0x20
    HTS221_Reg_Write(I2Cx, HTS221_CTRL_REG1, buffer, 1)
    

    如果一次 I2C 数据传输操作多个地址连续的寄存器,将 SubAddr 的 MSB 置 1,SubAddr[6:0] 为寄存器地址

    #define CONTINUOUS_ADDRESS(REG_ADDR)    REG_ADDR | 0x80
    HTS221_Reg_Write(I2Cx, CONTINUOUS_ADDRESS(HTS221_CTRL_REG1), buffer, 3)
    
  5. Slave 应答 SubAddr

  6. Master 发送 DATA,Slave 应答 SAK

  7. Master 发送完后,产生 STOP 信号(SCL hold high, SDA lowto high)

I2CWrite

Master read data from Slave

Steps

  1. Master 发送 START 信号(SCL hold high, SDA high to low)
  2. Master 发送 Slave 的 7 位地址 + 写信号
  3. Slave 进行地址匹配,匹配成功回应 SAK
  4. Master 发送 SubAddress,即 Slave 内部寄存器地址,操作同上
  5. Slave 应答 SubAddr
  6. Master 发送 RESTART 信号,重新发送 Slave 的 7 位地址 + 读信号,Slave 回应 SAK
  7. Slave 发送 Data,Master 应答 MAK
  8. Master 接收最后一个数据后,不应答 NMAK,产生 STOP 信号(SCL hold high, SDA lowto high)

I2CRead

Register Map

  • WHO_AM_I

    Reg Address is 0x0F, read only and default is 0xBC

    // HTS221 Device ID
    #define DEVICE_ID_WHO_AM_I              0xBC
    
  • AV_CONF

    Reg Address is 0x10, R/W and default is 0x1B

    该寄存器主要控制温度和湿度的样本个数

  • CTRL_REG1

    Reg Address is 0x20, R/W and default is 0x00

    1. PD 控制传感器开关,置 1 为 active;置 0 为 power-down

    2. BDU 控制 MSB 和 LSB 数据读取的连续性,置 1 为读完 MSB 和 LSB 之后再更新输出数据;置 0 为实时更新,可能会导致读取的 MSB 和 LSB 不是同一组

    3. ODR1 / ODR0 控制数据读取频率,00 为 one-shot,01 为 1Hz,10 为 7Hz,11 为 12.5Hz

  • CTRL_REG2

    Reg Address is 0x21, R/W and default is 0x00

    1. BOOT 用于重置寄存器的默认值

    2. Heater 用于启动加热器,恢复传感器环境温度

    3. ONE_SHOT 用于当 ODR 为 00 时,ONE_SHOT 置 1 为使能一次读数据指令,读完后该位会硬件清 0

  • CTRL_REG3

    Reg Address is 0x22, R/W and default is 0x00

    1. DRDY_H_L 配置 DRDY_EN 即 Pin3 管脚低有效还是高有效,0 为高有效,1 为低有效

    2. PP_OD 控制 Pin3 管脚,置 1 为 open drain,置 0 为 push pull

    3. DRDY_EN 输出到 Pin3 管脚,为 1 时说明数据可读,为 0 时数据不可读,数据读取之后会自动清 0

      DRDY_EN = STATUS_REG[1] | STATUS_REG[0]

  • STATUS_REG

    Reg Address is 0x27, read only and default is 0x00

    1. H_DA / T_DA 在 one-shot 或者每一个 ODR 频率周期时,自动置 1,表示数据可读,读取后自动清 0
  • HUMIDITY_OUT_L

    Reg Address is 0x28, read only

    湿度数据 LSB

  • HUMIDITY_OUT_H

    Reg Address is 0x29, read only

    湿度数据 MSB

    HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_HUMIDITY_OUT_L), buffer, 2);
    *H_T_OUT = (uint16_t)(buffer[1] << 8) | (uint16_t)buffer[0];
    
  • TEMP_OUT_L

    Reg Address is 0x2A, read only

    温度数据 LSB

  • TEMP_OUT_H

    Reg Address is 0x2B, read only

    温度数据 MSB

    HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_TEMP_OUT_L), buffer, 2);
    *T_OUT = (uint16_t)(buffer[1] << 8) | (uint16_t)buffer[0];
    
  • CALIB_0…F

    Reg Address is 0x30 - 0x3F, R/W

    用于校准,出厂时存在内部 non-volatile memory 中,配合 HUMIDITY_OUT / TEMP_OUT 得到准确的温湿度数据

    1. Humidity Calculation
      H R H [ % ] = ( H 1 _ r H ? H 0 _ r H ) × ( H _ T _ O U T ? H 0 _ T 0 _ O U T ) H 1 _ T 0 _ O U T ? H 0 _ T 0 _ O U T + H 0 _ r H H_{RH}[\%] = \frac{(H1\_rH - H0\_rH) × (H\_T\_OUT - H0\_T0\_OUT)}{H1\_T0\_OUT - H0\_T0\_OUT} + H0\_rH HRH?[%]=H1_T0_OUT?H0_T0_OUT(H1_rH?H0_rH)×(H_T_OUT?H0_T0_OUT)?+H0_rH

    2. Temperature Calculation
      T [ d e g C ] = ( T 1 _ d e g C ? T 0 _ d e g C ) × ( T _ O U T ? T 0 _ O U T ) T 1 _ O U T ? T 0 _ O U T + T 0 _ d e g C T[degC] = \frac{(T1\_degC - T0\_degC) × (T\_OUT - T0\_OUT)}{T1\_OUT - T0\_OUT} + T0\_degC T[degC]=T1_OUT?T0_OUT(T1_degC?T0_degC)×(T_OUT?T0_OUT)?+T0_degC

HTS221 Humidity and Temperature Calculation

//
HTS221_Error_Typedef HTS221_Humidity_Calibration_Get(I2C_TypeDef *I2Cx)
{
    u8 buffer[2] = {0, 0};
    if(HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_H0_RH_X2), buffer, 2))
        return HTS221_ERROR;
    H_Cal_InitStruct.H0_rH = (int16_t)(buffer[0] >> 1);                         // H0_rH = H0_rH_x2 / 2
    H_Cal_InitStruct.H1_rH = (int16_t)(buffer[1] >> 1);                         // H1_rH = H1_rH_x2 / 2

    if(HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_H0_T0_OUT_L), buffer, 2))
        return HTS221_ERROR;
    H_Cal_InitStruct.H0_T0_OUT = (uint16_t)(buffer[1] << 8) | (uint16_t)buffer[0];

    if(HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_H1_T0_OUT_L), buffer, 2))
        return HTS221_ERROR;
    H_Cal_InitStruct.H1_T0_OUT = (uint16_t)(buffer[1] << 8) | (uint16_t)buffer[0];

    return HTS221_OK;
}

//
HTS221_Error_Typedef HTS221_Temperature_Calibration_Get(I2C_TypeDef *I2Cx)
{
    u8 buffer[4] = {0, 0, 0, 0};
    uint8_t temp;
    if(HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_T0_DEGC_X8), buffer, 2))
        return HTS221_ERROR;
    if(HTS221_Reg_Read(I2Cx, HTS221_T1_T0_MSB, &temp, 1))
        return HTS221_ERROR;
    T_Cal_InitStruct.T0_degC_MSB = (int16_t)(temp & 0x03);
    T_Cal_InitStruct.T1_degC_MSB = (int16_t)((temp & 0x0C) >> 2);
    T_Cal_InitStruct.T0_degC = ((T_Cal_InitStruct.T0_degC_MSB << 8) | buffer[0]) >> 3;
    T_Cal_InitStruct.T1_degC = ((T_Cal_InitStruct.T1_degC_MSB << 8) | buffer[1]) >> 3;

    if(HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_H0_T0_OUT_L), buffer, 4))
        return HTS221_ERROR;
    T_Cal_InitStruct.T0_OUT = (uint16_t)(buffer[1] << 8) | (uint16_t)buffer[0];
    T_Cal_InitStruct.T1_OUT = (uint16_t)(buffer[3] << 8) | (uint16_t)buffer[2];

    return HTS221_OK;
}


HTS221_Error_Typedef HTS221_HUMIDITY_OUT_Get(I2C_TypeDef *I2Cx, int16_t *H_T_OUT)
{
    u8 buffer[2] = {0, 0};
    u8 one_shot = HTS221_CR2_ONE_SHOT;
    if(HTS221_Reg_Write(I2Cx, HTS221_CTRL_REG2, &one_shot, 1))
        return HTS221_ERROR;
    if(HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_HUMIDITY_OUT_L), buffer, 2))
        return HTS221_ERROR;
    *H_T_OUT = (uint16_t)(buffer[1] << 8) | (uint16_t)buffer[0];
    return HTS221_OK;
}


HTS221_Error_Typedef HTS221_TEMPERATURE_OUT_Get(I2C_TypeDef *I2Cx, int16_t *T_OUT)
{
    u8 buffer[2] = {0, 0};
    u8 one_shot = HTS221_CR2_ONE_SHOT;
    if(HTS221_Reg_Write(I2Cx, HTS221_CTRL_REG2, &one_shot, 1))
        return HTS221_ERROR;
    if(HTS221_Reg_Read(I2Cx, CONTINUOUS_ADDRESS(HTS221_TEMP_OUT_L), buffer, 2))
        return HTS221_ERROR;
    *T_OUT = (uint16_t)(buffer[1] << 8) | (uint16_t)buffer[0];
    return HTS221_OK;
}

//
HTS221_Error_Typedef HTS221_Humidity_Calculation(I2C_TypeDef *I2Cx, uint16_t *value)
{
    int16_t H_T_OUT = 0x00;
    if(HTS221_HUMIDITY_OUT_Get(I2Cx, &H_T_OUT))
        return HTS221_ERROR;

    int32_t temp;
    temp = ((int32_t)(H_T_OUT - H_Cal_InitStruct.H0_T0_OUT)) * ((int32_t)(H_Cal_InitStruct.H1_rH - H_Cal_InitStruct.H0_rH) * 10);
    *value = (uint16_t)((temp / (H_Cal_InitStruct.H1_T0_OUT - H_Cal_InitStruct.H0_T0_OUT)) + H_Cal_InitStruct.H0_rH * 10);
    if(*value > 1000){
        *value = 1000;
    }
    printf("Get Humidity value : %d.%d %% \n", *value / 10, *value % 10);
    return HTS221_OK;
}

//
HTS221_Error_Typedef HTS221_Temperature_Calculation(I2C_TypeDef *I2Cx, int16_t *value)
{
    int16_t T_OUT = 0x00;
    if(HTS221_TEMPERATURE_OUT_Get(I2Cx, &T_OUT))
        return HTS221_ERROR;

    int32_t temp;
    temp = ((int32_t)(T_OUT - T_Cal_InitStruct.T0_OUT)) * (((int32_t)(T_Cal_InitStruct.T1_degC - T_Cal_InitStruct.T0_degC) * 10));
    *value = (temp / (T_Cal_InitStruct.T1_OUT - T_Cal_InitStruct.T0_OUT)) + T_Cal_InitStruct.T0_degC * 10;
    printf("Get Temperature value : %d.%d C \n", *value / 10, *value % 10);
    return HTS221_OK;
}

The End

发现我内心世界真的非常 INFP,虽然我以前并没有意识到我是这样的……

  1. 压力都是自己给的,批评也是自己给的
  2. 从不后悔自己的决定,但是希望世界毁灭或人生重来
  3. 每个 INFP 都想成为艺术家,但因为怕吃不饱饭而没有成为艺术家
  4. 让我郁闷的是,我并不擅长 INFP 性格擅长的东西

INFP

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:27:28  更:2022-04-04 12:28:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:33:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码