SHT30 I2C 温湿度传感器实际应用

SHT30原理图如下

在这里插入图片描述

软件准备

  • 工作需要软件用到的是workspace IAR
  • 准备一个串口工具,用到的是sscom5.12.1

I2C

IIC总线在传送数据过程中共有四种类型信号:

开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据;

结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据;

数据传输信号:在开始条件以后,时钟信号SCL的高电平周期期间,当数据线稳定时,数据线SDA的状态表示数据有效,即数据可以被读走,开始进行读操作。在时钟信号SCL的低电平周期期间,数据线上数据才允许改变。每位数据需要一个时钟脉冲。

应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

写代码时注意I2C的时序。

IIC时序及温湿度读取 iic.c

注意时序问题!!!
每个OUT后都必须给SDA和SCL赋值!!

延时按实际情况自行定义!!



/* Includes ------------------------------------------------------------------*/
#include "iic.h"
#include <stdio.h>
#include "stm8l15x.h"
/* Private typedef -----------------------------------------------------------*/

#define BYTE unsigned char 
uint8_t am2320_data_buf[4];
#define POLYNOMIAL  0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001
/* Private define ------------------------------------------------------------*/
const u8 IIC_TX_Buffer[]={0x2c,0x06};   
uint8_t iic_recv_buf[6]={0xff,0xff,0xff,0xff,0xff,0xff};  
uint8_t WR_Flag=0;
#define IIC_Add 0x88
void I2C_delay(void)//10us
{        
   int i=2*880; //
   while(i>0) 
   { 
     i--;
   } 
}



/** 
  * @brief  IIC Init 
  * @param  A: 
  * @retval None 
  */  
void IIC_Init(void)  
{                          
   //CLK_PeripheralClockConfig (CLK_Peripheral_I2C1,ENABLE);   
   GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_Out_PP_Low_Fast);
   GPIO_Init(GPIOC, GPIO_Pin_1, GPIO_Mode_Out_PP_Low_Fast);
}

void IIC_DeInit(void){
  GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_In_FL_No_IT);
  GPIO_Init(GPIOC, GPIO_Pin_1, GPIO_Mode_In_FL_No_IT);
}

/** 
  * @brief  Set SDA Pin as Output Mode 
  * @retval None 
  */  
void SDA_OUT()
{    
  //  可能有问题
  
  GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_Out_PP_Low_Fast);   
}    
  
/** 
  * @brief  Set SDA Pin as Input Mode 
  * @retval None 
  */  
void SDA_IN()    
{    
  GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_In_PU_No_IT);   
}
  
/** 
  * @brief  read input voltage from SDA pin 
  * @retval None 
  */  
BYTE SDA_READ()  
{  
  return GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0);
} 
  
/** 
  * @brief  output high form SDA pin 
  * @retval None 
  */  
void IIC_SDA_1()  
{  
  GPIO_SetBits(GPIOC, GPIO_Pin_0);  
}  
  
/** 
  * @brief  output low form SDA pin 
  * @retval None 
  */  
void IIC_SDA_0()  
{  
  GPIO_ResetBits(GPIOC, GPIO_Pin_0);  
}  
  
/** 
  * @brief  output high form SCL pin 
  * @retval None 
  */  
void IIC_SCL_1()  
{  
GPIO_SetBits(GPIOC, GPIO_Pin_1);  
}  
  
/** 
  * @brief  output LOW form SCL pin 
  * @retval None 
  */  
void IIC_SCL_0()  
{
GPIO_ResetBits(GPIOC, GPIO_Pin_1);    
}  

u8 Test_Ack()  //注意这个函数
{ 
   u8 ACK_Flag=0;
   SDA_IN();
   IIC_SCL_0();
   IIC_SDA_1();    
   I2C_delay();
   IIC_SCL_1();
   I2C_delay();
   if(SDA_READ()==0)
     ACK_Flag = 1;
   else 
     ACK_Flag = 0;
   IIC_SCL_0();
   return ACK_Flag;
}  
  
/** 
* @brief  Simulate IIC conmunication :Create Start signal 
  * @retval None 
  */  
// I2C 启动信号
void I2C_Start(void)  
{  
    SDA_OUT();
    IIC_SDA_1();            
    IIC_SCL_1();  
    I2C_delay();  
    IIC_SDA_0();   //START:when CLK is high,DATA change form high to low   
    I2C_delay();  
    IIC_SCL_0();   //hold scl line, prepare to transmit data  
}  

//产生停止信号
void I2C_Stop()
{
   SDA_OUT();
   IIC_SDA_0();
   I2C_delay();
   IIC_SCL_1();
   I2C_delay();
   IIC_SDA_1();
}

//生成应答ACK
void Ack(void)
{  
   SDA_OUT();
   IIC_SDA_0();
   IIC_SCL_0();
   I2C_delay();
   IIC_SCL_1();
   I2C_delay();	
   IIC_SCL_0();
   IIC_SDA_1();
}

// 不生成ACK应答
void NoAck(void)
{  SDA_OUT();
   IIC_SDA_1();  
   IIC_SCL_0();
   I2C_delay();
   IIC_SCL_1();
   I2C_delay();
   IIC_SDA_1();
   IIC_SCL_0();
}

void SendData(unsigned char buffer)
{
   unsigned char BitCnt=8;
   SDA_OUT();
   do
   {
 	  IIC_SCL_0();
	  I2C_delay();
    if((buffer&0x80)==0)
       IIC_SDA_0();
    else
       IIC_SDA_1();
       IIC_SCL_1();
       I2C_delay();
       buffer=buffer<<1;
       BitCnt--;
   }
   while(BitCnt);
     IIC_SCL_0();        
}

