搜索
bottom↓
回复: 49

求助:SHT71/SHT11传感器所测得的温度数据能够变化,但是数据不对,从几十度到几百度不停

[复制链接]

出0入0汤圆

发表于 2008-4-22 21:55:48 | 显示全部楼层 |阅读模式
SHT71/SHT11传感器所测得的温度数据能够变化,但是数据不对,从几十度到几百度不停地变化,有没有高手知道是什么原因啊?或者告诉我一声可能是哪儿出了问题,我好有个方向去检查啊,谢谢啦...

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2008-4-23 08:32:59 | 显示全部楼层
是不是高低位测试搞反了啊,

出0入137汤圆

发表于 2008-4-23 08:37:14 | 显示全部楼层
看看手册,好像温度和湿度是有关系的,我以前好像也遇到过,后来看手册后才知道他有个算法

出0入0汤圆

 楼主| 发表于 2008-4-23 09:44:30 | 显示全部楼层
回1楼:我是按SHT公司的C51例程改的啊,应该不会有问题吧;前几天在论坛上看见你说你也在做这个传感器,你做出来了吗

出0入0汤圆

 楼主| 发表于 2008-4-23 09:46:26 | 显示全部楼层
回2楼:我是按SHT公司的C51例程改的,没有改它的算法,你的程序是自己按数据手册写的吗,还是按C51的例程自己改的呢,谢谢你...

出0入137汤圆

发表于 2008-4-23 09:59:21 | 显示全部楼层
我就是用他的程序,但没你说的波动那么大

出0入137汤圆

发表于 2008-4-23 09:59:30 | 显示全部楼层
我就是用他的程序,但没你说的波动那么大

出0入0汤圆

 楼主| 发表于 2008-4-23 10:06:37 | 显示全部楼层
那你后来对哪个地方进行了修改啊,谢谢指点...

出0入137汤圆

发表于 2008-4-23 10:13:38 | 显示全部楼层
刚开始我不知道,他的温度和湿度是在一起计算的,我改变温度发现湿度也变化,后来仔细看了手册才知道,也没有修改什么。精度还不错

出0入0汤圆

 楼主| 发表于 2008-4-23 10:20:23 | 显示全部楼层
哦,好的,谢谢...
我对比了一下我的程序和网上的程序,发现一个特别奇怪的问题,在测量函数中,等待传感器测量结束的那句话
for(i=0;i<65535;i++)
{if(DATA ==0)break;}
if(DATA == 1)) error+=1;
如果我不在break前加一句延时的语句,程序就总是会出现error=1,延时的时间短了也一样,查了查原理也没搞明白是什么原因;网上各位高手们给出的能运行的程序也没有在这个地方加延时,不知道为什么,特别莫名其妙...

出0入0汤圆

 楼主| 发表于 2008-4-23 10:20:27 | 显示全部楼层
哦,好的,谢谢...
我对比了一下我的程序和网上的程序,发现一个特别奇怪的问题,在测量函数中,等待传感器测量结束的那句话
for(i=0;i<65535;i++)
{if(DATA ==0)break;}
if(DATA == 1)) error+=1;
如果我不在break前加一句延时的语句,程序就总是会出现error=1,延时的时间短了也一样,查了查原理也没搞明白是什么原因;网上各位高手们给出的能运行的程序也没有在这个地方加延时,不知道为什么,特别莫名其妙...

出0入0汤圆

 楼主| 发表于 2008-4-23 10:20:33 | 显示全部楼层
哦,好的,谢谢...
我对比了一下我的程序和网上的程序,发现一个特别奇怪的问题,在测量函数中,等待传感器测量结束的那句话
for(i=0;i<65535;i++)
{if(DATA ==0)break;}
if(DATA == 1)) error+=1;
如果我不在break前加一句延时的语句,程序就总是会出现error=1,延时的时间短了也一样,查了查原理也没搞明白是什么原因;网上各位高手们给出的能运行的程序也没有在这个地方加延时,不知道为什么,特别莫名其妙...

出0入0汤圆

发表于 2008-4-23 10:36:12 | 显示全部楼层
不需要家延时,我已经调出来了,温湿度,变化很小啊.
*(p_value+1)  =s_read_byte(ACK);    //read the first byte (MSB)
  *(p_value)=s_read_byte(ACK);    //read the second byte (LSB)
你高低位调换一下看看.既然能读出数据应该其他地方没有问题

出0入0汤圆

 楼主| 发表于 2008-4-23 11:05:40 | 显示全部楼层
恩,好的我试试,感谢...

出0入0汤圆

 楼主| 发表于 2008-4-23 11:19:03 | 显示全部楼层
很感谢你啊,这次数据好像正确了,只有小数点后面的会跳动!为什么会这样呢,难道盛世瑞恩公司给的程序有问题吗

出0入0汤圆

发表于 2008-4-23 11:33:37 | 显示全部楼层
对了就行啊,不要谢了,留个QQ大家有事可以讨论一下.

出0入0汤圆

发表于 2008-4-23 11:34:43 | 显示全部楼层
只是型号不一样,测试的顺序变化了

出0入0汤圆

 楼主| 发表于 2008-4-23 14:27:02 | 显示全部楼层
哦,好的,我的QQ632010414...

出0入0汤圆

发表于 2008-4-23 16:19:35 | 显示全部楼层
那个程序没什么问题,看你怎么改了
而且不同的型号精度不一样,温度的线性度还可以,湿度差点,要补偿

出0入0汤圆

 楼主| 发表于 2008-4-23 17:53:56 | 显示全部楼层
