024【GD32F470】SHT20温湿度传感器模块_数字型温湿度测量模块 I2C通讯小体积模块

2.24 SHT20温湿度传感器

由瑞士Sensirion推出的 SHT20数字温湿度传感器,基于领先世界的CMOSens ® 数字传感技术,具有极高的可靠性和卓越的长期稳定性。全量程标定,两线数字接口,可与单片机直接相连,大大缩短研发时间、简化外围电路并降低费用。此外,体积微小、响应迅速、低能耗、可浸没、抗干扰能力强、温湿一体,兼有露点测量,性价比高,使该产品能够适于多种场合的应用。

2.24.1 模块来源

采购链接:
SHT20温湿度传感器模块/数字型温湿度测量模块 I2C通讯小体积模块
资料下载链接:

【完整代码资料见:https://pan.quark.cn/s/db9d3bda7208

2.24.2 规格参数

工作电压:2.1~3.6V
工作电流:0.1~1000uA
温度精度:±0.3℃
温度范围:-40~125℃
湿度范围:0~100 %RH
湿度精度:±3%RH
输出方式: IIC
管脚数量:4 Pin

2.24.3 移植过程

我们的目标是在梁山派GD32F470上能够测量环境温湿。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。

2.24.3.1 查看资料

开始传输后,随后先传输首字节包括I2C设备地址(7bit)和一个SDA方向位(R:1, W:0)。

在这里插入图片描述
一个时钟发送一个位,在第8个下降沿之后,通过拉低SDA引脚(ACK位 为0),只是传感器数据接收正常。在发出测量命令之后(‘1110’‘0011’代表温度测量,‘1110’‘0101’代表相对湿度测量 ,这种为主机模式),MCU必须等待测量完成。
在这里插入图片描述
主机模式和主机模式:①主机模式:测量过程中,SCL线被封锁(由传感器控制),在测量时,SHT2x将SCL拉低强制主机进入等待状态。当释放SCL线,表示传感器内部工作接收,可以继续进行数据传送

在这里插入图片描述
灰色的部分是传感器控制的,当传感器给MCU返回数据时,每返回一个字节,MCU要返回一个ACK信号,当接收完毕之后,返回一个NACK并接着传输停止时序(P)。
注:校验和可以不需要,不需要则就在数据接收完之后返回NACK

②非主机模式:测量过程中,SCL线是开发状态,可进行其它通信,可以在总线上处理其它I2C总线通信任务。
当MCU要对传感器状态进行查询时,先发起一个开始信号,在发送从机地址和SDA方向位(写),此时从机匹配地址成功,则发送ACK信号,并开始测量。如果传感器完成了测量过程,并且发送ASK信号,那么MCU就可以读取相关数据。如果测量没有完成,传感器发送NACK信号,此时MCU必须重新发送启动传输时序,直至测量完成,MCU读取数据。
注意:测量的数据,温度和湿度均为两个字节。而且无论哪一种传输模式,测量的最大分辨率最大是14bit,数据的第二个字节SDA上最后两位是用来标记相关状态信息。其中bit1表示测量类型(0是温度,1是湿度)

在这里插入图片描述
灰色的区域是传感器控制的,如果不需要校验和,那么在接收完两个字节的数据之后就MCU直接发出NACK信号再接着发出停止时序§,则结束通信。

通常测量的最长时间取决于测量类型和分辨率.
在这里插入图片描述
在计算MCU通信时间时,测量温度选择最长测量时间是85ms,而测量相对湿度选择最长的时间是29ms。

传感器内部设置的默认分辨率为相对湿度12位和温度14位。SDA的输出数据被转换成两个字节的数据包,高字节MSB在前(左对齐)。每个字节后面都跟随一个应答位。两个状态位,即 LSB的后两位在进行物理计算前须置0。
计算湿度:其中SRH表示我们读取到的湿度原始数据。

计算温度:其中ST表示我们读取到的温度原始数据。
在这里插入图片描述

2.24.3.2 引脚选择

在这里插入图片描述

2.24.3.3 移植至工程

移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_sht20.c与bsp_sht20.h。见2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件bsp_sht20.c中,编写如下代码。

/********************************************************************************
  * 文 件 名: bsp_sht20.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月27日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/

#include "bsp_sht20.h"
#include "systick.h"
#include "stdio.h"

/******************************************************************
 * 函 数 名 称:SHT20_GPIO_Init
 * 函 数 说 明:对IIC引脚初始化
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC 
 * 备       注:
******************************************************************/
void SHT20_GPIO_Init(void)
{                                
                //打开SDA与SCL的引脚时钟
        rcu_periph_clock_enable(RCU_SCL);
    rcu_periph_clock_enable(RCU_SDA);

        //设置SCL引脚模式为上拉输出
        gpio_mode_set(PORT_SCL, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SCL);
        //设置引脚为开漏模式,翻转速度2MHz
        gpio_output_options_set(PORT_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO_SCL);        
        //设置引脚输出高电平SCL等待信号
        gpio_bit_write(PORT_SCL, GPIO_SCL, SET);
        
        //设置SDA引脚
        gpio_mode_set(PORT_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SDA);
        gpio_output_options_set(PORT_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO_SDA);        
        gpio_bit_write(PORT_SDA, GPIO_SDA, SET);

}


