发新帖我要提问
12
返回列表
打印
[STM32F0]

STM32F0驱动SHT11结果异常,请求帮助

[复制链接]
楼主: dsoyy
手机看帖
扫描二维码
随时随地手机跟帖
21
//Code for reading the SHT11 temeprature and humidity sensor with an STM ARM CORTEX-M3 MCU 
////////////////////////////////////////////////////////////////////////////////////////
/*
The function read_temperature_and_humidity() reads the temperature and humidity and stores the data in XX.XX format
*/
/***********************************************************************************************
*          PORT DEFINITION
************************************************************************************************/
#define DATA_WR  GPIOA, GPIO_Pin_6
#define DATA_RD    GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)
#define SCK     GPIOA, GPIO_Pin_7

/*********************************************************************************************************
*          LOCAL DEFINITIONS
*********************************************************************************************************/
//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 RESETa         0x1e   //000   1111    0
#define noACK    0
#define ACKa      1
/*
***********************************************************************************************
*          GLOBAL CONSTANTS
************************************************************************************************/
enum {TEMP,HUMI};
typedef union
{
uint16_t i;
float f;
} value;
////////////////////////////////////////////////////////////////////////////////////////
//char temperature[15];
//char humidity[15];
int16_t  Real_Temperature;
uint16_t Real_Humidity;
int16_t  Temp_Hi_Limit;
int16_t  Temp_Lo_Limit;
uint16_t Humi_Hi_Limit;
uint16_t Humi_Lo_Limit;
   char Temp_Offset,Humi_Offset;
unsigned char DataStatus;// 数据结果标志位  0000 1111   
                               // 1:HumiLow HumidityHigh TempLow TempHigh