我觉得那个程序有问题,我就是改了下IO口,里面的语句都没有动,还加了一些延时,结果得不到正确的结果,按照12楼说的一改就好了...

出0入0汤圆

发表于 2008-4-26 16:59:09 | 显示全部楼层
我也在调试sht11,但是我发现在写入命令字节后检测不到应答信号。我的程序也是由C51移植过来的。整了一天,头都大了。楼主方不方便将与SHT11相关的程序贴一下?谢谢

出0入0汤圆

 楼主| 发表于 2008-4-28 15:37:22 | 显示全部楼层
这几天出去了,一直没有上,不好意思啦,我的程序:
/***********************************************************************************
Project:          SHTxx demo program (V2.1)
Filename:         SHTxx_Sample_Code.c     

Prozessor:        mega128L
Compiler:         icc avr
Cystal:           7.3728MHz

Autor:            fxl
Copyrigth:        (c) Sensirion AG      
***********************************************************************************/

#include <iom128v.h> //Microcontroller specific library, e.g. port definitions
#include <macros.h> //Keil library (is used for _nop()_ operation)   
#include <math.h>    //Keil library   
#include <stdio.h>   //Keil library
#include "1602LCD.h"
#include <stdlib.h>
#include <string.h>


typedef union  
{ unsigned int i;
  float f;
} value;

//----------------------------------------------------------------------------------
// modul-var
//----------------------------------------------------------------------------------
enum {TEMP,HUMI};
//--------------------------------
//PORTA initial
//--------------------------------

unsigned char Table_1[5];
unsigned char Table_2[5];
unsigned char Table_3[5];
unsigned char Table_4[5];


#define        DATA_H           PORTA|0X01
#define        DATA_L           PORTA&0XFE
#define        SCK_H            PORTA|0X02
#define        SCK_L            PORTA&0XFD

#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

//----------------------------------------------------------------------------------
char s_write_byte(unsigned char value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge  
{  
  unsigned char i,error=0;
  DDRA = 0B00000011;   
  for (i=0x80;i>0;i/=2)             //shift bit for masking
  { if (i & value) PORTA=DATA_H;          //masking value with i , write to SENSI-BUS
    else PORTA=DATA_L;  
        delay_nus(2);                       
    PORTA =SCK_H;                          //clk for SENSI-BUS
    delay_nus(5);                           //pulswith approx. 5 us           
    PORTA =SCK_L;
  }
  PORTA=DATA_H;           //release DATA-line
  delay_nus(2);                           
  DDRA = 0B00000010;
  PORTA=SCK_H;           //clk #9 for ack
  delay_nus(2);                                                
  if (PINA&0X01 == 0X01) error = 1;      
  else   error=0;                       //check ack (DATA will be pulled down by SHT11)
  //////////////////////////////
  if(error!=0)
  { LCD_write_char(0,0x01);  //显示清屏
                 delay_nms(2);
                 LCD_write_string(0,0,"Error1");
  }
/////////////////////////////
  
  delay_nus(2);
  PORTA = SCK_L;
  DDRA = 0B00000010;                     
  return error;                     //error=1 in case of no acknowledge
}

//----------------------------------------------------------------------------------
char s_read_byte(unsigned char ack)
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"  
{  
  unsigned char i,val=0;
  DDRA = 0B00000010;
  PORTA = DATA_H;                           //release DATA-line
  for (i=0x80;i>0;i/=2)                     //shift bit for masking
  { PORTA = SCK_H;                          //clk for SENSI-BUS
    delay_nus(2);
    if ((PINA&0X01) == 0X01) val=(val | i);        //read bit   
    PORTA = SCK_L;
        delay_nus(2);                                            
  }
  DDRA = 0B00000011;
  if(ack == 1) PORTA = DATA_L;                   //in case of "ack==1" pull down DATA-Line
  delay_nms(5);
  PORTA = SCK_H;                            //clk #9 for ack
  delay_nus(5);          //pulswith approx. 5 us  
  PORTA = SCK_L;                                                
  PORTA = DATA_H;                         //release DATA-line
  DDRA =0B00000010;
  return val;
}

//----------------------------------------------------------------------------------
void s_transstart(void)
//----------------------------------------------------------------------------------
// generates a transmission start  
//       _____         ________
// DATA:      |_______|
//           ___     ___
// SCK : ___|   |___|   |______
{   
   DDRA = 0B00000011;
   PORTA = DATA_H; PORTF = SCK_L;                   //Initial state
   delay_nus(2);  
   PORTA = SCK_H;
   delay_nus(2);  
   PORTA = DATA_L;
   delay_nus(2);  
   PORTA = SCK_L;   
   delay_nus(5);  
   PORTA = SCK_H;
   delay_nus(2);  
   PORTA = DATA_H;                    
   delay_nus(2);
   PORTA = SCK_L;
   DDRA = 0B00000010;                    
}

//----------------------------------------------------------------------------------
void s_connectionreset(void)
//----------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
//       _____________________________________________________         ________
// DATA:                                                      |_______|
//          _    _    _    _    _    _    _    _    _        ___     ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
{   
  unsigned char i;
  DDRA = 0B00000011;
  PORTA = DATA_H; PORTA = SCK_L;                    //Initial state
  for(i=0;i<9;i++)                  //9 SCK cycles
  { PORTA = SCK_H;
    delay_nus(1);
    PORTA = SCK_L;
        delay_nus(1);
  }
  s_transstart();                  //transmission start
  DDRA = 0B00000010;                    
}

//----------------------------------------------------------------------------------
char s_softreset(void)
//----------------------------------------------------------------------------------
// resets the sensor by a softreset  
{  
  unsigned char error=0;   
  s_connectionreset();              //reset communication
  error+=s_write_byte(RESET);       //send RESET-command to sensor
  return error;                     //error=1 in case of no response form the sensor
}

//----------------------------------------------------------------------------------
char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum)
//----------------------------------------------------------------------------------
// reads the status register with checksum (8-bit)
{  
  unsigned char error=0;
  s_transstart();                   //transmission start
  error=s_write_byte(STATUS_REG_R); //send command to sensor
  *p_value=s_read_byte(ACK);        //read status register (8-bit)
  *p_checksum=s_read_byte(noACK);   //read checksum (8-bit)   
  return error;                     //error=1 in case of no response form the sensor
}

