小熊派GD32开发(7)— 使用软件模拟I2C读取SHT30温湿度传感器

小熊派GD32开发(7)— 使用软件模拟I2C读取SHT30温湿度传感器

一、编写软件模拟I2C驱动程序

在【Devices】下新建soft_i2c.csoft_i2c.h文件,首先,查看硬件原理图,可以看到,IIC_SCL使用PB6引脚,IIC_SDA使用PB7引脚,将这两个引脚初始化即可:

/* 软件模拟IIC引脚初始化
 * IIC_SCL --> PB6
 * IIC_SDA --> PB7 */
void IIC_Init(void)
{
    rcu_periph_clock_enable(RCU_GPIOB);	/* 使能GPIOB时钟 */

	/* 配置IIC_SCL引脚为推挽输出 */ 
    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
	/* 配置IIC_SDA引脚为推挽输出 */ 
    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);

    gpio_bit_set(GPIOB, GPIO_PIN_6);
	gpio_bit_set(GPIOB, GPIO_PIN_7);
} 

因为模拟IIC通信里需要用到us延时,所以,编写一个us延时函数

/* 描述:us级延时函数
 * 参数nus:需要延时的us数
 * 返回值:无*/		    								   
void delay_us(uint32_t nus)
{		
	uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD;		/* 滴答定时器的重装载值 */
    ticks = nus * 120; 						/* 需要的节拍数 */
    told = SysTick->VAL;        			/* 刚进入时的计数器值 */

    while(1)
    {
        tnow = SysTick->VAL;

        if(tnow != told)
        {
            if(tnow < told)tcnt += told - tnow;
            else tcnt += reload - tnow + told;
            if(tcnt >= ticks)break;			 /* 时间超过/等于要延迟的时间,则退出. */
			told = tnow;
        }
    }  
}

模拟IIC通信的函数如下

/* 描述:启动I2C总线,即发送I2C起始条件. 
 * 参数:  无
 * 返回值:无						*/
void IIC_Start(void)
{
	SDA_OUT();
	IIC_SDA(1);
	IIC_SCL(1);
	delay_us(4);	
	IIC_SDA(0);
	delay_us(4); 
	IIC_SCL(0);
}
 
/* 描述:结束I2C总线,即发送I2C结束条件.  
 * 参数:  无
 * 返回值:无						*/
void IIC_Stop(void)
{
	SDA_OUT();
	IIC_SCL(0);
	IIC_SDA(0);  
	delay_us(4);	
	IIC_SCL(1);
	delay_us(4);
	IIC_SDA(1);
	delay_us(4);
}
 
/* 描述:发送应答 ACK 
 * 参数:  无
 * 返回值:无		*/
void IIC_ACK(void)
{
	SDA_OUT();
	IIC_SCL(0);
	delay_us(2); 
	IIC_SDA(0);
	delay_us(2);     
	IIC_SCL(1);
	delay_us(2);                  
	IIC_SCL(0);                     
	delay_us(1);    
}

/* 描述:发送非应答 NACK 
 * 参数:  无
 * 返回值:无		*/
void IIC_NACK(void)
{
	SDA_OUT();
	IIC_SCL(0);
	delay_us(2); 
	IIC_SDA(1);
	delay_us(2);      
	IIC_SCL(1);
	delay_us(2);                   
	IIC_SCL(0);                     
	delay_us(1);    
}

/* 描述:等待ACK 
 * 参数:  无
 * 返回值:等待应答返回0,没有等待到应答返回1	*/
uint8_t IIC_wait_ACK(void)
{
    uint8_t t = 200;
    SDA_OUT();
    IIC_SDA(1);		
    delay_us(1);
    IIC_SCL(0);
    delay_us(1); 
    SDA_IN();		/* 数据发送完后释放数据线,准备接收应答位 */
    delay_us(1); 
    while(READ_SDA)	/* 等待IIC应答*/
    {
		t--;
		delay_us(1); 
		if(t==0)
		{
			IIC_SCL(0);
			return 1;
		}
		delay_us(1); 
    }
    delay_us(1);      
    IIC_SCL(1);
    delay_us(1);
    IIC_SCL(0);             
    delay_us(1);    
    return 0;	
}