void mikrosekund(int cas)
{   
int i; int j; //int k=0;
for (i=0;i<cas;i++)
{
  for (j=0;j<1;j++)
  {  
  ;
  ;
  ;
  }
}
}
void datain(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void dataout(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void sckout(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/***********************************************************************************************
*         FUNCTION PROTOTYPES
***********************************************************************************************/
char s_softreset(void);
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);
//char s_write_statusreg(unsigned char *p_value);
//char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum);
/*
***********************************************************************************************
*         FUNCTION PROTOTYPES
*          HARDWARE SPECIFIC
***********************************************************************************************
*/
void s_transstart(void);
void s_connectionreset(void);
char s_read_byte(unsigned char ack);
char s_write_byte(unsigned char value);

/*
*********************************************************************************************************
*                             SOFT RESET THE SENSOR
*
* Description : Soft reset, resets the interface, clears the status register to default values
*    Wait minimum 11 ms before next command
* Arguments   : none
*   
* Returns     : 1 if no response from the sensor
* Notes    :
*********************************************************************************************************/
char s_softreset(void)
{
  unsigned char error_bit=0;  
  s_connection_reset();              //reset communication
  error_bit+=s_write_byte(RESETa);       //send RESET-command to sensor
  return error_bit;                     //error=1 in case of no response from the sensor
}
/*****************************************************************************************************
*                   MAKE MEASUREMENT ON HUMIDITY AND TEMPERATURE IN 12BITS ADN 14BITS
*
* Description : Makes a measurement (humidity/temperature) with checksum
* Arguments   :
*   
* Returns     :
* Notes    : It takes approximately 11/55/210 ms for a 8/12/14bit measurement.
*    Measurement data is stored until readout.
*    Two bytes of measurement data and one byte of CRC checksum will then be transmitted.
*    The uC must acknowledge each byte by pulling the DATA line low.
*********************************************************************************************************/
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
{
unsigned error_bit=0;
unsigned int i;

s_transstart();                   //transmission start
switch(mode)
{                     //send command to sensor
  case TEMP : error_bit+=s_write_byte(MEASURE_TEMP); break;
  case HUMI : error_bit+=s_write_byte(MEASURE_HUMI); break;
  default     : break;  
}
(mode==HUMI)?msDelay(55):msDelay(210);

for (i=0;i<65535;i++) if(DATA_RD==0) break; //wait until sensor has finished the measurement
if(DATA_RD) error_bit+=1;       //or timeout (~2 sec.) is reached

*(p_value+1)  = s_read_byte(ACKa);     //read the first byte (MSB)
*(p_value) = s_read_byte(ACKa);      //read the second byte (LSB)
*p_checksum  = s_read_byte(noACK);    //read checksum

return error_bit;
}
/*
*********************************************************************************************************
*                             TRANSMISSION START SEQUENCE
*
* Description : To initiate a transmission, a 揟ransmission Start?sequence has to be issued.
* Arguments   : none
*   
* Returns     : none
* Notes    :
*      generates a transmission start
*            _____         ________
*      DATA:       |_______|
*        ___     ___
*      SCK : ___|   |___|   |______
*********************************************************************************************************
*/
void s_transstart(void)
{  
   GPIO_ResetBits(SCK); //SCK=0;                   //Initial state
   datain();// DATA_TRIS = 1;   //pullup resistor brings DATA pin high
   mikrosekund(1);
   GPIO_SetBits(SCK); //SCK=1;
   mikrosekund(1);
   dataout(); GPIO_ResetBits(DATA_WR); //DATA_TRIS=0;   // DATA_WR=0; DATA_TRIS=0;
   mikrosekund(1);
   GPIO_ResetBits(SCK);//SCK=0;  
   mikrosekund(5);
   GPIO_SetBits(SCK);//SCK=1;
   mikrosekund(1);
   datain();// DATA_TRIS=1;       //pullup resistor brings DATA pin high
   mikrosekund(1);
   GPIO_ResetBits(SCK);//SCK=0;   
}

/*
*********************************************************************************************************
*                              CONNECTION RESET SEQUENCE
*
* Description : This sequence resets the interface only. The status register preserves its content.
* Arguments   : none
*   
* Returns     : none
* Notes    :
*      communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
*            _____________________________________________________         ________
*     DATA:                                                  |_______|
*               _    _    _    _    _    _    _    _    _        ___     ___
*     SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
*********************************************************************************************************
*/
void s_connection_reset(void)
{  
  unsigned char i;
dataout();//DATA_TRIS  = 0;    //set data pin an output
GPIO_SetBits(DATA_WR); //DATA_WR     = 1;   //set data pin high
sckout(); //SCK_TRIS = 0;   //set CLK pin an output low
GPIO_ResetBits(SCK);// SCK   = 0;

  for(i=0;i<9;i++)              //9 SCK cycles for connection reset sequence
  { GPIO_SetBits(SCK);//SCK=1;
mikrosekund(1);
    GPIO_ResetBits(SCK);//SCK=0;
mikrosekund(1);
  }
  s_transstart();             //transmission start
}

/*
*********************************************************************************************************
*                             LOW LEVEL READ FUNCTION
*
* Description : Read a byte form the Sensibus and gives an acknowledge in case of "ack == ACK"
* Arguments   : 'ack'  ACK (1) if acknowledge required
*      noACK (0) in case acknowledge NOT required
*   
* Returns     : return the byte read from the sensor
* Notes    :
*********************************************************************************************************
*/
char s_read_byte(unsigned char ack)
{
  unsigned char i,val=0;
  datain(); //DATA_TRIS = 1;                    //set DATA line an input
  GPIO_ResetBits(SCK);//SCK = 0;
  for (i=0x80;i>0;i/=2)             //shift bit for masking
  { GPIO_SetBits(SCK);//SCK=1;                          //clk for SENSI-BUS
mikrosekund(2);
    if (DATA_RD) val=(val | i);        //read bit  
    GPIO_ResetBits(SCK);//SCK=0;        
mikrosekund(2);
  }
if(ack==ACKa)
{
dataout();// DATA_TRIS = 0;
  GPIO_ResetBits(DATA_WR);//DATA_WR = 0;
}
   GPIO_SetBits(SCK);//SCK=1;                          //clk #9 for ack
mikrosekund(5);      //pulse-width approx. 5 us         
   GPIO_ResetBits(SCK);//SCK=0;         
    datain();// DATA_TRIS = 1;                  //release DATA-line
  return val;
}
/*
*********************************************************************************************************
*                             LOW LEVEL WRITE FUNCTION
*
* Description : Write a byte on the Sensibus and checks the acknowledge
* Arguments   : 'value' is the byte to write to the sensor
*   
* Returns     : 1 in case of an error (no acknowledge) from the sensor
* Notes    :
*********************************************************************************************************
*/
char s_write_byte(unsigned char value)
{
  unsigned char i,error_bit=0;
  dataout();//DATA_TRIS = 0;
  for (i=0x80;i>0;i/=2)                //shift bit for masking
  {
   if (i & value) GPIO_SetBits(DATA_WR);// DATA_WR=1;             //masking value with i , write to SENSI-BUS
    else GPIO_ResetBits(DATA_WR); //DATA_WR=0;

mikrosekund(5);   //add by idea
                        
    GPIO_SetBits(SCK);//SCK=1;                             //clk for SENSI-BUS
mikrosekund(5);            //pulse-width approx. 5 us
    GPIO_ResetBits(SCK);//SCK=0;
mikrosekund(5);
  }
  datain();//DATA_TRIS=1;                             //release DATA-line, let SHT10 sensor controls DATA line
  GPIO_SetBits(SCK);//SCK=1;                               //clk #9 for ack
  error_bit=DATA_RD;                          //check ack (DATA will be pulled down by SHT11)
  GPIO_ResetBits(SCK);//SCK=0;        
  return error_bit;                        //error=1 in case of no acknowledge
}

////////////////konec kode za branje temp
void calc_sht1x(float *p_humidity ,float *p_temperature)
// calculates temperature [癈] and humidity [%RH]
// input :  humi [Ticks] (12 bit)
//          temp [Ticks] (14 bit)
// output:  humi [%RH]
//          temp [deg Cel]
{ 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 [癈]
  t_C=t*0.01 - 40;                      //calc. temperature from ticks to [deg Cel]
  rh_lin=0.0405*rh - 0.0000028*rh*rh - 4.0;      //calc. humidity from ticks to [%RH]
  rh_true=(t_C-25)*(0.01+0.00008*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
  //if(t_C<0)t_C=0;//by idea
  *p_temperature=t_C;                   //return temperature [deg Cel]
  *p_humidity=rh_true;                  //return humidity[%RH]
}
void read_temperature_and_humidity(void)
{
value humi_val, temp_val;
unsigned char error_bit, checksum;
////s_softreset();             //reset the SHT10 sensor

msDelay(20);  // itcakam 20 mirko sekund, da se senzor umiri
error_bit=0;
    error_bit+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI);   //measure humidity
    error_bit+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP);   //measure temperature
    if(error_bit!=0)
{
   s_connection_reset(); //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_sht1x(&humi_val.f,&temp_val.f);      //calculate humidity, temperature
  //sprintf(temperature, "%f", temp_val.f,);
  //sprintf(humidity, "%f", humi_val.f);
  ////
  Real_Temperature=(int16_t)(temp_val.f*10);
  Real_Humidity=(uint16_t)(humi_val.f*10);      
  // 温度
  Real_Temperature=Real_Temperature+Temp_Offset;
  wg=Real_Temperature%10;    // ge
  ws=(Real_Temperature%100)/10;    // shi
  wb=(Real_Temperature%1000)/100;  // Bai
  
  // 湿度
  Real_Humidity=Real_Humidity+Humi_Offset;
  if(Real_Humidity>990)Real_Humidity=990;
  sg=Real_Humidity%10;   // ge
  ss=(Real_Humidity%100)/10;    // shi
  sb=(Real_Humidity%1000)/100;  // Bai
}
}


使用特权

评论回复
22
dsoyy|  楼主 | 2016-1-7 09:25 | 只看该作者
Ketose 发表于 2016-1-6 17:32
用逻辑分析仪看下延时函数是否正确。

用逻辑分析仪看来,符合手册里面的时序。

第一次读取结构每次都正确。第二次在读取就错了,偏差很大。

并且,第一次读取结束后,复位传感器,或者重新初始化传感器引脚,均不能改变第二次读取错误的问题

使用特权

评论回复
23
dsoyy|  楼主 | 2016-1-7 09:25 | 只看该作者
Brand2 发表于 2016-1-6 20:52
关键就是看延时准吗

按照手册来看,几个有时间要求的时间都是满足要求的。

使用特权

评论回复
24
dsoyy|  楼主 | 2016-1-7 09:27 | 只看该作者
本帖最后由 dsoyy 于 2016-1-7 09:31 编辑

我比较测试下。在反馈。
感谢另外上传代码是怎么做到你这种格式的,下面有复制选项的?

使用特权

评论回复
25
Ketose| | 2016-1-7 09:43 | 只看该作者
dsoyy 发表于 2016-1-7 09:25
用逻辑分析仪看来,符合手册里面的时序。

第一次读取结构每次都正确。第二次在读取就错了,偏差很大。

你没懂我的意思
我的意思是使用延时函数产生一个PWM,然后看下脉宽是否正确。如果你延时10us的高电平,结果出来20us的高电平,那肯定是延时函数的问题了。

使用特权

评论回复
26
dsoyy|  楼主 | 2016-1-7 09:52 | 只看该作者
Ketose 发表于 2016-1-7 09:43
你没懂我的意思
我的意思是使用延时函数产生一个PWM,然后看下脉宽是否正确。如果你延时10us的高电平,结 ...

校准了

使用特权

评论回复
27
玛尼玛尼哄| | 2016-1-17 23:21 | 只看该作者
如果逻辑分析仪显示的节奏没错,那就是延时问题,就是中间的延时修改就行了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则