//----------------------------------------------------------------------------------
char s_write_statusreg(unsigned char *p_value)
//----------------------------------------------------------------------------------
// writes the status register with checksum (8-bit)
{  
  unsigned char error=0;
  s_transstart();                   //transmission start
  error+=s_write_byte(STATUS_REG_W);//send command to sensor
  error+=s_write_byte(*p_value);    //send value of status register
  return error;                     //error>=1 in case of no response form the sensor
}
                                                            
//----------------------------------------------------------------------------------
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
//----------------------------------------------------------------------------------
// makes a measurement (humidity/temperature) with checksum
{  
  unsigned error=0;
  unsigned int i;
  

  s_transstart();                   //transmission start
  switch(mode){                     //send command to sensor
    case TEMP        : error+=s_write_byte(MEASURE_TEMP); break;
    case HUMI        : error+=s_write_byte(MEASURE_HUMI); break;
    default     : break;         
  }
  DDRA = 0B00000010;
for(i=0;i<65535;i++)
  {
   if(PINA|0XFE == 0XFE)
   {     
                 delay_nms(1000);
                 break;
        }       
  } //wait until sensor has finished the measurement  or timeout (~2 sec.) is reached
if(PINA&0X01 == 0X01) error+=1;               
  if(error!=0)
  { LCD_write_char(0,0x01);  //显示清屏
                 delay_nms(2);
                 LCD_write_string(0,0,"Error3");
  }
  *(p_value+1)  =s_read_byte(ACK);    //read the first byte (MSB)
  *(p_value)=s_read_byte(ACK);    //read the second byte (LSB)
  *p_checksum =s_read_byte(noACK);  //read checksum
  return error;
}

  
//----------------------------------------------------------------------------------------
   const float C1=-4.0;           // for 12 Bit
   const float C2=+0.0405;           // for 12 Bit
   const float C3=-0.0000028;        // for 12 Bit
   const float T1=+0.01;             // for 14 Bit @ 5V
   const float T2=+0.00008;           // for 14 Bit @ 5V
//----------------------------------------------------------------------------------------
// calculates temperature [癈] and humidity [%RH]  
// input :  humi [Ticks] (12 bit)  
//          temp [Ticks] (14 bit)
// output:  humi [%RH]
//          temp [癈]
//----------------------------------------------------------------------------------------

   
   void calc_sth11(float *p_humidity ,float *p_temperature)   
{
  float rh=*p_humidity;             // rh:      Humidity [Ticks] 12 Bit  
  float t=*p_temperature;           // t:       Temperature [Ticks] 14 Bit
  float rh_lin;                     // rh_lin:  Humidity linear
  float rh_true;                    // rh_true: Temperature compensated humidity
  float t_C;                        // t_C   :  Temperature [癈]
  int y;
  int z;
                     

  t_C=t*0.01 - 40;                  //calc. temperature from ticks to [癈]
  rh_lin=C3*rh*rh + C2*rh + C1;     //calc. humidity from ticks to [%RH]
  rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;   //calc. temperature compensated humidity [%RH]
  if(rh_true>100)rh_true=100;       //cut if the value is outside of
  if(rh_true<0.1)rh_true=0.1;       //the physical possible range

  *p_temperature=t_C;               //return temperature [癈]
  *p_humidity=rh_true;              //return humidity[%RH ]
  
   y=(int)t_C;
  itoa(Table_1,y,10);         
   z=(int)((t_C-y)*100);
  itoa(Table_2,z,10);
  
  y=(int)rh_true;
  itoa(Table_3,y,10);
  z=(int)((rh_true-y)*100);
  itoa(Table_4,z,10);
                 
}

//--------------------------------------------------------------------
float calc_dewpoint(float h,float t)
//--------------------------------------------------------------------
// calculates dew point
// input:   humidity [%RH], temperature [癈]
// output:  dew point [癈]
{ float logEx,dew_point;
  logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2);
  dew_point = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);
  return dew_point;
}

//----------------------------------------------------------------------------------
void main()
//----------------------------------------------------------------------------------
// sample program that shows how to use SHT11 functions
// 1. connection reset  
// 2. measure humidity [ticks](12 bit) and temperature [ticks](14 bit)
// 3. calculate humidity [%RH] and temperature [癈]
// 4. calculate dew point [癈]
// 5. print temperature, humidity, dew point   