/* 描述:一个字节数据发送函数               
 * 参数:  无
 * 返回值:无		*/
void IIC_SendByte(uint8_t byte)
{
	uint8_t BitCnt;
	SDA_OUT();
	IIC_SCL(0);
	for(BitCnt=0;BitCnt<8;BitCnt++) /* 要传送的数据长度为8位 */
	{
		if(byte&0x80) IIC_SDA(1);	/* 判断发送位 */
		else IIC_SDA(0); 
		byte<<=1;
		delay_us(2); 
		IIC_SCL(1);
		delay_us(2);
		IIC_SCL(0);
		delay_us(2);
	}
}

/* 描述:一个字节数据接收函数               
 * 参数:  无
 * 返回值:接收到的字节数据		*/   
uint8_t IIC_RcvByte(void)
{
	uint8_t retc;
	uint8_t BitCnt;
	retc=0; 
	SDA_IN();			/* 设置数据线为输入方式 */
	delay_us(1);                    
	for(BitCnt=0;BitCnt<8;BitCnt++)
	{  
		IIC_SCL(0);		/* 设置时钟线为低,准备接收数据位	*/
		delay_us(2);               
		IIC_SCL(1);		/* 设置时钟线为高使数据线上数据有效  */              
		retc=retc<<1;
		if(READ_SDA) retc |=1;	/* 读数据位,接收的数据位放入retc中 */
		delay_us(1);
	}
	IIC_SCL(0);    
	return(retc);
}

soft_i2c.h文件如下,

#ifndef __SOFT_I2C_H_
#define __SOFT_I2C_H_

#include "gd32f30x.h"

/* 设置IIC_SDA的方向,输入还是输出 */
#define SDA_IN()  {GPIO_CTL0(GPIOB)&=~GPIO_MODE_MASK(7);GPIO_CTL0(GPIOB)|=GPIO_MODE_SET(7,0x8);}//PB9输入模式
#define SDA_OUT() {GPIO_CTL0(GPIOB)&=~GPIO_MODE_MASK(7);GPIO_CTL0(GPIOB)|=GPIO_MODE_SET(7,0x3);}//PB9输出模式

/* 设置SCL和SDA输出电平,以及读取SDA电平 */
#define IIC_SCL(n) (n?gpio_bit_set(GPIOB, GPIO_PIN_6):gpio_bit_reset(GPIOB, GPIO_PIN_6))
#define IIC_SDA(n) (n?gpio_bit_set(GPIOB, GPIO_PIN_7):gpio_bit_reset(GPIOB, GPIO_PIN_7))
#define READ_SDA	gpio_input_bit_get(GPIOB,GPIO_PIN_7)

void IIC_Init(void); 			/* 软件模拟IIC引脚初始化 */
void IIC_Start(void);			/* 启动I2C总线,即发送I2C起始条件 */
void IIC_Stop(void);			/* 结束I2C总线,即发送I2C结束条件 */
void IIC_ACK(void);				/* 发送应答 ACK */
void IIC_NACK(void);			/* 发送非应答 NACK */
uint8_t IIC_wait_ACK(void);		/* 等待ACK */
void IIC_SendByte(uint8_t byte);/* 一个字节数据发送函数 */ 
uint8_t IIC_RcvByte(void); 		/* 一个字节数据接收函数 */

#endif

二、编写SHT30应用程序

在【Devices】下新建sht3x.csht3x.h文件,头文件如下

#ifndef __SHT3X_H_
#define __SHT3X_H_

#include "gd32f30x.h"
#include "systick.h"

uint8_t SHT3x_Init(void);	/* 描述:SHT3x初始化函数  */
uint8_t SHT3x_ReadSerialNumber(uint32_t* serialNumber);
uint8_t SHT3x_Get_Humiture_single(double *Tem_val,double *Hum_val);	/* 单次获取 */
uint8_t SHT3x_Get_Humiture_periodic(double *Tem_val,double *Hum_val); /* 周期获取 */

