关于温湿度SHT20传感器,用普通GPIO口来模拟IIC实现驱动

时间:2022-05-04 00:14:40

/******************************************************************************
*-----------------SHT_PROTOCOL_H.h文件-----------------------------------
*******************************************************************************
* 对SHT20温湿度传感器进行采集,头文件说明
---------------------------------------------------------------------------------------------------
*******************************************************************************/


#ifndef __SHT_PROTOCOL_H__

#define __SHT_PTOTOCOL_H__

/*******************************************************************************
================================数据部分=================
*******************************************************************************/

//定义了温度传感器SHT20的scl和sda口
#define sht_scl_pin            0//GPIO口
#define sht_sda_pin            1//gpio口

//读写指令
#define   READ    0x81
#define   WRITE   0x80  

#define  HOLD_AT_START  0xe3  //触发温度测量
#define  HOLD_AH_START  0xe5  //触发湿度测量
#define  NO_HOLD_AT_START  0xf3 //触发温度测量
#define  NO_HOLD_AH_START  0xf5 //触发湿度测量
#define  WRITE_REG      0xe6    //写寄存器
#define  READ_REG       0xe7    //读寄存器
#define  REST           0xfe    //软件复位





/*****************************************************************************
=================================函数部分=================================
*****************************************************************************/


/*****************************************************************************
*    function:
*        void SHT_set_scl_state(int flag)
*    description:
*        设置SCL口的输出状态
*    param:
*        int flag :  0 : 输出为0
*                1 : 输出为1
*    return:    
*        void
*****************************************************************************/
void SHT_set_scl_state(int flag);

/*****************************************************************************
*    function:
*        int SHT_get_sda_state(void);
*    description:
*        读取SDA口的状态值
*    param:
*        void
*    return:    
*        int : IO的状态
*****************************************************************************/
int SHT_get_sda_state(void);


/*****************************************************************************
*    function:
*        void vkelD1_SHT_set_sda_state(int flag)
*    description:
*        设置SDA口的输出状态
*    param:
*        int flag :  0 : 输出为0
*                1 : 输出为1
*    return:    
*        void
*****************************************************************************/
void SHT_set_sda_state(int flag);


/*****************************************************************************
*    function:
*        void SHT_set_sda_dir(int flag)
*    description:
*        设置SDA口是输入还是输出状态
*    param:
*        int flag :  0 : 输入
*                1 : 输出
*    return:    
*        void
*****************************************************************************/
void SHT_set_sda_dir(int flag);

/*****************************************************************************
*    function:
*        void SHT_set_scl_dir(int flag)
*    description:
*        设置SCL口是输入还是输出状态
*    param:
*        int flag :  0 : 输入
*                1 : 输出
*    return:    
*        void
*****************************************************************************/
void SHT_set_scl_dir(int flag);

/*****************************************************************************
*    function:
*        void SHT_iic_start()
*    description:
*        启动IIC
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_start();

/*****************************************************************************
*    function:
*        void SHT_iic_start()
*    description:
*        停止IIC
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_stop();

/*****************************************************************************
*    function:
*        int SHT_iic_waitAck()
*    description:
*        等待IIC响应
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
int SHT_iic_waitAck();

/*****************************************************************************
*    function:
*        void SHT_iic_sendAck()
*    description:
*        发送响应
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_sendAck();

/*****************************************************************************
*    function:
*        void SHT_iic_sendNoAck()
*    description:
*        发送非响应
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_sendNoAck();

/*****************************************************************************
*    function:
*        void SHT_iic_sendByte()
*    description:
*        发送一个字节
*    param:
*        unsigned char byte : 需要发送的一个字节
*    return:    
*        void
*****************************************************************************/
void SHT_iic_sendByte(unsigned char byte);

/*****************************************************************************
*    function:
*        unsigned char SHT_iic_recvByte()
*    description:
*        接收一个字节
*    param:
*        void
*    return:    
*        unsigned char : 接收到的一个字节
*****************************************************************************/
unsigned char SHT_iic_recvByte(void);

/*****************************************************************************
*    function:
*        void SHT_iic_Init()
*    description:
*        初始化SHT温湿度传感器
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_Init();




/*****************************************************************************
*    function:
*        void SHT_delay_1us(unsigned int delay);
*    description:
*        1us的延时函数
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
 void SHT_delay_1us(unsigned int delay);


/*****************************************************************************
*    function:
*        float SHT_get_temp(void)
*    description:
*        经过转换,获取SHT的温度值,
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
float SHT_get_temp(void);

/*****************************************************************************
*    function:
*        float SHT_get_hum(void)
*    description:
*        经过转换,获取SHT的湿度值,
*    param:
*        void
*    return:    
*        void

*****************************************************************************/

float SHT_get_hum(void);



/*****************************************************************************
*    function:
*        void SHT_init();
*    description:
*        初始化启动任务
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_init();

#endif


=================================================================

=================================================================

SHT_protocol.c file


#include "SHT_protocol.h"
/*******************************************************************************
================================函数部分==================
*******************************************************************************/

//vkelD1_delay_1us
//d1_sht_scl_pin    
//d1_sht_sda_pin    


