STM32 采集SHT10传感器数据(非float)

来源:互联网 发布:config.inc.php下载 编辑:程序博客网 时间:2024/05/24 15:41

本来想在网上直接load一个sht10驱动就直接能用用了,没想到太天真了。

非但没有stm32L0cube这个库的程序而且大部分还是使用浮点运算的,你妹的,stm32好多都是不支持浮点运算的呀。所以只好自己搞了。

以下为sth10常规的时序,抠出来的没啥好说

  1、接口定义:
  SHT10的接口定义如下图所示:
                                                             
           如上图所示,1脚为GND,4脚为VDD。它的供电电压范围为2.4~5.5V,建议的电压为3.3V,在电源引脚(VDD、GND)之间必须加上一个0.1uf的电容,应于去耦滤波用。它的2脚DATA为数据引脚,3脚SCK为时钟控制引脚,没有发现这两个引脚很像IIC所使用的引脚功能?没错,这个传感器确实可以认为是IIC接口,但是又有却别。该传感器不能按照IIC的协议编址,但是,如果IIC总线上没有挂接别的元件,传感器可以直接连到IIC总线上,但是单片机必须按照传感器的协议工作。传感器与单片机的接线如下图所示:
                                    

    2、传感器的通讯
      
     2.1、“启动传输”时序
用一组“启动传输”时序来完成数据传输的初始化。它包括:当SCK时钟高电平时DATA翻转为低电平,紧接着SCK变成低电平,随后是在SCK时钟高电平,随后是在SCK时钟高电平DATA翻转位高电平。时序如下:

                       

     2.2、复位时序
如果与SHT1x 通讯中断,可通过下列信号时序复位:当DATA 保持高电平时,触发SCK 时钟9 次或更多。时序图如下:
                    
    2.3、命令集
传感器的命令包含三个地址位(目前只支持000,这就是他只能挂接在空闲的IIC总线上的原因)和五个命令位。。SHT1x 会以下述方式表示已正确地接收到指令:在第8 个SCK 时钟的下降沿之后,将DATA 下拉为低电平(ACK 位)。在第9 个SCK 时钟的下降沿之后,释放DATA(恢复高电平)。命令集如下:
                            

     2.4、温湿度测量
发布一组测量命令(‘00000101’表示相对湿度RH,‘00000011’表示温度T)后,控制器要等待测量结束。这个过程需要大约20/80/320ms,分别对应8/12/14bit 测量。确切的时间随内部晶振速度,最多可能有-30%的变化。。SHT1x 通过下拉DATA 至低电平并进入空闲模式,表示测量的结束。控制器在再次触发SCK 时钟前,必须等待这个“数据备妥”信号来读出数据。检测数据可以先被存储,这样控制器可以继续执行其它任务在需要时再读出数据。
在收到CRC 的确认位之后,表明通讯结束。如果不使用CRC-8 校验,控制器可以在测量值LSB 后,通过保持ACK高电平终止通讯。在测量和通讯完成后,SHT1x 自动转入休眠模式。

    2.5、状态寄存器
SHT1x 的某些高级功能可以通过给状态寄存器发送指令来实现,如选择测量分辨率,电量不足提醒,使用 OTP 加载或启动加热功能等。状态寄存器度、写如下:


状态寄存器写


状态寄存器读

状态寄存器的具体描述如下表所示:



测量分辨率:默认分辨率 14bit (温度) 和 12bit (湿度) 可以被降低为 12 和 8bit. 尤其适用于要求测量速度极高或者功耗极低的应用。
电量不足检测功能:在电压不足 2.47V 发出警告。精度为±0.05 V。
加热:可通过向状态寄存器内写入命令启动传感器内部加热器.。加热器可以使传感器的温度高于周围环境 5 – 10°C12 。功耗大约为 8mA @ 5V 。
OPT加载:开启此功能,标定数据将在每次测量前被上传到寄存器。如果不开启此功能,可减少大约 10ms的测量时间。
上面的寄存器如果没有什么特殊要求或应用于特定的场合,则无需配置,选择默认就可以了。

     2.6、通讯过程
传感器的通讯过程为:发送”启动传输“时序,初始化传感器——>发送命令——>等待传感器应答,及测量结束——>接收传感器的16位数据值——>接收8为的CRC校验数据——>休眠,等待下一次传输开始。
传输的过程的测量时序可以由下图示意:

  上图中 TS = 传输开始, MSB = 高有效字节,LSB =低有效字节, LSb = 低有效位。
下面举个实际测量时的相对湿度测量时序例子。时序如下:

这张图可以知道:我们接收到的数据数值为”0000 0100 0011 0001“ = 1073 = 35.50% RH (位含温度补偿),至于怎么计算的,请接着往下看。

     2.7、信号转化  
       2.7.1 温度的转化
设T 2 1 SOt为从传感器上读出来的测量数值,我们需要用下面的公式将测量数值转换成整整的温度值。
T = d1 + d2 * SOt  (其中d1,d2的值根据实际情况选择,选项如下)



      2.7.2 湿度的转换 
湿度的转换公式如下:。其中湿度的转化参数如下选择:根据采样的精度不同而不同。

99%以上的湿度已经接近饱和必须经过处理显示100%RH13.请注意 湿度传感器对电压无依赖性。测量值与相对湿度的转化如下图所示:

  相对湿度根据上面的参数与公式算出来之后,还需要考虑当前环境温度而进行适当的补偿。补偿的公式及其参数选择如下:

头文件部分
/* Define to prevent recursive inclusion -------------------------------------*/#ifndef __SHT10_H#define __SHT10_H/* Includes ------------------------------------------------------------------*/#include "stm32l0xx_hal.h"#include "stm32l0xx_nucleo.h"#define SHT10_DATA_PINGPIO_PIN_6#define SHT10_SCK_PINGPIO_PIN_7#define SHT10_GPIO_PORTGPIOA#define DATA_PIN_HIGH()HAL_GPIO_WritePin(SHT10_GPIO_PORT,SHT10_DATA_PIN,1)#define DATA_PIN_LOW()HAL_GPIO_WritePin(SHT10_GPIO_PORT,SHT10_DATA_PIN,0)#define SCK_PIN_HIGH()HAL_GPIO_WritePin(SHT10_GPIO_PORT,SHT10_SCK_PIN,1)#define SCK_PIN_LOW()HAL_GPIO_WritePin(SHT10_GPIO_PORT,SHT10_SCK_PIN,0)#define DATA_VALUE()HAL_GPIO_ReadPin(SHT10_GPIO_PORT,SHT10_DATA_PIN)extern void SHT10_init(void);extern void GetEnvInfo(uint16_t *humi_val_real,uint16_t *temp_val_real);/* Exported types ------------------------------------------------------------*//* Exported constants --------------------------------------------------------*//* Exported macro ------------------------------------------------------------*//* Exported functions ------------------------------------------------------- */#endif /* __MAIN_H *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/



c文件

#include "main.h"#include "sht10.h"typedef union { unsigned int i; float f; } value; //----------------------------------------------------------------------------------// modul-var //----------------------------------------------------------------------------------enum {TEMP,HUMI}; #define noACK 0 #define ACK 1 //adr command r/w #define STATUS_REG_W 0x06 //000 0011 0 #define STATUS_REG_R 0x07 //000 0011 1 #define MEASURE_TEMP 0x03 //000 0001 1 #define MEASURE_HUMI 0x05 //000 0010 1 #define RESET 0x1e //000 1111 0 static GPIO_InitTypeDef  GPIO_InitSckStruct;static GPIO_InitTypeDef  GPIO_InitDataStruct;void SHT10_Dly(void)  {      uint16_t i;      for(i = 500; i > 0; i--);  }  void SHT10_DATAOut(void)  {  GPIO_InitDataStruct.Mode  = GPIO_MODE_OUTPUT_PP;GPIO_InitDataStruct.Pull  = GPIO_PULLUP;GPIO_InitDataStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitDataStruct.Pin = SHT10_DATA_PIN;HAL_GPIO_Init(SHT10_GPIO_PORT, &GPIO_InitDataStruct);}      /*************************************************************   Function   :SHT10_DATAIn     Description:设置DATA引脚为输入   Input      : none           return     : none     *************************************************************/  void SHT10_DATAIn(void)  {      //PD0 DATA 浮动输入   GPIO_InitDataStruct.Mode  = GPIO_MODE_INPUT;GPIO_InitDataStruct.Pull  = GPIO_NOPULL;GPIO_InitDataStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitDataStruct.Pin = SHT10_DATA_PIN;HAL_GPIO_Init(SHT10_GPIO_PORT, &GPIO_InitDataStruct);}    /*************************************************************   Function   :SHT10_TransStart     Description:开始传输信号,时序如下:                      _____         ________                DATA:      |_______|                          ___     ___                SCK : ___|   |___|   |______    Input      : none           return     : none     *************************************************************/  void SHT10_TransStart(void)  {      SHT10_DATAOut();              //设置DATA数据线为输出        //SHT10_DATA_H();  DATA_PIN_HIGH();    //SHT10_SCK_L();  SCK_PIN_LOW();    SHT10_Dly();      //SHT10_SCK_H();   SCK_PIN_HIGH();    SHT10_Dly();      //SHT10_DATA_L(); DATA_PIN_LOW();      SHT10_Dly();      //SHT10_SCK_L();  SCK_PIN_LOW();    SHT10_Dly();      //SHT10_SCK_H();     SCK_PIN_HIGH();    SHT10_Dly();      //SHT10_DATA_H();  DATA_PIN_HIGH();     SHT10_Dly();      //SHT10_SCK_L();   SCK_PIN_LOW();   }  void SHT10_ConReset(void)  {      uint8_t i;        SHT10_DATAOut();        //SHT10_DATA_H();  DATA_PIN_HIGH();    //SHT10_SCK_L();  SCK_PIN_LOW();      for(i = 0; i < 9; i++)         //触发SCK时钟9c次      {          //SHT10_SCK_H();          SCK_PIN_HIGH();        SHT10_Dly();          //SHT10_SCK_L();  SCK_PIN_LOW();        SHT10_Dly();      }      SHT10_TransStart();           //启动传输  }  void SHT10_init(void){GPIO_InitSckStruct.Mode  = GPIO_MODE_OUTPUT_PP;GPIO_InitSckStruct.Pull  = GPIO_PULLUP;GPIO_InitSckStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitSckStruct.Pin = SHT10_SCK_PIN;HAL_GPIO_Init(SHT10_GPIO_PORT, &GPIO_InitSckStruct);GPIO_InitDataStruct.Mode  = GPIO_MODE_OUTPUT_PP;GPIO_InitDataStruct.Pull  = GPIO_PULLUP;GPIO_InitDataStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitDataStruct.Pin = SHT10_DATA_PIN;HAL_GPIO_Init(SHT10_GPIO_PORT, &GPIO_InitDataStruct);SHT10_ConReset();}uint8_t SHT10_WriteByte(uint8_t value)  {      uint8_t i;uint8_t err = 0;            SHT10_DATAOut();              //设置DATA数据线为输出        for(i = 0x80; i > 0; i /= 2)  //写1个字节      {          if(i & value)              DATA_PIN_HIGH();          else              DATA_PIN_LOW();          SHT10_Dly();          SCK_PIN_HIGH();          SHT10_Dly();          SCK_PIN_LOW();          SHT10_Dly();      }      SHT10_DATAIn();               //设置DATA数据线为输入,释放DATA线      SCK_PIN_HIGH();      err = DATA_VALUE();         //读取SHT10的应答位      SCK_PIN_LOW();        return err;  }  uint8_t SHT10_ReadByte(uint8_t Ack)  {      uint8_t i;uint8_t val = 0;        SHT10_DATAIn();               //设置DATA数据线为输入      for(i = 0x80; i > 0; i /= 2)  //读取1字节的数据      {          SHT10_Dly();          SCK_PIN_HIGH();          SHT10_Dly();          if(DATA_VALUE())              val = (val | i);          SCK_PIN_LOW();      }      SHT10_DATAOut();              //设置DATA数据线为输出      if(Ack)          DATA_PIN_LOW();           //应答,则会接下去读接下去的数据(校验数据)      else          DATA_PIN_HIGH();           //不应答,数据至此结束      SHT10_Dly();      SCK_PIN_HIGH();      SHT10_Dly();      SCK_PIN_LOW();      SHT10_Dly();        return val;                   //返回读到的值  }  uint8_t SHT10_Measure(uint16_t *p_value, uint8_t *p_checksum, uint8_t mode) {uint8_t err = 0;      uint32_t i;      uint8_t value_H = 0;      uint8_t value_L = 0;        SHT10_TransStart();                      //开始传输      switch(mode)                                   {      case TEMP:                               //测量温度          err += SHT10_WriteByte(MEASURE_TEMP);//写MEASURE_TEMP测量温度命令          break;      case HUMI:          err += SHT10_WriteByte(MEASURE_HUMI);//写MEASURE_HUMI测量湿度命令          break;      default:          break;      }      SHT10_DATAIn();      for(i = 0; i < 72000000; i++)                 //等待DATA信号被拉低      {          if(DATA_VALUE() == 0) break;       //检测到DATA被拉低了,跳出循环      }      if(DATA_VALUE() == 1)                  //如果等待超时了          err += 1;  //HAL_Delay(20);    value_H = SHT10_ReadByte(ACK);      value_L = SHT10_ReadByte(ACK);      *p_checksum = SHT10_ReadByte(noACK);     //读取校验数据      *p_value = (value_H << 8) | value_L;      return err;  }int getTemprature(void){uint16_t temp_val = 0;uint8_t  checksum = 0;  SHT10_Measure(&temp_val, &checksum, TEMP);return (int)(temp_val/100-40);}int getHumidity(void){int realHumi=0;uint16_t humi_val = 0;uint8_t  checksum = 0;  SHT10_Measure(&humi_val, &checksum, HUMI);realHumi = ((humi_val*405/10000)+(((humi_val*humi_val)*28)/1000000)-4);if(realHumi > 100){realHumi = 100;}else if(realHumi < 0){realHumi = 0;}return realHumi;}#if 1void GetEnvInfo(uint16_t *humi_val_real,uint16_t *temp_val_real){*humi_val_real = getHumidity();*temp_val_real = getTemprature(); } #endif

使用的话,先调用SHT10_init,然后调用GetEnvInfo即可。我是用的是pa6,pa7作为模拟io口实际使用可任君选择。(另外说下,我是用的是STM32L0系列的库,使用的芯片是stm32L071RB)。

阅读全文
0 0
原创粉丝点击