/* 枚举SHT3x命令列表 */
typedef enum
{
    /* 软件复位命令 */
    SOFT_RESET_CMD = 0x30A2,	
    /* 单次测量模式
    命名格式:Repeatability_CS_CMD
    CS: Clock stretching */
    HIGH_ENABLED_CMD    = 0x2C06,
    MEDIUM_ENABLED_CMD  = 0x2C0D,
    LOW_ENABLED_CMD     = 0x2C10,
    HIGH_DISABLED_CMD   = 0x2400,
    MEDIUM_DISABLED_CMD = 0x240B,
    LOW_DISABLED_CMD    = 0x2416,

    /* 周期测量模式
    命名格式:Repeatability_MPS_CMD
    MPS:measurement per second */
    HIGH_0_5_CMD   = 0x2032,
    MEDIUM_0_5_CMD = 0x2024,
    LOW_0_5_CMD    = 0x202F,
    HIGH_1_CMD     = 0x2130,
    MEDIUM_1_CMD   = 0x2126,
    LOW_1_CMD      = 0x212D,
    HIGH_2_CMD     = 0x2236,
    MEDIUM_2_CMD   = 0x2220,
    LOW_2_CMD      = 0x222B,
    HIGH_4_CMD     = 0x2334,
    MEDIUM_4_CMD   = 0x2322,
    LOW_4_CMD      = 0x2329,
    HIGH_10_CMD    = 0x2737,
    MEDIUM_10_CMD  = 0x2721,
    LOW_10_CMD     = 0x272A,
	/* 周期测量模式读取数据命令 */
	READOUT_FOR_PERIODIC_MODE = 0xE000,
	/* 读取传感器编号命令 */
	READ_SERIAL_NUMBER = 0x3780,
} SHT3X_CMD;

#endif

sht3x.c文件中,先将读写标志以及SHT30的地址设置好:

#define write 0
#define read  1

uint8_t addr = 0x44;	//设置传感器地址 

然后就是发送命令和接收数据函数

/* 描述:向SHT30发送一条16bit指令 
 * 参数cmd:SHT30指令(在SHT30_MODE中枚举定义)
 * 返回值:发送成功返回0,发送失败返回1 		*/
static uint8_t SHT3x_Send_Cmd(SHT3X_CMD cmd)
{
    uint8_t cmd_buffer[2];
	uint8_t ret;
    cmd_buffer[0] = cmd >> 8;
    cmd_buffer[1] = cmd;
	
	IIC_SendByte(addr<<1 | write);	/* 写7位I2C设备地址加0作为写取位 */
	ret = IIC_wait_ACK();
	IIC_SendByte(cmd_buffer[0]);
	ret |= IIC_wait_ACK();
	IIC_SendByte(cmd_buffer[1]);
	ret |= IIC_wait_ACK();
	
	return ret;
}

/* 描述:从SHT3x读取数据 
 * 参数data_len:读取多少个字节数据
 * 参数data_arr:读取的数据存放在一个数组里
 * 返回值:读取成功返回0,读取失败返回1 
*/
static uint8_t SHT3x_Recv_Data(uint8_t data_len, uint8_t* data_arr)
{
	uint8_t ret,i;
	IIC_SendByte(addr<<1 | read);	/* 写7位I2C设备地址加1为读取位 */
	ret = IIC_wait_ACK();
	if(ret != 0) return 1;
	for(i = 0; i < (data_len - 1); i++)
	{
		data_arr[i]=IIC_RcvByte();
		IIC_ACK();
	}
	data_arr[i]=IIC_RcvByte();
	IIC_NACK();

	return 0;
}

接下来我们测试一下读取传感器的编号

/* 描述:读取传感器编号
 * 参数:存储编号数据的指针
 * 返回值:0-读取成功,1-读取失败 */
uint8_t SHT3x_ReadSerialNumber(uint32_t* serialNumber)
{ 
	uint8_t ret = 0; 
	uint8_t Num_buf[4] = {0xFF,0xFF,0xFF,0xFF};
	
	IIC_Start();
	SHT3x_Send_Cmd(READ_SERIAL_NUMBER);
	IIC_Stop();
	delay_1ms(10);	/* 有问题时需要适当延长!!!!!!*/
	IIC_Start();
	ret = SHT3x_Recv_Data(4,Num_buf);
	IIC_Stop();
	
	*serialNumber = ((Num_buf[0] << 24) | (Num_buf[1] << 16) |(Num_buf[2] << 8) |(Num_buf[3]));
	if(0xFF == *serialNumber) return 1; 
	return ret; 
}