{
  value humi_val,temp_val;
  float dew_point;
  unsigned char error,checksum;
  
  PORTA = 0X00;
  DDRA = 0X02;
  
  


     DDRD |= LCD_DATA;
     DDRC |= LCD_RS | LCD_EN;

         LCD_EN_PORT &= ~LCD_EN;      //EN=0
     
         LCD_init();
         LCD_write_char(0,0x01);  //显示清屏
                 delay_nms(2);
                 LCD_write_string(3,0,"Testing...");
                 LCD_write_string(2,1,"Please wait!");
                 delay_nms(2000);

   s_connectionreset();
  while(1)
  {
    error=0;
        delay_nms(200);
    error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);  //measure humidity
        delay_nms(200);
        error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP);  //measure temperature
   
       
    if(error!=0) s_connectionreset();                 //in case of an error: connection reset
    else
    {
      humi_val.f=(float)humi_val.i;                   //converts integer to float
      temp_val.f=(float)temp_val.i;                   //converts integer to float
      calc_sth11(&humi_val.f,&temp_val.f);            //calculate humidity, temperature
          dew_point=calc_dewpoint(humi_val.f,temp_val.f); //calculate dew point
       
           LCD_write_char(0,0x01);  //显示清屏
                 delay_nms(2);
                 LCD_write_string(0,0,"TEMP:");
                 LCD_write_string(5,0,Table_1);
                 LCD_write_string(7,0,".");
                 LCD_write_string(8,0,Table_2);                 
                 LCD_write_string(0,1,"HUMI:");                                                                              
                 LCD_write_string(5,1,Table_3);
                 LCD_write_string(7,1,".");
                 LCD_write_string(8,1,Table_4);
                 delay_nms(2000);  
          
         }
       
       
             
    //----------wait approx. 0.8s to avoid heating up SHTxx------------------------------      
   delay_nms(1000);
            //(be sure that the compiler doesn't eliminate this line!)
    //-----------------------------------------------------------------------------------                        
  }
}  
其中有部分是LCD1602的显示程序,明显的很,你去掉就行了。。。
还得提示你一下,我用是是SHT71,好多地方说它和SHT11是一样的,我不知道是不是,但是经过这次调试我发现,SHT71的测量顺序绝对不是手册上说的那样,具体的就是本帖前面的部分了,祝你成功啊...

出0入0汤圆

发表于 2008-4-28 15:42:55 | 显示全部楼层
问一下楼主,这东西要多少钱啊,如何价格合适,可以替换18B20用用

出0入0汤圆

 楼主| 发表于 2008-4-28 16:11:30 | 显示全部楼层
这东西很贵,我在北京买的SHT71要180,SHT11要90;好像其他地方比较便宜,网上也有帖子,好像他们买的SHT71一百多点吧,SHT11就四五十吧...

出0入0汤圆

发表于 2008-4-30 14:47:48 | 显示全部楼层
楼主你小子不够意识,我帮你解决了问题,加你QQ你不让加。

出0入0汤圆

 楼主| 发表于 2008-4-30 21:54:01 | 显示全部楼层
最近我没有上QQ啊,不好意思啊,我晚上回去上QQ加你啊,呵呵...你的是7326397吗?

出0入0汤圆

发表于 2008-5-7 19:37:05 | 显示全部楼层
我读出来的温度偏高了,温度变化幅度也有问题,大家帮个忙,器件还在水合中,不知道有没效果

出0入0汤圆

 楼主| 发表于 2008-5-7 20:08:41 | 显示全部楼层
我就根本没有水合,效果也挺好...

出0入0汤圆

发表于 2008-5-8 11:39:36 | 显示全部楼层
to 9 楼
我遇到的问题跟你的一样, 就是按照厂家给出的代码, 测量总会出错, 后来无意中发现单步调试可以正确读出数据, 于是在代码中加了延时就OK了. 原因仍未找到, 怀疑是SHT11内部单片机的问题.

出0入0汤圆

 楼主| 发表于 2008-5-8 12:09:34 | 显示全部楼层
恩,我也是无意中发现的...

出0入0汤圆

发表于 2008-5-8 12:34:40 | 显示全部楼层
要不就是你的那东西坏了
焊接的时候要防静电

出0入0汤圆

 楼主| 发表于 2008-5-8 12:49:15 | 显示全部楼层
没有坏啊,温度是对的啊,湿度就不知道了,温度的误差很小,我用温度计对比过

出0入0汤圆

发表于 2008-5-9 09:54:10 | 显示全部楼层
SHT10 11 71最多500ms读一次数据,要不芯片温度会上升,导致测量数据不准,另外要给SHT足够的转换时间,就是延时时间要足够^_^我做SHT10快3年了,我们的装置都用这东西

出0入0汤圆

发表于 2008-5-9 17:28:57 | 显示全部楼层
现在sht11价格还是比较高,总代理那边一百片以内都还要六十,大伙那边有没便宜点
的货源或是其它比较好的替代品

出0入0汤圆

发表于 2008-5-11 10:24:43 | 显示全部楼层
我的sht11测量回来的数据倒是很稳定,可是误差很大,光温度现在的环境是十几度的样子,可是采集回来的是37度,一直很稳定,就小数部分在变,帮帮忙啊,是哪里的问题:
     int i;   
     int t,rh;
     Sht11_START();              //调用启动子函数     
     Sht11_WR(0x03);   //写入一字节数据,这里写入温度检测
     a =0;
     a =Sht11_RD(1);  //读取高低字节
     
     b =0;
     b =Sht11_RD(2);
     a =a<<8;
     t =a|b;
     Sht11_RD(0);  //读取CRC校验码

不知道这么写对不对啊

出0入0汤圆

 楼主| 发表于 2008-5-13 10:15:19 | 显示全部楼层
为什么不按公司给的例子改呢,自己写总会出现莫名其妙的错误...

出0入0汤圆

发表于 2008-9-9 09:49:23 | 显示全部楼层
我发现读出来的数据确实要偏高一些,

出0入0汤圆