unsigned char ReceiveData()  //可能有问题 
{
  unsigned char BitCnt=8,IIC_RX_Data=0;
  SDA_IN();
  IIC_SDA_1();           //
  do
  {
    IIC_SCL_0();
    I2C_delay();  
    IIC_RX_Data=IIC_RX_Data<<1;   //
    BitCnt--;	  
    IIC_SCL_1();
    I2C_delay();
    if(SDA_READ())
      IIC_RX_Data = IIC_RX_Data|0x01;  //
    else
      IIC_RX_Data = IIC_RX_Data&0x0fe; // 
   }
   while(BitCnt);
   IIC_SCL_0();
   return IIC_RX_Data;
}

void Delay_Ms(int16_t time)
{
	time=time*1;
	while(time>0)
	{
		I2C_delay();
		time--;
	}
}

void Waken(void)
{
    I2C_Start();
    SendData(IIC_Add);
    Test_Ack();
    Delay_Ms(2);
    I2C_Stop();	
}

static u8 WriteNByte(u8 sla,u8 *s,u8 n)
{
   unsigned char i;
   
   I2C_Start(); 
   SendData(sla);
   if(!Test_Ack())
   {	
     WR_Flag = 1;
     return(0);
   }
   for(i=0;i<n;i++)
   {
      SendData(*(s+i));
	  if(!Test_Ack())
	  {
	    WR_Flag = 1;
		return(0);
	  }
   }
   I2C_Stop();
   return(1);
}

static u8 ReadNByte(u8 Sal, u8 *p,u8 n)
{
  unsigned char i;
  I2C_Start();    
  SendData((Sal)| 0x01); 
  if(!Test_Ack())
  {
  	WR_Flag = 1;
	return(0);
  }
  I2C_delay();  
  I2C_delay();
  I2C_delay(); 
        
  for(i=0;i<n-1;i++)  
  {
     *(p+i)=ReceiveData();
     Ack(); 
  }
  *(p+n-1)=ReceiveData();        
  NoAck();
  I2C_Stop(); 
  return(1);	 
}

unsigned int CRC16(unsigned char *ptr, unsigned char len)
{
   unsigned int crc=0xffff;
   unsigned char i;
   while(len--)
   {
       crc ^=*ptr++;
       for(i=0;i<8;i++)
	   {
	       if(crc & 0x1)
		   {
		      crc>>=1;
			  crc^=0xa001;
		   }
		   else
		   {
		      crc>>=1;
		   }
	   }
   }
   return crc;
}
unsigned char CheckCRC(unsigned char *ptr,unsigned char len)
{
  unsigned int crc;
	crc=(unsigned int)CRC16(ptr,len-2);
	if(ptr[len-1]==(crc>>8) && ptr[len-2]==(crc & 0x00ff))
	{
	    return 0xff;
	}
	else
	{
	   return 0x0;
	}
}

extern int g_sys_runtime_counter;
uint8_t crc = 0;
void get_sht30(uint8_t *data)
{
	float temp, humi;
	int i;
	
	WriteNByte(IIC_Add,(uint8_t *)IIC_TX_Buffer,2);
	Delay_Ms(200); 
	ReadNByte(IIC_Add,iic_recv_buf,6);
        Delay_Ms(200);
	crc = sht30_calc_crc(iic_recv_buf, 2);
	if(crc!=iic_recv_buf[2])
		return ;
		// 注意先转换为u16,uint8_t计算可能出现负数!!
        u16 temp_h = iic_recv_buf[0] * 256;
        u16 temp_l = iic_recv_buf[1];
	temp = 175.00 * (temp_h + temp_l) / 65535.0 - 45;
        printf("temp:%f\n", temp);
	crc = sht30_calc_crc(iic_recv_buf + 3, 2);
	if(crc != iic_recv_buf[5])
	  return ;
	  // 注意先转换为u16,uint8_t计算可能出现负数!!
        u16 humi_h = iic_recv_buf[3] * 256;
        u16 humi_l = iic_recv_buf[4];
        humi = 100.00 * (humi_h + humi_l) / 65535.0;
        printf("humi:%f\n", humi);
	//humi = 100.00 * (iic_recv_buf[3] * 256 + iic_recv_buf[4]) / 65535.0;
	if(temp > 0)
	{
		am2320_data_buf[2] = (uint16_t)(temp * 10) >> 8; 
	}else
	{
		am2320_data_buf[2] = (uint16_t)(temp * 10) | 0x80;
	}
	am2320_data_buf[0] = (uint16_t)(humi * 10) >> 8;
	am2320_data_buf[1] = (uint16_t)(humi * 10) & 0xff;
	am2320_data_buf[3] = (uint16_t)(temp * 10) & 0xff;
	
	data[0] = am2320_data_buf[0];
	data[1] = am2320_data_buf[1];
	data[2] = am2320_data_buf[2];
	data[3] = am2320_data_buf[3];
        
 
}

uint8_t sht30_calc_crc(uint8_t* data, uint8_t len)
{
	uint8_t bit;        // bit mask
	uint8_t crc = 0xFF; // calculated checksum
	uint8_t byteCtr;    // byte counter

	// calculates 8-Bit checksum with given polynomial
	for(byteCtr = 0; byteCtr < len; byteCtr++)
	{
		crc ^= (data[byteCtr]);
		for(bit = 8; bit > 0; --bit)
		{
			if(crc & 0x80)
			crc = (crc << 1) ^ POLYNOMIAL;
			else
			crc = (crc << 1);
		}
	}
	return crc;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值