在main函数中调用,编译下载运行,可以得到其编号:
在这里插入图片描述
然后我们将其设置为周期读取模式,周期读取数据

/* 描述:数据CRC校验
 * 参数message:需要校验的数据
 * 参数initial_value:crc初始值
 * 返回值:计算得到的CRC码 */
#define CRC8_POLYNOMIAL 0x131
uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value)
{
    uint8_t  remainder;	    //余数
    uint8_t  i = 0, j = 0;  //循环变量

    /* 初始化 */
    remainder = initial_value;
    for(j = 0; j < 2;j++)
    {
        remainder ^= message[j];
        /* 从最高位开始依次计算  */
        for (i = 0; i < 8; i++)
        {
            if (remainder & 0x80)
                remainder = (remainder << 1)^CRC8_POLYNOMIAL;
            else
                remainder = (remainder << 1);
        }
    }
    /* 返回计算的CRC码 */
    return remainder;
}

/* 描述:温湿度数据获取函数,周期读取,注意,需要提前设置周期模式   
 * 参数Tem_val:存储温度数据的指针, 温度单位为°C
 * 参数Hum_val:存储湿度数据的指针, 温度单位为%
 * 返回值:0-读取成功,1-读取失败
********************************************************************/
uint8_t SHT3x_Get_Humiture_periodic(double *Tem_val,double *Hum_val)
{
	uint8_t ret=0;
	uint8_t buff[6];
	uint16_t tem,hum;
	double Temperature=0;
	double Humidity=0;

	IIC_Start();
	ret = SHT3x_Send_Cmd(READOUT_FOR_PERIODIC_MODE);	
	IIC_Start();
	ret = SHT3x_Recv_Data(6,buff);
	IIC_Stop();
	
	/* 校验温度数据和湿度数据是否接收正确 */
	if(CheckCrc8(buff, 0xFF) != buff[2] || CheckCrc8(&buff[3], 0xFF) != buff[5])
	{	
		printf("CRC_ERROR,ret = 0x%x\r\n",ret);
		return 1;
	}
		
	/* 转换温度数据 */
	tem = (((uint16_t)buff[0]<<8) | buff[1]);//温度数据拼接
	Temperature= (175.0*(double)tem/65535.0-45.0) ;	// T = -45 + 175 * tem / (2^16-1)
	
	/* 转换湿度数据 */
	hum = (((uint16_t)buff[3]<<8) | buff[4]);//湿度数据拼接
	Humidity= (100.0*(double)hum/65535.0);			// RH = hum*100 / (2^16-1)
	
	/* 过滤错误数据 */
	if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))
	{
		*Tem_val = Temperature;
		*Hum_val = Humidity;
		return 0;
	}
	else
		return 1;
}

在主函数中,每隔一秒读取一次数据

	if( 0 == SHT3x_Init())
		printf("SHT3x_Init OK \r\n");
	else
		printf("SHT3x_Init ERR \r\n");
	
	while(1)
	{
		delay_1ms(1000);
		if(SHT3x_Get_Humiture_periodic(&Tem_val,&Hum_val) == 0)
			printf("Tem_val:%f C,\t&Hum_val:%f %%Rh\r\n",Tem_val,Hum_val);
		else
			printf("Get_Humiture ERR\r\n");
	}

编译下载运行,可以得到,读取数据成功
在这里插入图片描述
另外,也可以单次读取