发表于 2008-9-9 11:34:33 | 显示全部楼层
温度大约都是高0.2,0.3左右的样子,很少有比标准值偏小的,还有湿度,SHT10,11,偶测试过不下百来个,在大于80%以上的环境中显示数值都是要偏高5%以上,很少有偏高3%、4%的,在60-80%内,偏高3%、4%,20-60%,偏高2-3%,10%以下偏高1-2%,还没碰到过湿度小于标准值的,数据基本上都是上公差

出0入0汤圆

发表于 2010-4-9 12:15:14 | 显示全部楼层
楼主的问题
不是程序的问题,是关于单片机大小端的问题
SHT11公司给的是51的例程,而51是大端,
AVR,430,STM32都是小端

在移植过程当中,注意一下,把高低字节调换一下

出0入0汤圆

发表于 2010-6-21 14:33:22 | 显示全部楼层
Mark

出0入0汤圆

发表于 2010-6-21 18:13:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-21 19:30:52 | 显示全部楼层
我的sht15 用的很正常.....avr按照官方例子改的......12232液晶显示,都用了1年了.....

出0入0汤圆

发表于 2010-8-12 09:14:47 | 显示全部楼层
多谢!碰到同样问题了,哈哈,按12楼一改就正确了,再谢!

出0入0汤圆

发表于 2011-5-24 12:30:04 | 显示全部楼层
成功标记

出0入0汤圆

发表于 2011-6-10 15:14:45 | 显示全部楼层
请教下各位我的怎么去湿度数据的时候没有我问题,回来的值也正常,但是读取温度的时候,error=1出错,然后忽略error=1的话 就出现0xffff的大值

出0入0汤圆

发表于 2011-6-10 15:15:35 | 显示全部楼层
这个是我的单片机程序
#include "p33FJ32GP204.h"                             //特定单片机的配置文件
#include <math.h>                                     //一些数学公式的计算
#include "libpic30.h"                                 //用于读写Flash的库函数  
_FOSCSEL(FNOSC_PRI&IESO_OFF);                     
_FOSC(FCKSM_CSDCMD&OSCIOFNC_OFF&POSCMD_HS);           //外部晶振配置
_FWDT( FWDTEN_ON & WDTPRE_PR128 &  WDTPOST_PS8192 );  //看门狗配置
_FGS(GSS_HIGH&GCP_ON&GWRP_OFF);                       //通用段代码保护高安全性通用段代码写保护,
_FPOR(FPWRT_PWR128);
_FICD(JTAGEN_OFF);  
#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

//#define SCK LATBbits.LATB8                            //SCL
//#define DATA LATBbits.LATB9                            //SDA
#define SCK PORTBbits.RB8                //SCK PORTBbits.RB9
#define DATA PORTBbits.RB9        //DATA
//#define SCK PORTBbits.RB8                //SCK
//#define DATA PORTBbits.RB9                //DATA

//函数申明
void delay(int TIME);
void i2c_delay(unsigned int i2c_count1);
char s_write_byte(unsigned char value);
char s_read_byte(unsigned char ack);
void s_transstart(void);
void s_connectionreset(void);
char s_softreset(void);
char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum);
char s_write_statusreg(unsigned char *p_value);
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);
void init_uart();
void calc_sth11(float *p_humidity ,float *p_temperature);
float calc_dewpoint(float h,float t);
void init_spi(void);
void show(void);

typedef union  
{ unsigned int i;
  float f;
} value;
enum {TEMP,HUMI};
unsigned char LED1=10,LED2=10,LED3=10,LED4=10;

/*****************************************************
                     延迟函数
*****************************************************/
void delay(int TIME)
{
        int i,ii;
        for (ii=0;ii<TIME;ii++)  
        {
            for (i=0;i<32000;i++);        //32480*time+time次自加运算
        }
}
//----------------------------------------------------------------------------------
//                 I2C通讯延时函数 赋值1的话大约是1us
//----------------------------------------------------------------------------------
void i2c_delay(unsigned int i2c_count)
{
        while(i2c_count !=0)
        i2c_count--;
}