/*****************************************************************************
*    function:
*        void SHT_set_scl_state(int flag)
*    description:
*        设置SCL口的输出状态
*    param:
*        int flag :  0 : 输出为0
*                1 : 输出为1
*    return:    
*        void
*****************************************************************************/
void SHT_set_scl_state(int flag)
{
    GPIO_WriteIO(flag, sht_scl_pin);
}

/*****************************************************************************
*    function:
*        int SHT_get_sda_state(void);
*    description:
*        读取SDA口的状态值
*    param:
*        void
*    return:    
*        int : IO的状态
*****************************************************************************/
int SHT_get_sda_state(void)
{
    if(GPIO_ReadIO(sht_sda_pin))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}


/*****************************************************************************
*    function:
*        void SHT_set_sda_state(int flag)
*    description:
*        设置SDA口的输出状态
*    param:
*        int flag :  0 : 输出为0
*                1 : 输出为1
*    return:    
*        void
*****************************************************************************/
void SHT_set_sda_state(int flag)
{
    GPIO_WriteIO(flag, sht_sda_pin);
}


/*****************************************************************************
*    function:
*        void SHT_set_sda_dir(int flag)
*    description:
*        设置SDA口是输入还是输出状态
*    param:
*        int flag :  0 : 输入
*                1 : 输出
*    return:    
*        void
*****************************************************************************/
void SHT_set_sda_dir(int flag)
{
    GPIO_InitIO(flag, sht_sda_pin);
}

/*****************************************************************************
*    function:
*        void SHT_set_scl_dir(int flag)
*    description:
*        设置SCL口是输入还是输出状态
*    param:
*        int flag :  0 : 输入
*                1 : 输出
*    return:    
*        void
*****************************************************************************/
void SHT_set_scl_dir(int flag)
{
    GPIO_InitIO(flag, sht_scl_pin);
}

/*****************************************************************************
*    function:
*        void SHT_iic_start()
*    description:
*        启动IIC
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_start()
{
    SHT_set_sda_dir(1);
    
    SHT_set_scl_state(1);//在SCL为高电瓶的时候
    
    SHT_set_sda_state(1);//SDA有一个下降沿
    SHT_delay_1us(2);
    SHT_set_sda_state(0);

    SHT_delay_1us(2);    
}

/*****************************************************************************
*    function:
*        void SHT_iic_start()
*    description:
*        停止IIC
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_stop()
{
    SHT_set_sda_dir(1);
    
    SHT_set_scl_state(1);//在SCL为高电瓶的时候
    
    SHT_set_sda_state(0);//SDA有一个上升沿
    SHT_delay_1us(2);
    SHT_set_sda_state(1);

   SHT_delay_1us(2);    
}

/*****************************************************************************
*    function:
*        void SHT_iic_waitAck()
*    description:
*        等待IIC响应
*    param:
*        void
*    return:    
*        int 返回读取
*****************************************************************************/
int SHT_iic_waitAck()
{
    int overTime = 255;
    
    SHT_set_sda_dir(0);//SDA设置成输入

    SHT_delay_1us(1);
    SHT_set_scl_state(0);
    SHT_delay_1us(1);
    SHT_set_scl_state(1);//上升沿波
    SHT_delay_1us(1);
    while(SHT_get_sda_state())//等待SDA被拉低电平
    {
        //读取总线上的ACK信号
        overTime--;
        if(overTime <= 0)
        {
            SHT_iic_stop();//
            return 0;
        }
        SHT_delay_1us(1);
    }

    SHT_set_scl_state(0);

    return 1;    
}

/*****************************************************************************
*    function:
*        void SHT_iic_sendAck()
*    description:
*        发送响应
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_sendAck()
{
    SHT_set_sda_dir(1);//SDA设置成输出

    SHT_set_sda_state(0);//在SCL边沿,sda输出为底
    SHT_delay_1us(2);

    SHT_set_scl_dir(1);
    SHT_delay_1us(2);

    SHT_set_scl_dir(0);

}

/*****************************************************************************
*    function:
*        void SHT_iic_sendNoAck()
*    description:
*        发送非响应
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_sendNoAck()
{
    SHT_set_sda_dir(1);//SDA设置成输出

    SHT_set_sda_state(1);//在SCL边沿,sda输出为底
    SHT_delay_1us(2);

    SHT_set_scl_dir(1);
    SHT_delay_1us(2);

    SHT_set_scl_dir(0);

}

/*****************************************************************************
*    function:
*        void SHT_iic_sendByte()
*    description:
*        发送一个字节
*    param:
*        unsigned char byte : 需要发送的一个字节
*    return:    
*        void
*****************************************************************************/
void SHT_iic_sendByte(unsigned char byte)
{
    int i = 0;

    SHT_set_sda_dir(1);//设置成输出的方向
    
    //循环一个字节
    for(i = 0; i < 8; i++)
    {
        SHT_set_scl_state(0);
        if(byte&0x80)
        {
            SHT_set_sda_state(1);
        }
        else
        {
            SHT_set_sda_state(0);
        }
        SHT_delay_1us(2);
        SHT_set_scl_state(1);
        SHT_delay_1us(2);

        byte = byte<<1;
    }

    SHT_set_scl_state(0);
}

