SHT10(温湿度传感器)类IIC代码

2019-07-20 03:19发布

F429BI测试过
//////////////
////IICD.h////
//////////////

#ifndef __IICD_H
#define __IICD_H
#include "sys.h"
#include "delay.h"
#include "usart.h"

//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"  //ucos 使用
#endif

//IO方向设置
#define  SDA_IND()  {GPIOD->MODER&=~(3<<(4*2));GPIOD->MODER|=0<<4*2;}  //PD4输入模式
#define  SDA_OUTD() {GPIOD->MODER&=~(3<<(4*2));GPIOD->MODER|=1<<4*2;}  //PD4输出模式

//IO操作函数
#define  IICD_SCL                        PDout(5)
#define  IICD_SDA                        PDout(4)
#define  READD_SDA                       PDin(4)

//IICD所有操作函数
void iicd_init(void);
u8 iicd_write_byte(u8 value);
u8 iicd_read_byte(u8 ack);
void iicd_transstart(void);
void iicd_connectreset(void);
u8 iicd_softreset(void);
u8 iicd_read_statusreg(u8 *p_value, u8 *p_checksum);
u8 iicd_write_statusreg(u8 *p_value);
u8 iicd_measure(u8 *p_value, u8 *p_checksum, u8 mode);
s16 iicd_getTem(void);
u16 iicd_getHum(s16 Tem);
#endif


//////////////
////IICD.c////
//////////////

#include "IICD.h"
#define IIC_DELAY_TIME 10

#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

enum {TEMP,HUMI};
u8 iicd_valueH, iicd_valueL,iicd_crc8;


//-------------//
// iicd initial//
//-------------//
void iicd_init(void){
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);        //使能GPIO时钟

    //GPIO初始化设置
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4|GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;              //普通输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;              //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;          //100MHz
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;               //上拉
    GPIO_Init(GPIOD, &GPIO_InitStructure);                      //初始化

    IICD_SCL=0;IICD_SDA=1;
}

//---------------------------------------------------------//
// writes a byte on the Sensibus and checks the acknowledge//
//---------------------------------------------------------//
u8 iicd_write_byte(u8 value){
    u8 i,error=0;

    SDA_OUTD();
    for (i=0x80;i>0;i/=2){                            //shift bit for masking
        if (i & value) IICD_SDA=1;            //masking value with i , write to SENSI-BUS
        else IICD_SDA=0;
        delay_us(IIC_DELAY_TIME);IICD_SCL=1;delay_us(IIC_DELAY_TIME); //clk for SENSI-BUS
        delay_us(IIC_DELAY_TIME);IICD_SCL=0;delay_us(IIC_DELAY_TIME); //pulswith approx. 5 us
    }
    IICD_SDA=1;                                                    //release DATA-line

    SDA_IND();
    delay_us(IIC_DELAY_TIME);IICD_SCL=1;delay_us(IIC_DELAY_TIME);
    error=READD_SDA;                                    //check ack (DATA will be pulled down by SHT11)
    delay_us(IIC_DELAY_TIME);IICD_SCL=0;delay_us(IIC_DELAY_TIME);//clk拉低

    return error;
}

//---------------------------------------------------------------------------//
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"//
//---------------------------------------------------------------------------//
u8 iicd_read_byte(u8 ack){
    u8 i,val=0;
    IICD_SDA=1;                         //release DATA-line

    SDA_IND();
    for (i=0x80;i>0;i/=2){              //shift bit for masking
        delay_us(IIC_DELAY_TIME);IICD_SCL=1;delay_us(IIC_DELAY_TIME);//clk for SENSI-BUS
        if (READD_SDA) val |= i;        //read bit
        delay_us(IIC_DELAY_TIME);IICD_SCL=0;delay_us(IIC_DELAY_TIME);
    }

    SDA_OUTD();
    IICD_SDA=!ack;                      //in case of "ack==1" pull down DATA-Line
    delay_us(IIC_DELAY_TIME);IICD_SCL=1;delay_us(IIC_DELAY_TIME);//clk #9 for ack
    delay_us(IIC_DELAY_TIME);IICD_SCL=0;delay_us(IIC_DELAY_TIME);
    IICD_SDA=1;                         //release DATA-line

    return val;
}

//-------------------------------//
// generates a transmission start//
//-------------------------------//
//       _____         ________
// DATA:      |_______|
//           ___     ___
// SCK : ___|   |___|   |______
//-------------------------------//

void iicd_transstart(void){
//初始状态
    SDA_OUTD();IICD_SDA=1;IICD_SCL=0;

//开始信号
    delay_us(IIC_DELAY_TIME);IICD_SCL=1;delay_us(IIC_DELAY_TIME);//clk拉高
    IICD_SDA=0;
    delay_us(IIC_DELAY_TIME);IICD_SCL=0;delay_us(IIC_DELAY_TIME);//clk拉低

    delay_us(IIC_DELAY_TIME);IICD_SCL=1;delay_us(IIC_DELAY_TIME);//clk拉高
    IICD_SDA=1;
    delay_us(IIC_DELAY_TIME);IICD_SCL=0;delay_us(IIC_DELAY_TIME);//clk拉低
}