//----------------------------------------------------------------------------------
char s_write_byte(unsigned char value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge  
{  
        unsigned char i,write=0;
        TRISBbits.TRISB9=0;                          //I2C-SDA输出
        i2c_delay(2);
        for (i=0x80;i>0;i/=2)              //shift bit for masking
        {
                if (i & value) DATA=1;          //masking value with i , write to SENSI-BUS
            else DATA=0;                        
            i2c_delay(5);                    //observe setup time
            SCK=1;                           //clk for SENSI-BUS
            i2c_delay(15);                                 //pulswith approx. 5 us   
            SCK=0;
           // i2c_delay(5);
        }
        //TRISBbits.TRISB9=1; //
        //i2c_delay(2);
        DATA=1;                           //release DATA-line
        i2c_delay(5);                         //observe setup time
        TRISBbits.TRISB9=1;                                  //改变进出
        SCK=1;                                                         //clk #9 for ack                        
        i2c_delay(5);  
        //if(PORTBbits.RB9==0X01) write=1;  //check ack (DATA will be pulled down by SHT11)
        //write=0;
        write=PORTBbits.RB9;
        SCK=0;         
        return write;                     //error=1 in case of no acknowledge
}

//----------------------------------------------------------------------------------
char s_read_byte(unsigned char ack)
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"  
{  
        unsigned char i,val=0;
        DATA=1;                           //release DATA-line
        TRISBbits.TRISB9=1;                          //I2C-SDA输入
        i2c_delay(2);
        for (i=0x80;i>0;i/=2)             //shift bit for masking
        {
                SCK=1;                          //clk for SENSI-BUS
            if (PORTBbits.RB9) val=(val | i);        //read bit   
            SCK=0;
                i2c_delay(2);        
        }
        //i2c_delay(2);
        TRISBbits.TRISB9=0;                                  //I2C-SDA输出       
        if(ack == 1) DATA=0;                        //in case of "ack==1" pull down DATA-Line
        i2c_delay(5);                     //observe setup time
        SCK=1;                            //clk #9 for ack
        i2c_delay(10);                                 //pulswith approx. 5 us  
        SCK=0;
        i2c_delay(5);                     //observe hold time      
        DATA=1;                           //release DATA-line
        //TRISBbits.TRISB9=0;                        
        return val;
}
//----------------------------------------------------------------------------------
void s_transstart(void)
//----------------------------------------------------------------------------------
// generates a transmission start  
//       _____         ________
// DATA:      |_______|
//           ___     ___
// SCK : ___|   |___|   |______
{   
        DATA=1; SCK=0;                   //Initial state
        i2c_delay(5);
        SCK=1;
        i2c_delay(5);
        DATA=0;
        i2c_delay(5);
        SCK=0;   
        i2c_delay(10);
        SCK=1;
        i2c_delay(5);
        DATA=1;      
        i2c_delay(5);
        SCK=0;  
}

//----------------------------------------------------------------------------------
void s_connectionreset(void)
//----------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
//       _____________________________________________________         ________
// DATA:                                                      |_______|
//          _    _    _    _    _    _    _    _    _        ___     ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
{   
        unsigned char i;  
        DATA=1; SCK=0;                    //Initial state
        for(i=0;i<9;i++)                  //9 SCK cycles
        {
                SCK=1;
            SCK=0;
        }
        s_transstart();                   //transmission start
}

//----------------------------------------------------------------------------------
char s_softreset(void)
//----------------------------------------------------------------------------------
// resets the sensor by a softreset  
{  
        unsigned char error=0;   
        s_connectionreset();              //reset communication
        error+=s_write_byte(RESET);       //send RESET-command to sensor
        return error;                     //error=1 in case of no response form the sensor
}
//----------------------------------------------------------------------------------
char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum)
//----------------------------------------------------------------------------------
// reads the status register with checksum (8-bit)
{  
        unsigned char error=0;
        s_transstart();                   //transmission start
        error=s_write_byte(STATUS_REG_R); //send command to sensor
        *p_value=s_read_byte(ACK);        //read status register (8-bit)
        *p_checksum=s_read_byte(noACK);   //read checksum (8-bit)   
        return error;                     //error=1 in case of no response form the sensor
}

//----------------------------------------------------------------------------------
char s_write_statusreg(unsigned char *p_value)
//----------------------------------------------------------------------------------
// writes the status register with checksum (8-bit)
{  
        unsigned char error=0;
        s_transstart();                   //transmission start
        error+=s_write_byte(STATUS_REG_W);//send command to sensor
        error+=s_write_byte(*p_value);    //send value of status register
        return error;                    //error>=1 in case of no response form the sensor
}
            
//----------------------------------------------------------------------------------
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
//----------------------------------------------------------------------------------
// makes a measurement (humidity/temperature) with checksum
{  
        unsigned char error=0;
        unsigned int i;
        s_transstart();                   //transmission start
        switch(mode)
        {                     
            case TEMP : error+=s_write_byte(MEASURE_TEMP); break; //send command to sensor
            case HUMI : error+=s_write_byte(MEASURE_HUMI); break;
            default   : break;   
        }        
        for (i=0;i<65535;i++)
        if(PORTBbits.RB9==0) break; //wait until sensor has finished the measurement
        if(PORTBbits.RB9) error+=1;                // or timeout (~2 sec.) is reached
        *(p_value+1)=s_read_byte(ACK);    //read the second byte (LSB)
        *(p_value)  =s_read_byte(ACK);    //read the first byte (MSB)
        *p_checksum =s_read_byte(noACK);  //read checksum
        return error;                                          // error=1 measure fail,error=0 success
}
//----------------------------------------------------------------------------------
void init_uart()
//----------------------------------------------------------------------------------
//9600 bps @ 11.059 MHz  
{
        TRISBbits.TRISB9=0;                         //初始SDA为输出
        TRISBbits.TRISB8=0;                                                 //初始SDA为输出   
}

//----------------------------------------------------------------------------------
void calc_sth11(float *p_humidity ,float *p_temperature)
//----------------------------------------------------------------------------------
// calculates temperature [°C] and humidity [%RH]  
// input :  humi [Ticks] (12 bit)  
//          temp [Ticks] (14 bit)
// output:  humi [%RH]
//          temp [°C]
{
        const float C1=-2.0468;           // for 12 Bit RH
        const float C2=+0.0367;           // for 12 Bit RH
        const float C3=-0.0000015955;     // for 12 Bit RH
        const float T1=+0.01;             // for 12 Bit RH
        const float T2=+0.00008;          // for 12 Bit RH  

        float rh=*p_humidity;             // rh:      Humidity [Ticks] 12 Bit  
        float t=*p_temperature;           // t:       Temperature [Ticks] 14 Bit
        float rh_lin;                     // rh_lin:  Humidity linear
        float rh_true;                    // rh_true: Temperature compensated humidity
        float t_C;                        // t_C   :  Temperature [°C]

        t_C=t*0.01 - 40.1;              //calc. temperature[°C]from 14 bit temp.ticks @5V
        rh_lin=C3*rh*rh + C2*rh + C1;     //calc. humidity from ticks to [%RH]
        rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;   //calc. temperature compensated humidity [%RH]
        if(rh_true>100)rh_true=100;       //cut if the value is outside of
        if(rh_true<0.1)rh_true=0.1;       //the physical possible range

        *p_temperature=t_C;               //return temperature [°C]
        *p_humidity=rh_true;              //return humidity[%RH]
}