/*****************************************************************************
*    function:
*        unsigned char SHT_iic_recvByte()
*    description:
*        接收一个字节
*    param:
*        void
*    return:    
*        unsigned char : 接收到的一个字节
*****************************************************************************/
unsigned char SHT_iic_recvByte(void)
{
    int i = 0;
    unsigned char data = 0;

    SHT_set_sda_dir(0);//设置成输入的方向
    
    for(i = 0; i < 8; i++)
    {
        data <<= 1;
        SHT_set_scl_state(0);
        SHT_delay_1us(2);
        SHT_set_scl_state(1);
        if(SHT_get_sda_state())
        {
            data |= 0x01;
        }
        else
        {
            data &= 0xfe;
        }        
    }
    SHT_delay_1us(2);
   SHT_set_scl_state(0);

    return data;
}

/*****************************************************************************
*    function:
*        void SHT_iic_Init()
*    description:
*        初始化SHT温湿度传感器
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_iic_Init()
{
    SHT_iic_start();
    SHT_iic_sendByte(WRITE);

    if(SHT_iic_waitAck())
    {
        SHT_iic_sendByte(REST);//复位指令

        if(SHT_iic_waitAck())
        {
            SHT_iic_stop();
        }
    }
}


/*****************************************************************************
*    function:
*        float SHT_get_temp(void)
*    description:
*        经过转换,获取SHT的温度值,直接四舍五入存储到
*        _uct_tag_TH_data中
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
float vkelD1_SHT_get_temp(void)
{
    unsigned int dat= 0;
    unsigned char Hbyte = 0;
    unsigned char Lbyte = 0;
    unsigned char crc = 0;

    float temp = 0;

    SHT_iic_start();
    SHT_iic_sendByte(WRITE);

    if(SHT_iic_waitAck())
    {
        SHT_iic_sendByte(NO_HOLD_AT_START);
        if(SHT_iic_waitAck())
        {
            do
            {
                SHT_iic_start();
                SHT_iic_sendByte(READ);
                
            }while(SHT_iic_waitAck() == 0);

            Hbyte = SHT_iic_recvByte();//接收到高字节的数据
            SHT_iic_sendAck();//发送应答

            Lbyte = SHT_iic_recvByte();//接收到底字节的数据
            SHT_iic_sendAck();//发送应答

            crc = SHT_iic_recvByte();//接收到底字节的数据
            SHT_iic_sendNoAck();

            SHT_iic_stop();

            Lbyte &= 0xfc;
            dat = (Hbyte<<8)|Lbyte;

            temp = (dat*175.72)/65536-46.85;
           
        }
    }

     return temp;
}

/*****************************************************************************
*    function:
*        float SHT_get_hum(void)
*    description:
*        经过转换,获取SHT的湿度值,直接四舍五入存储到
*        _uct_tag_TH_data中
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
float SHT_get_hum(void)
{
    unsigned int dat = 0;
    unsigned char Hbyte = 0;
    unsigned char Lbyte = 0;
    unsigned char crc = 0;
    float temp = 0;

    SHT_iic_start();
    SHT_iic_sendByte(WRITE);

    if(SHT_iic_waitAck())
    {
        SHT_iic_sendByte(NO_HOLD_AH_START);
        if(SHT_iic_waitAck())
        {
            do
            {
                SHT_iic_start();
                SHT_iic_sendByte(READ);
                
            }while(SHT_iic_waitAck() == 0);

            Hbyte = SHT_iic_recvByte();//接收到高字节的数据
            SHT_iic_sendAck();//发送应答

            Lbyte = SHT_iic_recvByte();//接收到底字节的数据
            SHT_iic_sendAck();//发送应答

            crc = SHT_iic_recvByte();//接收到底字节的数据
            SHT_iic_sendNoAck();

           SHT_iic_stop();

            Lbyte &= 0xfc;
            dat = (Hbyte<<8)|Lbyte;

            temp = (float)((dat*125.0)/65536.0-6);
  
        }
    
    }

    return temp;
}

/*****************************************************************************
*    function:
*        void SHT_delay_1us(unsigned int delay);
*    description:
*        1us的延时函数
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
 void SHT_delay_1us(unsigned int delay)

{

      int count = 100;

      int i = 0;

      for(i = 0; i < delay; i++)

       {

             while(count--);

       }

}


/*****************************************************************************
*    function:
*        void SHT_init();
*    description:
*        初始化启动任务
*    param:
*        void
*    return:    
*        void
*****************************************************************************/
void SHT_init()
{

    GPIO_ModeSetup(sht_scl_pin, 0);//作为普通额GPIO口
    GPIO_ModeSetup(sht_sda_pin, 0);//作为普通的GPIO口来模拟IIC的功能

    GPIO_PullenSetup(sht_scl_pin, 1);//使能上拉
    GPIO_PullenSetup(sht_sda_pin, 1);

    SHT_set_scl_dir(1);//SCL设置成输出
}