//----------------------------------------------------------------------------------//
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart//
//----------------------------------------------------------------------------------//
//       _____________________________________________________         ________
// DATA:                                                      |_______|
//          _    _    _    _    _    _    _    _    _        ___     ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
//----------------------------------------------------------------------------------//

void iicd_connectreset(void){
    u8 i;
//初始状态
    SDA_OUTD();IICD_SDA=1;IICD_SCL=0;
//复位方法
    for(i=0;i<9;i++){
        delay_us(IIC_DELAY_TIME);IICD_SCL=1;delay_us(IIC_DELAY_TIME);//clk拉高
        delay_us(IIC_DELAY_TIME);IICD_SCL=0;delay_us(IIC_DELAY_TIME);//clk拉低
    }
    iicd_transstart();
}

//---------------------------------//
// resets the sensor by a softreset//
//---------------------------------//

u8 iicd_softreset(void){
    u8 error=0;
    iicd_connectreset();                      //reset communication
    error+=iicd_write_byte(RESET);      //send RESET-command to sensor
    return error;                             //error=1 in case of no response form the sensor
}

//------------------------------------------------//
// reads the status register with checksum (8-bit)//
//------------------------------------------------//

u8 iicd_read_statusreg(u8 *p_value, u8 *p_checksum){
    u8 error=0;
    iicd_transstart();                  //transmission start
    error=iicd_write_byte(STATUS_REG_R);//send command to sensor
    *p_value=iicd_read_byte(ACK);       //read status register (8-bit)
    *p_checksum=iicd_read_byte(noACK);  //read checksum (8-bit)

    printf("read_statusreg is %x.reg checksum is %x. ",*(p_value),*p_checksum);
    return error;                             //error=1 in case of no response form the sensor
}

//-------------------------------------------------//
// writes the status register with checksum (8-bit)//
//-------------------------------------------------//

u8 iicd_write_statusreg(u8 *p_value){
    u8 error=0;
    iicd_transstart();                  //transmission start
    error+=iicd_write_byte(STATUS_REG_W);//send command to sensor
    error+=iicd_write_byte(*p_value);   //send value of status register
    return error;                       //error>=1 in case of no response form the sensor
}

//---------------------------------------------------------//
// makes a measurement (humidity/temperature) with checksum//
//---------------------------------------------------------//
u8 iicd_measure(u8 *p_value, u8 *p_checksum, u8 mode){
    u16 error=0;
    u32 i;

    iicd_transstart();                  //transmission start

    switch(mode){                       //send command to sensor
        case TEMP   : error+=iicd_write_byte(MEASURE_TEMP); break;
        case HUMI   : error+=iicd_write_byte(MEASURE_HUMI); break;
        default     : break;
    }

    for (i=0;i<65535;i++) {
        if(READD_SDA==0) break;             //wait until sensor has finished the measurement
        delay_us(30);
    }        
    if(READD_SDA) error+=1;             // or timeout (~2 sec.) is reached

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

    printf("value0 is %x.value1 is %x.checksum is %x. ",*(p_value),*(p_value+1),*p_checksum);
    return error;
}



////////////////////////////////////////////////////////////////////////
//实际计算公式                                                        //
//Tem=0.01*recieveDateT-39.63;                                        //
//HumRaw=-4+0.0405*recieveDateH-2.8*10^(-6)*recieveDateH*recieveDateH //
//HumCal=(Tem-25)*(0.01+0.00008*recieveDateH)+HumRaw                  //
////////////////////////////////////////////////////////////////////////

//得到扩大了10^2倍的温度
s16 iicd_getTem(void){
    u8 error;
    u16 TemDate;
    s16 Tem;
    error=iicd_measure(&iicd_valueH, &iicd_valueL,0);  //0,tem.1,hum
    if(error==0){
        TemDate=((u16)iicd_valueH<<8)+iicd_valueL;
        Tem=TemDate-3963;
        return Tem;
    }
    else return 0x1fff;
}

//得到扩大了10^2倍的湿度
u16 iicd_getHum(s16 Tem){   
    u8 error;
    u16 HumDate;
    u32 HumOri;
    u32 HumCal;
    u16 Hum;

    error=iicd_measure(&iicd_valueH, &iicd_valueL,1);  //0,tem.1,hum

    if(error==0){
        HumDate=((u16)iicd_valueH<<8)+iicd_valueL;
        HumOri=405000*HumDate-28*HumDate*HumDate-40000000;
        HumCal=(Tem-2500)*(1000+8*HumDate)+HumOri;
        Hum=HumCal/100000;
        return Hum;
    }   
    else return 0x1fff;
}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
4条回答
lengjingzju
2019-07-20 07:24
有个小bug
u8 iicd_measure(u8 *p_value, u8 *p_checksum, u8 mode)函数和它的声明
改为u8 iicd_measure(u8 *p_value0, u8 *p_value1, u8 *p_checksum, u8 mode)
这个函数里中*(p_value) 改为*(p_value0)  ;*(p_value+1) 改为*(p_value1)
相应的调用这个函数的部分请修改。
如温度 error=iicd_measure(&iicd_valueH,  &iicd_valueL, &iicd_crc8,0);
如湿度 error=iicd_measure(&iicd_valueH,  &iicd_valueL, &iicd_crc8,1);

当然你也可以不这样修改,如valueH,valueL变为数组value[2],再改得到温度和得到湿度这两个函数。

一周热门 更多>