/******************************************************************
 * 函 数 名 称:IIC_Start
 * 函 数 说 明:IIC起始信号
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void IIC_Start(void)
{
        SDA_OUT();
                   
        SDA(1);
        delay_1us(5);
        SCL(1); 
        delay_1us(5);
        
        SDA(0);
        delay_1us(5);
        SCL(0);
        delay_1us(5);
                       
}
/******************************************************************
 * 函 数 名 称:IIC_Stop
 * 函 数 说 明:IIC停止信号
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void IIC_Stop(void)
{
        SDA_OUT();
        SCL(0);
        SDA(0);
        
        SCL(1);
        delay_1us(5);
        SDA(1);
        delay_1us(5);
        
}
/******************************************************************
 * 函 数 名 称:IIC_Send_Ack
 * 函 数 说 明:主机发送应答
 * 函 数 形 参:0应答  1非应答
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void IIC_Send_Ack(unsigned char ack)
{
        SDA_OUT();
        SCL(0);
        SDA(0);
        delay_1us(5);
        if(!ack) SDA(0);
        else         SDA(1);
        SCL(1);
        delay_1us(5);
        SCL(0);
        SDA(1);
}
/******************************************************************
 * 函 数 名 称:IIC_Wait_Ack
 * 函 数 说 明:等待从机应答
 * 函 数 形 参:无
 * 函 数 返 回:1=无应答   0=有应答
 * 作       者:LC
 * 备       注:无
******************************************************************/

unsigned char IIC_Wait_Ack(void)
{
        
        char ack = 0;
        unsigned char ack_flag = 10;
        SDA_IN();
    SDA(1);
        delay_1us(5);
        SCL(1);
        delay_1us(5);
        while( (GETSDA()==1) && ( ack_flag ) )
        {
                ack_flag--;
                delay_1us(5);
        }
        
        if( ack_flag <= 0 )
        {
                IIC_Stop();
                return 1;
        }
        else
        {
                SCL(0);
                SDA_OUT();
        }
        return ack;
}
/******************************************************************
 * 函 数 名 称:IIC_Write
 * 函 数 说 明:IIC写一个字节
 * 函 数 形 参:dat写入的数据
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void IIC_Write(unsigned char dat)
{
        int i = 0;
        SDA_OUT();
        SCL(0);//拉低时钟开始数据传输
        
        for( i = 0; i < 8; i++ )
        {
                SDA( (dat & 0x80) >> 7 );
                __nop();
        __nop();
        __nop();
        dat<<=1;
        delay_1us(6); 
                SCL(1);
                delay_1us(4);
                SCL(0);
                delay_1us(4);
                
        }        
}

/******************************************************************
 * 函 数 名 称:IIC_Read
 * 函 数 说 明:IIC读1个字节
 * 函 数 形 参:无
 * 函 数 返 回:读出的1个字节数据
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned char IIC_Read(void)
{
        unsigned char i,receive=0;
    SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
        {
        SCL(0);
        delay_1us(5);
        SCL(1);
        delay_1us(5);
        receive<<=1;
        if( GETSDA() )
        {        
            receive|=1;   
        }
        delay_1us(5); 
    }                
  return receive;
}

/******************************************************************
 * 函 数 名 称:SHT20_Read
 * 函 数 说 明:测量温湿度
 * 函 数 形 参:regaddr寄存器地址 regaddr=0xf3测量温度 =0x35测量湿度 
 * 函 数 返 回:regaddr=0xf3时返回温度,regaddr=0xf5时返回湿度
 * 作       者:LC
 * 备       注:无
******************************************************************/
float SHT20_Read(unsigned char regaddr)
{
    unsigned char data_H = 0;
    unsigned char data_L = 0;
    float temp = 0;
    IIC_Start();
    IIC_Write(0x80|0);
    if( IIC_Wait_Ack() == 1 ) printf("error -1\r\n");
    IIC_Write(regaddr);
    if( IIC_Wait_Ack() == 1 ) printf("error -2\r\n");
       
    do{
    delay_1us(10);
    IIC_Start();
    IIC_Write(0x80|1);
    
    }while( IIC_Wait_Ack() == 1 );

    delay_1us(20);
    
    data_H = IIC_Read();
    IIC_Send_Ack(0);
    data_L = IIC_Read();
    IIC_Send_Ack(1);
    IIC_Stop();
    
    if( regaddr == 0xf3 )
    {
        temp = ((data_H<<8)|data_L) / 65536.0 * 175.72 - 46.85;
    }
    if( regaddr == 0xf5 )
    {
        temp = ((data_H<<8)|data_L) / 65536.0 * 125.0 - 6;
    }
   return temp;
}

    

在文件bsp_sht20.h中,编写如下代码。

/********************************************************************************
  * 文 件 名: bsp_sht20.h
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2022年04月27日
  * 功能介绍:          
  ******************************************************************************
  * 开发板官网:www.lckfb.com        
*********************************************************************************/

#ifndef _BSP_SHT20_H_
#define _BSP_SHT20_H_
 
#include "gd32f4xx.h"


#define RCU_SCL  RCU_GPIOA
#define PORT_SCL GPIOA
#define GPIO_SCL GPIO_PIN_5

#define RCU_SDA  RCU_GPIOA
#define PORT_SDA GPIOA
#define GPIO_SDA GPIO_PIN_6


#define SDA_IN()  {gpio_mode_set(PORT_SDA, GPIO_MODE_INPUT,  GPIO_PUPD_PULLUP, GPIO_SDA);}        //SDA输入模式
#define SDA_OUT() {gpio_mode_set(PORT_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SDA);}  //SDA输出模式

#define SCL(BIT)  gpio_bit_write( PORT_SCL, GPIO_SCL, BIT?SET:RESET)
#define SDA(BIT)  gpio_bit_write( PORT_SDA, GPIO_SDA, BIT?SET:RESET)
#define GETSDA()  gpio_input_bit_get( PORT_SDA, GPIO_SDA)


void SHT20_GPIO_Init(void);
float SHT20_Read(unsigned char regaddr);
#endif


2.24.4 移植验证

在自己工程中的main主函数中,编写如下。

【完整代码资料见:https://pan.quark.cn/s/db9d3bda7208

移植现象:每隔一秒测量一次温湿度,并发送至串口0。

在这里插入图片描述

移植成功示例
【完整代码资料见:https://pan.quark.cn/s/db9d3bda7208

  • 28
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用GD32F470系列微控制器的硬件I2C接口来进行I2C通信。以下是一个简单的例子代码,展示了如何初始化和使用硬件I2C。 首先,需要包含相应的头文件和定义一些常量: ```c #include "gd32f4xx.h" #define I2C_SCL_PIN GPIO_PIN_6 #define I2C_SDA_PIN GPIO_PIN_7 #define I2C_GPIO_PORT GPIOB #define I2C_GPIO_CLK RCU_GPIOB #define I2C_GPIO_AF GPIO_AF_I2C1 #define I2C_SPEED 100000 // I2C速度设置为100KHz I2C_InitPara i2c_init_struct; ``` 然后,在`main`函数中进行初始化和配置: ```c int main(void) { // 使能I2C时钟 rcu_periph_clock_enable(RCU_I2C1); // 配置I2C引脚 gpio_init(I2C_GPIO_PORT, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN | I2C_SDA_PIN); gpio_af_set(I2C_GPIO_PORT, I2C_GPIO_AF, I2C_SCL_PIN | I2C_SDA_PIN); gpio_output_options_set(I2C_GPIO_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN | I2C_SDA_PIN); // 配置I2C参数 i2c_deinit(I2C1); i2c_init_struct.mode = I2C_MODE_I2C; i2c_init_struct.duty_cycle = I2C_DUTYCYCLE_2; i2c_init_struct.own_address = 0x00; i2c_init_struct.general_call = I2C_GENERALCALL_DISABLE; i2c_init_struct.addressing_mode = I2C_ADDRESSINGMODE_7BIT; i2c_init_struct.dual_address_mode = I2C_DUALADDRESS_DISABLE; i2c_init_struct.own_address2 = 0x00; i2c_init_struct.general_call2 = I2C_GENERALCALL_DISABLE; i2c_init_struct.timing = 0x00201D2B; // 根据I2C速度设置调整此参数 i2c_init(I2C1, &i2c_init_struct); // 使能I2C i2c_enable(I2C1); while (1) { // 在此处编写你的代码 } } ``` 在初始化完成后,你可以在`while`循环中编写你的I2C通信代码。例如,如果你要向从设备写入数据,可以使用以下代码: ```c uint8_t data[] = {0x01, 0x02, 0x03}; i2c_master_transmit(I2C1, slave_address, data, sizeof(data), I2C_FLAG_WRITE); ``` 如果你要从从设备读取数据,可以使用以下代码: ```c uint8_t data[4]; i2c_master_receive(I2C1, slave_address, data, sizeof(data), I2C_FLAG_READ); ``` 注意,`slave_address`是从设备的地址。 这只是一个简单的示例代码,你可以根据你的具体需求进行更多的配置和操作。请参考GD32F4xx系列微控制器的官方文档和相应的库函数手册获取更多信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值