/* 描述:温湿度数据获取函数,单次获取
 * 参数Tem_val:存储温度数据的指针, 温度单位为°C
 * 参数Hum_val:存储湿度数据的指针, 温度单位为%
 * 返回值:0-读取成功,1-读取失败
********************************************************************/
uint8_t SHT3x_Get_Humiture_single(double *Tem_val,double *Hum_val)
{
	uint8_t ret=0;
	uint8_t buff[6];
	uint16_t tem,hum;
	double Temperature=0;
	double Humidity=0;

	IIC_Start();
	SHT3x_Send_Cmd(HIGH_ENABLED_CMD);
	IIC_Stop();
	
	delay_1ms(50);
	
	IIC_Start();
	ret = SHT3x_Recv_Data(6,buff);
	IIC_Stop();
	
	/* 校验温度数据和湿度数据是否接收正确 */
	if(CheckCrc8(buff, 0xFF) != buff[2] || CheckCrc8(&buff[3], 0xFF) != buff[5])
	{	
		printf("CRC_ERROR,ret = 0x%x\r\n",ret);
		return 1;
	}
		
	/* 转换温度数据 */
	tem = (((uint16_t)buff[0]<<8) | buff[1]);//温度数据拼接
	Temperature= (175.0*(double)tem/65535.0-45.0) ;	// T = -45 + 175 * tem / (2^16-1)
	
	/* 转换湿度数据 */
	hum = (((uint16_t)buff[3]<<8) | buff[4]);//湿度数据拼接
	Humidity= (100.0*(double)hum/65535.0);			// RH = hum*100 / (2^16-1)
	
	/* 过滤错误数据 */
	if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))
	{
		*Tem_val = Temperature;
		*Hum_val = Humidity;
		return 0;
	}
	else
		return 1;
}

三、上传到云端

结合之前的代码,将其温湿度数据上传到EMQ,5秒上报一次:

#include "gd32f30x.h"
#include "systick.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "app_nbiot.h"
#include "soft_i2c.h"
#include "sht3x.h"

extern uint8_t update_flag;
extern int udp_socket;

int main(void)
{
//	uint32_t sn;
	char res_buf[128];
	char data_buf[128];
	int times = 0;
	double Tem_val,Hum_val;
	systick_config();	/* 配置系统时钟 */
	LED_init();			/* 初始化 LED */	
	uart_init(115200);	/* 初始化USART0 */
	uart1_init(9600);	/* 初始化USART1 */
	timer5_init(50000,12000);	/* 定时5000ms*/
	
	printf("Hello world! \r\n");
	
	while(NB_Start())
	{
		u1_printf("AT+NRB\r\n");	/* 重启*/
		while(USART1_RX_NUM == 0) 
			;
		if(USART1_RX_NUM >0)
		{
			printf("NBIoT: %s\r\n",rx1_date_buf);
			USART1_RX_NUM = 0;
		}
	}
	printf("start OK\r\n");
	
//	IIC_Init();
//	if( 0 == SHT3x_ReadSerialNumber(&sn))
//		printf("ReadSerialNumber OK sn = 0x%x \r\n",sn);
//	else
//		printf("ReadSerialNumber ERR \r\n");
	
	if( 0 == SHT3x_Init())
		printf("SHT3x_Init OK \r\n");
	else
		printf("SHT3x_Init ERR \r\n");
	
	while(1)
	{	
		if(update_flag  == 1)
		{
			update_flag = 0;
			times++;
			LED(times%2);
			/* 采集温湿度数据然后上传到EMQ */
			if(SHT3x_Get_Humiture_periodic(&Tem_val,&Hum_val) == 0)
			{
				sprintf(data_buf,"{\"temperature\":%6.2lf ,\"humidity\":%6.2lf }",Tem_val,Hum_val);
				NB_Send_data("39.96.35.207", "SHT3x", data_buf);
				printf("%s\r\nData send to EMQ...\r\n",data_buf);
			}
			else
				printf("Get_Humiture ERR\r\n");
		}
		if(USART1_RX_NUM >0)
		{
			USART1_RX_NUM = 0;
			if(Find_string((char *)rx1_date_buf,"+NSONMI:","\r\n",res_buf)>0)
			{
				u1_printf("AT+NSORF=%d,%d\r\n",udp_socket,res_buf[2]-'0');
			}
			printf("NBIOT: %s\r\n",rx1_date_buf);			
		}
		if(USART_RX_NUM >0)
		{
			USART_RX_NUM = 0;
			u1_printf("%s",rx0_date_buf);			
		}
	}
}

