цифровая электроника
вычислительная техника
встраиваемые системы

 
» » » Библиотека для работы с датчиком SHT11



Библиотека для работы с датчиком SHT11

Автор: Mike(admin) от 30-03-2014, 14:00

Для определения влажности и температуры радиолюбители в своих проектах иногда используют датчик SHT11 от Sensirion. Этот датчик с интерфейсом I2C обладает хорошей точностью измерений, поддерживает широкие диапазоны температуры, относительной влажности и рабочего напряжения.


Проблемой для начинающих может быть настройка связи с вычислительным устройством, например, микроконтроллером. Поэтому ниже предлагается платформонезависимая библиотека, позволяющая общаться с SHT11.


Основная функция здесь представляет собой конечный автомат. Для того, чтобы прочитать с датчика все необходимые данные, в главном цикле должна быть вызвана соответствующая функция. В конце кода имеется пример такого вызова. Для адаптации кода для различных архитектур пользователь должен написать свой заголовочный файл sht_low_level_drv.h. Также он должен обозначить переменную sys_timer_ticks, которая инкрементируется каждую 1 мс.



/*********** начало заголовочного файла библиотеки sht11.h ***************/

#ifndef _SHTXX_H
#define _SHTXX_H

#include <inttypes.h>


#define HUMIDITY_BYTE    0x05
#define TEMPERATURE_BYTE 0x03

//State machine states

#define SHT_DATA_WAIT_INITIAL_STATE     0
#define SHT_DATA_WAIT_TIMEOUT_STATE     1

#define SHT_PROC_RESET_COND_STATE       0  
#define SHT_PROC_START_COND_STATE       1
#define SHT_PROC_SEND_STATE             2
#define SHT_PROC_WAIT_STATE             3
#define SHT_PROC_RETURN_STATE           4

#define SHT_RH_READ_TEMPERATURE_STATE   0
#define SHT_RH_READ_HUMIDITY_STATE      1
#define SHT_RH_CONVERT_RH_STATE         2


#include <sht_low_level_drv.h>

void shtxx_init(void);

int shtxx_proc(uint8_t sht_param,uint16_t *ret_value);

int shtxx_get_temp(uint16_t *ret_temperature);
int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity );

#endif /* _SHTXX_H */

/*********** начало файла с исходным кодом библиотеки sht11.c ***************/
#include "sht11.h"

void shtxx_init( void )
{
    shtxx_set_db();
    shtxx_set_cb();
}


void shtxx_wait( void ) //SHT_WAIT должен быть настроен в соответствии с тактированием МК
{
    volatile int wait_cnt;
    for ( wait_cnt = 0; wait_cnt < SHT_WAIT;wait_cnt )
    {
        wait_cnt++;
    }
}

void shtxx_reset_condition( void )
{
    uint8_t i;
    shtxx_set_db();
    shtxx_set_out_data_dir();
    for ( i = 0;i < 12;i++ )
    {
        if ( i % 2 == 0 )
            shtxx_set_cb();
        else
            shtxx_clr_cb();
        shtxx_wait();
    }
}

void shtxx_start_condition( void )
{
    shtxx_set_db();
    shtxx_set_out_data_dir();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    shtxx_clr_db();
    shtxx_wait();
    shtxx_clr_cb();
    shtxx_wait();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    shtxx_set_db();
    shtxx_wait();
    shtxx_clr_cb();
    shtxx_wait();

}

int shtxx_send_byte( uint8_t sht_data2send )
{
    uint8_t i = 0;
    while ( i <= 7 )
    {
        if ( ( ( sht_data2send << i++ ) & 0x80 ) == 0x80 )
            shtxx_set_db();
        else
            shtxx_clr_db();
        shtxx_set_out_data_dir();
        shtxx_wait();
        shtxx_set_cb();
        shtxx_wait();
        shtxx_clr_cb();

    }
    shtxx_set_in_data_dir();
    shtxx_wait();
    shtxx_set_cb();
    shtxx_wait();
    if ( shtxx_get_db() == 0 )
        return 1;

    else
        return -1;
}

int shtxx_data_wait( sht_ticks_t sht_timeout )
{
    static uint8_t sht_wait_state;
    static sht_ticks_t sht_previous_ticks;

    switch ( sht_wait_state )
    {
    case SHT_DATA_WAIT_INITIAL_STATE:
        sht_previous_ticks = sht_msec_ticks;
        sht_wait_state = SHT_DATA_WAIT_TIMEOUT_STATE;
        shtxx_set_in_data_dir();
        shtxx_clr_cb();

    case SHT_DATA_WAIT_TIMEOUT_STATE:
        if ( shtxx_get_db() == 0 )
        {
            sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
            return 1;
        }
        else
        {
            if ( ( sht_msec_ticks - sht_previous_ticks ) > sht_timeout )
            {
                sht_wait_state = SHT_DATA_WAIT_INITIAL_STATE;
                return -1;
            }
            else
                return 0;
        }
    }
}

uint8_t sht_read_byte( uint8_t sht_ack )
{
    shtxx_set_in_data_dir();
    uint8_t temp_rx_buff = 0;
    int8_t i = 7;
    while ( i >= 0 )
    {
        shtxx_wait();
        shtxx_set_cb();
        temp_rx_buff |= ( ( shtxx_get_db() & 0x01 ) << i );
        i--;
        shtxx_wait();
        shtxx_clr_cb();

    }

    if ( sht_ack == 1 )
    {
        shtxx_clr_db();
        shtxx_set_out_data_dir();
        shtxx_wait();
        shtxx_set_cb();
        shtxx_wait();
        shtxx_clr_cb();
        shtxx_set_in_data_dir();

    }
    return temp_rx_buff;
}