//--------------------------------------------------------------------
float calc_dewpoint(float h,float t)
//--------------------------------------------------------------------
// calculates dew point
// input:   humidity [%RH], temperature [°C]
// output:  dew point [°C]
{
        float k,dew_point ;
        k = (log10(h)-2)/0.4343 + (17.62*t)/(243.12+t);
        dew_point = 243.12*k/(17.62-k);
        return dew_point;
}

//--------------------------------------------------------------------
//                    SPI初始化
//--------------------------------------------------------------------
void init_spi(void)
{   
        __builtin_write_OSCCONL(OSCCON&0xbf);
        RPOR2bits.RP4R=8;                             //设置SPI1的SCK1功能为RP4脚
        RPOR9bits.RP19R=7;                            //设置SPI1的SDO1功能为RP19脚
        __builtin_write_OSCCONL(OSCCON|0x40);
        SPI1CON1=0x027B;                              //SPI配置,注意SPI1CON的MODE16位,SMP位,CKP位
        SPI1STATbits.SPIROV=0;                        //清零,未接收溢出
        SPI1STATbits.SPIEN=1;                         //开启SPI模块   
}

//--------------------------------------------------------------------
//                     数码管显示程序
//--------------------------------------------------------------------
void show(void)                              
{
        unsigned int i;
        IFS0bits.SPI1IF=0;              //打开SPI中断
        SPI1STATbits.SPIROV=0;          //接收溢出标志位:0---未发生溢出
  
        switch(LED1)                      //ABCHDEGF
        {
            case 0:SPI1BUF =0xED;break;        //0
            case 1:SPI1BUF =0x9F;break;        //1
            case 2:SPI1BUF =0x31;break;        //2
            case 3:SPI1BUF =0x15;break;        //3
            case 4:SPI1BUF =0x9C;break;        //4
            case 5:SPI1BUF =0x54;break;        //5
            case 6:SPI1BUF =0x50;break;        //6
            case 7:SPI1BUF =0x1F;break;        //7
            case 8:SPI1BUF =0x10;break;        //8
            case 9:SPI1BUF =0x14;break;        //9
            case 10:SPI1BUF =0xFF;break;       //不显
            case 11:SPI1BUF =0xFD;break;       //负号
            case 12:SPI1BUF =0x9D;break;       //负1
            case 13:SPI1BUF =0x78;break;       //显示F
            case 14:SPI1BUF =0x8F;break;        //1.
            case 15:SPI1BUF =0x21;break;        //2.
            case 16:SPI1BUF =0x05;break;        //3.
            case 17:SPI1BUF =0x8C;break;        //4.
            case 18:SPI1BUF =0x44;break;        //5.
            case 19:SPI1BUF =0x8D;break;        //-1. 负值显示用  
        }
        for (i=0;i<15;i++);
        if(_SPI1IF==0)
        {  
            for (i=0;i<5;i++);
            if(_SPI1IF==0)
            goto loop;
        }
  
        IFS0bits.SPI1IF=0;
        SPI1STATbits.SPIROV=0;
        switch(LED2)                       //BAFGEDCH
        {
            case 0:SPI1BUF =0x11;break;      //0
            case 1:SPI1BUF =0x7D;break;      //1
            case 2:SPI1BUF =0x23;break;      //2
            case 3:SPI1BUF =0x29;break;      //3
            case 4:SPI1BUF =0x4D;break;      //4
            case 5:SPI1BUF =0x89;break;      //5
            case 6:SPI1BUF =0x81;break;      //6
            case 7:SPI1BUF =0x3D;break;      //7
            case 8:SPI1BUF =0x01;break;      //8
            case 9:SPI1BUF =0x09;break;      //9
            case 10:SPI1BUF =0xFF;break;     //不显
            case 11:SPI1BUF =0xD3;break;     //显示"L"
            case 12:SPI1BUF =0xEF;break;     //显负号
            case 13:SPI1BUF =0xF1;break;     //反风
            case 14:SPI1BUF =0x87;break;     //超压显示  
        }
        for (i=0;i<15;i++);
        if(_SPI1IF==0)
        {  
            for (i=0;i<5;i++);
            if(_SPI1IF==0)
            goto loop;
        }

        IFS0bits.SPI1IF=0;
        SPI1STATbits.SPIROV=0;
        switch(LED3)
        {
            case 0:SPI1BUF =0x10;break;      //0
            case 1:SPI1BUF =0x7C;break;      //1
            case 2:SPI1BUF =0x22;break;      //2
            case 3:SPI1BUF =0x28;break;      //3
            case 4:SPI1BUF =0x4C;break;      //4
            case 5:SPI1BUF =0x88;break;      //5
            case 6:SPI1BUF =0x80;break;      //6
            case 7:SPI1BUF =0x3C;break;      //7
            case 8:SPI1BUF =0x00;break;      //8
            case 9:SPI1BUF =0x08;break;      //9
            case 10:SPI1BUF =0xFF;break;     //不显
            case 11:SPI1BUF =0xD3;break;     //显示"L"
            case 12:SPI1BUF =0xD7;break;     //显10。0用
            case 13:SPI1BUF =0xF1;break;     //反风
            case 14:SPI1BUF =0x87;break;     //超压显示
            case 15:SPI1BUF =0x11;break;     //显示ON用
            case 16:SPI1BUF =0xEF;break;     //显示负号
            case 20:SPI1BUF =0x11;break;      //0(AD显示用)
            case 21:SPI1BUF =0x7D;break;      //1(AD显示用)
            case 22:SPI1BUF =0x23;break;      //2(AD显示用)
            case 23:SPI1BUF =0x29;break;      //3(AD显示用)
            case 24:SPI1BUF =0x4D;break;      //4(AD显示用)
            case 25:SPI1BUF =0x89;break;      //5(AD显示用)
            case 26:SPI1BUF =0x81;break;      //6(AD显示用)
            case 27:SPI1BUF =0x3D;break;      //7(AD显示用)
            case 28:SPI1BUF =0x01;break;      //8(AD显示用)
            case 29:SPI1BUF =0x09;break;      //9(AD显示用)
        }
        for (i=0;i<15;i++);
        if(_SPI1IF==0)
        {
            for (i=0;i<5;i++);
            if(_SPI1IF==0)
            goto loop;
        }

        IFS0bits.SPI1IF=0;
        SPI1STATbits.SPIROV=0;
        switch(LED4)
        {
            case 0:SPI1BUF =0x11;break;      //0
            case 1:SPI1BUF =0x7D;break;      //1
            case 2:SPI1BUF =0x23;break;      //2
            case 3:SPI1BUF =0x29;break;      //3
            case 4:SPI1BUF =0x4D;break;      //4
            case 5:SPI1BUF =0x89;break;      //5
            case 6:SPI1BUF =0x81;break;      //6
            case 7:SPI1BUF =0x3D;break;      //7
            case 8:SPI1BUF =0x01;break;      //8
            case 9:SPI1BUF =0x09;break;      //9
            case 10:SPI1BUF =0xFF;break;     //不显
            case 11:SPI1BUF =0xD3;break;     //显示"L"
            case 12:SPI1BUF =0xD7;break;     //
            case 13:SPI1BUF =0xF1;break;    //反风
            case 14:SPI1BUF =0x87;break;     //
            case 15:SPI1BUF =0x15;break;     //显示ON用  
        }
        for (i=0;i<15;i++);
        if(_SPI1IF==0)
        {
            for (i=0;i<5;i++);
            if(_SPI1IF==0)
            goto loop;
        }
        loop:  for(i=0;i<1155;i++);
}

//----------------------------------------------------------------------------------
void main()
//----------------------------------------------------------------------------------
// sample program that shows how to use SHT11 functions
// 1. connection reset  
// 2. measure humidity [ticks](12 bit) and temperature [ticks](14 bit)
// 3. calculate humidity [%RH] and temperature [°C]
// 4. calculate dew point [°C]
// 5. print temperature, humidity, dew point   
{
        value humi_val,temp_val;         //定义两个结构体变量
        float dew_point;                         //定义露点
        unsigned char error,checksum; //
        unsigned int i,j,shidu_show,wendu_show;
        unsigned int F;//开机倒计时
        init_spi();
        init_uart();
        //开机倒计时
        /*for (F=3;F>=0;F--)      //开机延时3s
        {               
            ClrWdt();             //清看门狗
            LED1=13;               
            LED2=10;                 
            LED3=F/10;               
            LED4=F%10;               
            if(LED3>=1)
            {LED3=F/10;}
            else
            {LED3=10;}   
            show();        
                delay(22);           
        }*/
        //复位启动
        s_connectionreset();
        while(1)
        {
                error=0;
                //i2c_delay(200);
            error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);  //measure humidity
                delay(200);
            error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP);  //measure temperature
            if(error!=0)
                        s_connectionreset();        //in case of an error: connection reset
            else
                {      
                        humi_val.f=(float)humi_val.i;                   //converts integer to float
                        temp_val.f=(float)temp_val.i;                   //converts integer to float
                        //temp_val.f=655.000;          
                        calc_sth11(&humi_val.f,&temp_val.f);            //calculate humidity, temperature
                        //dew_point=calc_dewpoint(humi_val.f,temp_val.f); //calculate dew point        
                        shidu_show=temp_val.f*10;
                        ClrWdt();                                                                          //清看门狗
                        LED1=shidu_show/1000;               //显示湿度千位  
                        LED2=(shidu_show%1000)/100;         //显示湿度百十位  
                        LED3=(shidu_show%100)/10;           //显示湿度十位  
                        LED4=(shidu_show%10)%10;                 //显示湿度小数点后第一位
                        show();
                        //delay(5);

                        //printf("temp:%5.1fC humi:%5.1f%% dew_point:%5.1fC\n",temp_val.f,humi_val.f,dew_point);  
                //----------wait approx. 0.8s to avoid heating up SHTxx-----------------------------      
                for (i=0;i<40000;i++); //(be sure that the compiler doesn't eliminate this line!)
                for (i=0;i<40000;i++);
                //----------------------------------------------------------------------------------        
                }
        }
}

出0入0汤圆

发表于 2011-8-31 13:41:52 | 显示全部楼层
请问谁有SHT CVAVR的完整的源程序,请提供,谢谢!!

出0入0汤圆

发表于 2014-8-29 15:31:26 | 显示全部楼层
我现在用的是SHT10也出现这种情况,按照12楼的说法,也没解决问题

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-8-29 15:33:22 | 显示全部楼层
  while(1)
  { error=0;
    error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI);  //measure humidity 测量湿度
    error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP);  //measure temperature 测量温度
    if(error!=0)
        {
                s_connectionreset();                 //in case of an error: connection reset 的一个错误:连接重置
            printf("Error\n");    在这里添加了一行,方便调试观察,发现以下这种结果
        }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-8-29 15:34:13 | 显示全部楼层
说明的数据一会正,一会不正常,求高人指点
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-2 23:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表