编译下载运行,可以看到,在EMQ上接收到数据
在这里插入图片描述

四、代码

完整代码我存放在码云,可以查看:https://gitee.com/william_william/GD32.git

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是模拟I2C实现SHT20温湿度传感器的no hold master的读取度的程序示例: ```c #include <stdio.h> #include <stdlib.h> #include <wiringPi.h> #define I2C_SDA_PIN 2 #define I2C_SCL_PIN 3 #define SHT20_I2C_ADDR 0x40 // 定义SHT20芯片命令 #define SHT20_MEASURE_TEMP_NO_HOLD 0xF3 // I2C总线初始化 void i2c_init() { wiringPiSetup(); pinMode(I2C_SDA_PIN, OUTPUT); pinMode(I2C_SCL_PIN, OUTPUT); } // I2C总线开始信号 void i2c_start() { digitalWrite(I2C_SDA_PIN, HIGH); digitalWrite(I2C_SCL_PIN, HIGH); delayMicroseconds(5); digitalWrite(I2C_SDA_PIN, LOW); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); } // I2C总线停止信号 void i2c_stop() { digitalWrite(I2C_SCL_PIN, LOW); digitalWrite(I2C_SDA_PIN, LOW); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, HIGH); delayMicroseconds(5); digitalWrite(I2C_SDA_PIN, HIGH); delayMicroseconds(5); } // I2C总线发送一个字节数据 void i2c_write_byte(unsigned char data) { int i; for (i = 0; i < 8; i++) { digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); if (data & 0x80) { digitalWrite(I2C_SDA_PIN, HIGH); } else { digitalWrite(I2C_SDA_PIN, LOW); } delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, HIGH); delayMicroseconds(5); data <<= 1; } digitalWrite(I2C_SCL_PIN, LOW); digitalWrite(I2C_SDA_PIN, HIGH); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, HIGH); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); } // I2C总线读取一个字节数据 unsigned char i2c_read_byte() { unsigned char data = 0; int i; digitalWrite(I2C_SDA_PIN, HIGH); for (i = 0; i < 8; i++) { data <<= 1; digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, HIGH); delayMicroseconds(5); if (digitalRead(I2C_SDA_PIN)) { data |= 0x01; } delayMicroseconds(5); } digitalWrite(I2C_SCL_PIN, LOW); digitalWrite(I2C_SDA_PIN, HIGH); delayMicroseconds(5); return data; } // 从SHT20芯片读取度 float sht20_read_temperature() { float temperature = 0; // 发送开始信号 i2c_start(); // 发送设备地址和写命令 i2c_write_byte(SHT20_I2C_ADDR << 1); // 发送读取度命令 i2c_write_byte(SHT20_MEASURE_TEMP_NO_HOLD); // 等待转换完成 delay(100); // 发送开始信号 i2c_start(); // 发送设备地址和读命令 i2c_write_byte((SHT20_I2C_ADDR << 1) | 0x01); // 读取度数据的高字节 unsigned char temp_h = i2c_read_byte(); // 发送ACK信号 digitalWrite(I2C_SDA_PIN, LOW); digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, HIGH); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); // 读取度数据的低字节 unsigned char temp_l = i2c_read_byte(); // 发送NACK信号 digitalWrite(I2C_SDA_PIN, HIGH); digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, HIGH); delayMicroseconds(5); digitalWrite(I2C_SCL_PIN, LOW); delayMicroseconds(5); // 计算度值 int raw_temp = ((unsigned int)temp_h << 8) | temp_l; temperature = -46.85 + 175.72 * ((float)raw_temp / 65536.0); // 发送停止信号 i2c_stop(); return temperature; } int main() { // 初始化I2C总线 i2c_init(); // 读取度并打印 float temperature = sht20_read_temperature(); printf("Temperature: %.2f\n", temperature); return 0; } ``` 这个程序使用了树莓的wiringPi库来控制GPIO口模拟I2C总线,通过发送SHT20芯片的控制命令来读取度数据。请根据具体硬件及引脚连接进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值