int shtxx_proc( uint8_t sht_param, uint16_t *ret_value )
{

    static uint8_t sht_proc_state = 0;
    int8_t      wait_status;

    switch ( sht_proc_state )
    {
    case SHT_PROC_RESET_COND_STATE:
        shtxx_reset_condition();
    case SHT_PROC_START_COND_STATE:
        shtxx_start_condition();
    case SHT_PROC_SEND_STATE:
        shtxx_send_byte( sht_param );
    case SHT_PROC_WAIT_STATE:
        wait_status = shtxx_data_wait( 300 );
        if ( wait_status == -1 )
        {
            sht_proc_state = SHT_PROC_RESET_COND_STATE;
            return -1;

        }
        if ( wait_status == 0 )
        {
            sht_proc_state = SHT_PROC_WAIT_STATE;
            return 0;
        }
        else
            sht_proc_state = SHT_PROC_RETURN_STATE;
    case SHT_PROC_RETURN_STATE:
        *ret_value = ( ( uint16_t ) sht_read_byte( 1 ) << 8 );
        shtxx_wait();
        *ret_value += sht_read_byte( 0 );
        sht_proc_state = SHT_PROC_START_COND_STATE;
        return 1;

    }
}

int shtxx_get_temp( uint16_t *ret_temperature )
{
    static uint16_t tmp_temp;
    if ( shtxx_proc( TEMPERATURE_BYTE, &tmp_temp ) == 1 )
    {
        *ret_temperature = tmp_temp - 3965;
        return 1;
    }
    else
        return 0;
}

int shtxx_get_temp_RH( int16_t *ret_temperature, int16_t *ret_humidity )
{

    static uint8_t sht_humidity_state;
    static uint16_t sht_humidity_raw;
    static uint16_t sht_temp_C;

    static float RH_linear;
    static float RH_compensated;

    switch ( sht_humidity_state )
    {
    case SHT_RH_READ_TEMPERATURE_STATE:
        if ( shtxx_get_temp( &sht_temp_C ) )
            sht_humidity_state = SHT_RH_READ_HUMIDITY_STATE;
        break;
    case SHT_RH_READ_HUMIDITY_STATE:
        if ( shtxx_proc( HUMIDITY_BYTE, &sht_humidity_raw ) )
            sht_humidity_state = SHT_RH_CONVERT_RH_STATE;
        break;
    case SHT_RH_CONVERT_RH_STATE:
        RH_linear = ( float ) ( ( 0.0405 * ( float ) sht_humidity_raw ) - ( 0.0000028 * ( float ) sht_humidity_raw * ( float ) sht_humidity_raw ) - 4 );
        RH_compensated = ( float ) ( ( ( ( ( ( float ) sht_temp_C ) / 100 ) - 25 ) * ( 0.01 + ( 0.00008 * ( float ) sht_humidity_raw ) ) ) + RH_linear );
        sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
        *ret_temperature = sht_temp_C;
        *ret_humidity = ( ( int16_t ) ( RH_compensated * 100 ) );
        return 1;
    default:
        sht_humidity_state = SHT_RH_READ_TEMPERATURE_STATE;
    }
        return 0;
}

/*** пример низкоуровневого определения (платформозависимо) sht_low_level_drv.h ***/


#ifndef _SHT_LOW_LEVEL_DRV_H
#define _SHT_LOW_LEVEL_DRV_H

#include <types.h>
#include <system_def.h> /* должны быть определены HW,  SHT_PORT, SHT_DATA_BIT*/

#define SHT_MAX_CLK             100000
#define SHT_WAIT                (CCLK/SHT_MAX_CLK) /* CCLK определяется тактируемой частотой */
#define sht_ticks_t             uint32_t
#define sht_msec_ticks          sys_timer_ticks /* эта переменная должна быть определена в BSP и инкрементироваться каждую мс*/

static inline void shtxx_set_db(void)
{
       
        SET_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}

static inline void shtxx_clr_db(void)
{
        CLR_OUT_PIN(SHT_PORT,SHT_DATA_BIT);
}

static inline void shtxx_set_cb(void)
{
        SET_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}

static inline void shtxx_clr_cb(void)
{
        CLR_OUT_PIN(SHT_PORT,SHT_CLK_BIT);
}

static inline uint8_t shtxx_get_db(void)
{
        return( GET_IN_PIN(SHT_PORT,SHT_DATA_BIT) );   
}

static inline void shtxx_set_in_data_dir(void)
{
        IO0DIR &=~(SHT_DATA_BIT);
}

static inline void shtxx_set_out_data_dir(void)
{
        IO0DIR |= SHT_DATA_BIT ;
}

#endif /* _SHT_LOW_LEVEL_DRV_H */


/********************* пример использования в основной программе ************************/

//..............
int16_t temperature, humidity;

while(1) //основной цикл пользовательской программы
{
    if (shtxx_get_temp_RH( &temperature, &humidity )
    {
        //выполняем задачи
    }
    //выполняем прочие операции
    //.....................      
}



Перевод © digitrode.ru


<Источник>




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий