STM32 DHT8x驱动

通过模拟I2c对DHT8x传感器进行温度和湿度的读取。

 

/**************************************************.h文件**************************************************/

#ifndef __BSP_DTH8x_H

#define __BSP_DTH8x_H


#include "stm32f10x.h"


#define DTH8x_CH_MAX      16


enum __type
{
TEM=0,
HUM,
TEM_AND_HUM
};


//commond                        //adr commond r/w
#define WRITE_STATUS_REG   0x06  //000 0011    0
#define READ_STATUS_REG    0x07  //000 0011    1
#define TEM_MEASURE        0x03  //000 0001    1
#define HUM_MEASURE        0x05  //000 0010    1
#define RESET              0x1e  //000 1111    0

//config
typedef struct
{
unsigned char  sck_port;
unsigned char  sck_pin;
unsigned char  data_port;
unsigned char  data_pin;
}DTH8x_config_t;


//data
typedef struct
{
float tem;
float hum;
}DTH8x_Data_t;


typedef struct
{
unsigned char     isUsed;
DTH8x_config_t    config;
DTH8x_Data_t      state;
}DTH8x_t;


int DTH8x_setConfig(unsigned char ch, DTH8x_config_t config);
int DTH8x_GetConfig(unsigned char ch, DTH8x_config_t* config);
int DTH8x_Measure(unsigned char ch, enum __type type, unsigned char ischeckCrc);
int DTH8x_GetData(unsigned char ch, DTH8x_Data_t* value);


#endif
 

/**************************************************.c文件**************************************************/

#include "bsp_DTH8x.h"
#include <stdio.h>


DTH8x_t  DTH8x[DTH8x_CH_MAX] = {0};


//SCK
#define SCK_OUTPUT_H(port,pin)          GPIO_SetBits(port, pin)
#define SCK_OUTPUT_L(port,pin)          GPIO_ResetBits(port, pin)
//DATA
#define DATA_OUTPUT_H(port,pin)         GPIO_SetBits(port, pin)
#define DATA_OUTPUT_L(port,pin)         GPIO_ResetBits(port, pin)
#define DATA_INPUT_READ(port,pin)       GPIO_ReadInputDataBit(port, pin)


//ACK
enum __ack
{
NACK=0,
ACK
};


//tem cal
enum __tem_d1_cal
{
TEM_5V=0,
TEM_4V,
TEM_3_5V,
TEM_3V,
TEM_2_5V,
TEM_D1_ALL
};
typedef struct
{
float d1_C;
float d1_F;
}temD1_t;
temD1_t const temCal_d1[TEM_D1_ALL] = {
{-40.1, -40.2},
{-39.8, -39.6},
{-39.7, -39.5},
{-39.6, -39.3},
{-39.4, -38.9}
};


enum __tem_d2_cal
{
TEM_14BIT=0,
TEM_12BIT,
TEM_D2_ALL
};
typedef struct
{
float d2_C;
float d2_F;
}temD2_t;
temD2_t const temCal_d2[TEM_D2_ALL] = {
{0.01, 0.018}, 
{0.04, 0.072}
};


//hum cal
enum __hum_cal
{
HUM_12BIT=0,
HUM_8BIT,
HUM_ALL
};
typedef struct
{
float c1;
float c2;
float c3;
}humCal_t;
humCal_t const humCal[HUM_ALL] = {
{-2.0468, 0.0367, -0.0000015955}, 
{-2.0468, 0.5872, -0.00040845}
};


typedef struct
{
float t1;
float t2;
}humCmpe_t;
humCmpe_t const humCmp[HUM_ALL] = {
{0.01, 0.00008}, 
{0.01, 0.00128}
};


//cal
#define HUM_RH_LINEAR(c1,c2,c3,H)                ( c1 + (c2*H) + (c3*H*H) )               //相对湿度
#define TEM_TC(d1,d2,T)                          ( d1 + (d2*T) )                          //实际温度
#define HUM_RH_TRUE(t1,t2,H,RH_LINEAR,TC)        ( ( (TC-25)*(t1+(t2*H)) ) + RH_LINEAR )  //实际湿度


//void delay_nus(unsigned long n)
//{
// unsigned long j = 0;
//
// while(n--)
// {
// j = 12;
// while(j--);
// }
//}


static GPIO_TypeDef* getPortIdx(INT8U port)
{
INT8U PortIdx = port;
GPIO_TypeDef* GPIOx = NULL;

switch(PortIdx)
{
case 0: GPIOx = GPIOA; break;
case 1: GPIOx = GPIOB; break;
case 2: GPIOx = GPIOC; break;
case 3: GPIOx = GPIOD; break;
case 4: GPIOx = GPIOE; break;
case 5: GPIOx = GPIOF; break;
case 6: GPIOx = GPIOG; break;
default:break;
}

return GPIOx;
}


static unsigned short getPinIdx(INT8U pin)
{
return (unsigned short)(1<<pin);
}


int DTH8x_DATA_GpioModeSet(unsigned char ch, GPIOMode_TypeDef gpioMode)
{
int err = 0;
GPIO_InitTypeDef GPIO_InitStructure;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
err = -2;

//端口速度
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
//端口模式,此为输出推挽模式
GPIO_InitStructure.GPIO_Mode = gpioMode;
//DATA_PIN引脚设置
GPIO_InitStructure.GPIO_Pin = getPinIdx(DTH8x[ch].config.data_pin);
//DATA_PORT初始化端口
GPIO_Init(getPortIdx(DTH8x[ch].config.data_port), &GPIO_InitStructure);

return err;
}


int DTH8x_transferStart(unsigned char ch)
{
int err = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
return err = -1;

//init state
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
DATA_OUTPUT_L (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}
return err;
}


int DTH8x_connectionReset(unsigned char ch)
{
int err = 0;
unsigned char i = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
return err = -1;


//init state
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
for(i = 0; i < 9; i++)
{
__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
}

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}
err = DTH8x_transferStart(ch);

return err;
}


int DTH8x_writeByte(unsigned char ch, unsigned char value)
{
int err = 0;
int ack = 0;
unsigned char i = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
return err = -1;

//write
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

for(i = 0x80; i > 0; i/=2)
{
if(i&value)
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
else
DATA_OUTPUT_L (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
}

//release DATA-line
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

//data-line gpio set input
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_IPU);

//clk #9 for ack
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
//check ack
ack = DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

//data-line gpio set output
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_Out_PP);

//release DATA-line
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}

if(ack)
return err = -3;

return err;
}


unsigned char DTH8x_readByte(unsigned char ch, unsigned char ack, int* errCode)
{
unsigned char value = 0;
unsigned char i = 0;

if((ch >= DTH8x_CH_MAX) || (errCode == 0))
{
*errCode = -1;
return value;
}

if(!DTH8x[ch].isUsed)
{
*errCode = -2;
return value;
}

//read
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

//data-line gpio set input
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_IPU);

for(i = 0x80; i > 0; i/=2)
{
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

if(DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
value = value | i;


__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
}

 //data-line gpio set output
 DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_Out_PP);

if(ack)
DATA_OUTPUT_L (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
else
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

__nop();__nop();__nop();
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}

*errCode = 0;

return value;
}


//-----------------------------------------------
// crc caculate
//-----------------------------------------------
char DTH8x_crc8(char byte,char crc8)
{
 char i;
 char temp;

 crc8^=byte;
 for(i=0;i<8;i++)
 {
  temp=crc8;
  crc8<<=1;
  if((temp&0x80)!=0)
   crc8^=0x31;
 }
 
 return crc8;
}
//-----------------------------------------------
// swap crc byte
//-----------------------------------------------
char DTH8x_swapcrc(char byte)
{
 unsigned char i;
 char temp=0;
 
 for (i=0x80;i>0;i/=2)
 {
  if((byte&i)!=0)
   temp|=0x80;
  if(i==0x01)
   break;
  temp>>=1;
  temp&=0x7f;
 }
 
 return temp;
}


int DTH8x_CRC8_check(unsigned char commond,unsigned char adValueH,unsigned char adValueL,unsigned char checksum)
{
int isOk = 0;
unsigned char crcvalue = 0;


crcvalue = DTH8x_crc8(commond,crcvalue); //first byte ,commond
crcvalue = DTH8x_crc8(adValueH,crcvalue);//second byte,adValueH
crcvalue = DTH8x_crc8(adValueL,crcvalue);//thrid byte,adValueL
crcvalue = DTH8x_swapcrc(crcvalue);      //swap high and low bit

if(crcvalue==checksum)                   //checksum == crcvalue
isOk=1;

return isOk;
}


static int DTH8x_getAd(unsigned char ch, enum __type type, unsigned char isCheckCrc, unsigned short* value)
{
int err = 0;
unsigned char commond = 0;
unsigned char adValueH = 0;
unsigned char adValueL = 0;
unsigned short adValue = 0;
unsigned char checkSum = 0;
unsigned long int i = 0;

if((ch >= DTH8x_CH_MAX) || (value == 0))
err = -1;

if(!DTH8x[ch].isUsed)
err = -2;

//开始读取
{
//连接测量
err = DTH8x_transferStart(ch);
if(!err)
{
switch(type)
{
case TEM: commond = TEM_MEASURE; break;
case HUM: commond = HUM_MEASURE; break;
default: err = -1;               break;
}
}

if(!err)
{
//send commond
err = DTH8x_writeByte(ch,commond);

//data-line gpio set input
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_IPU);


//等待ACK,超时500ms
#ifdef RTOS_UCOS
for(i = 0; i < 100; i++)
{
if(!DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
break;

OSTimeDly(OSmsToTick(5));
}
#else
for(i = 0; i < SystemCoreClock/72; i++) //时钟为72M
{
if(!DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
break;
}
#endif


if(DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
err = -4;
}
//data-line gpio set output
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_Out_PP);

if(!err)
adValueH = DTH8x_readByte(ch,ACK,&err);//MSB


if(!err)
{
adValueL = DTH8x_readByte(ch,ACK,&err);
adValue = (unsigned short)(adValueH<<8) + adValueL;
}

if(!err)
checkSum = DTH8x_readByte(ch,NACK,&err);//check sum


// printf("***%s***: adValueH = 0x%02x, adValueL = 0x%02x, checkSum = 0x%02x, adValue = 0x%02x\r\n", \
//        (type==TEM?"TEM":"HUM"), adValueH, adValueL, checkSum, adValue);

if((!err) && (isCheckCrc))
{
if(!DTH8x_CRC8_check(commond,adValueH,adValueL,checkSum))
err = -5;
}

if(!err)
*value = adValue;
}

return err;
}


int DTH8x_Measure(unsigned char ch, enum __type type, unsigned char ischeckCrc)
{
int err = 0;
unsigned short temValue = 0;
unsigned short humValue = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;


if(!DTH8x[ch].isUsed)
return err = -2;

//计算真实值
switch(type)
{
case TEM:
{
err = DTH8x_getAd(ch, TEM, ischeckCrc, &temValue);
if(err == 0)
{
float d1 = temCal_d1[TEM_3_5V].d1_C;
float d2 = temCal_d2[TEM_14BIT].d2_C;
DTH8x[ch].state.tem = TEM_TC(d1,d2,temValue); 
}
}
break;
case HUM:
{
err = DTH8x_getAd(ch, HUM, ischeckCrc, &humValue);
if(err == 0)
{
float c1 = humCal[HUM_12BIT].c1;
float c2 = humCal[HUM_12BIT].c2;
float c3 = humCal[HUM_12BIT].c3;
float RH_linear = HUM_RH_LINEAR(c1,c2,c3,humValue);
float t1 = humCmp[HUM_12BIT].t1;
float t2 = humCmp[HUM_12BIT].t2;
DTH8x[ch].state.hum = HUM_RH_TRUE(t1,t2,humValue,RH_linear,DTH8x[ch].state.tem);
}
}
break;
case TEM_AND_HUM:
{
err = DTH8x_getAd(ch, TEM, ischeckCrc, &temValue);
if(err == 0)
{
float d1 = temCal_d1[TEM_3_5V].d1_C;
float d2 = temCal_d2[TEM_14BIT].d2_C;
DTH8x[ch].state.tem = TEM_TC(d1,d2,temValue); 
}

if(!err)
err = DTH8x_getAd(ch, HUM, ischeckCrc, &humValue);

if(err == 0)
{
float c1 = humCal[HUM_12BIT].c1;
float c2 = humCal[HUM_12BIT].c2;
float c3 = humCal[HUM_12BIT].c3;
float RH_linear = HUM_RH_LINEAR(c1,c2,c3,humValue);
float t1 = humCmp[HUM_12BIT].t1;
float t2 = humCmp[HUM_12BIT].t2;
DTH8x[ch].state.hum = HUM_RH_TRUE(t1,t2,humValue,RH_linear,DTH8x[ch].state.tem);
}
}
break;
default: err = -1;
break;
}

//异常复位
if(err)
{
printf("DTH8x_Measure, ch = %d, err = %d\r\n", ch, err);
DTH8x_connectionReset(ch);
}
else
{
//printf("ch = %d, tem = %.2fC, hum=%.2f%%\r\n", ch,DTH8x[ch].state.tem,DTH8x[ch].state.hum);
}

return err;
}


int DTH8x_setConfig(unsigned char ch, DTH8x_config_t config)
{
int err = 0;
GPIO_InitTypeDef GPIO_InitStructure;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if((getPortIdx(config.data_port) == 0) || (getPortIdx(config.sck_port) == 0) 
   || (getPinIdx(config.data_pin) > GPIO_Pin_All) || (getPinIdx(config.sck_pin) > GPIO_Pin_All))
return err = -1;

if((getPortIdx(config.data_port) == GPIOA)||(getPortIdx(config.sck_port) == GPIOA))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
else if((getPortIdx(config.data_port) == GPIOB)||(getPortIdx(config.sck_port) == GPIOB))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
else if((getPortIdx(config.data_port) == GPIOC)||(getPortIdx(config.sck_port) == GPIOC))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
else if((getPortIdx(config.data_port) == GPIOD)||(getPortIdx(config.sck_port) == GPIOD))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
else if((getPortIdx(config.data_port) == GPIOE)||(getPortIdx(config.sck_port) == GPIOE))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
else if((getPortIdx(config.data_port) == GPIOF)||(getPortIdx(config.sck_port) == GPIOF))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
else if((getPortIdx(config.data_port) == GPIOG)||(getPortIdx(config.sck_port) == GPIOG))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
else
return err = -1;


//端口速度
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
//端口模式,此为输出推挽模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//SCK_PIN引脚设置
GPIO_InitStructure.GPIO_Pin = getPinIdx(config.sck_pin);
//SCK_PORT初始化端口
GPIO_Init(getPortIdx(config.sck_port), &GPIO_InitStructure);
//DATA_PIN引脚设置
GPIO_InitStructure.GPIO_Pin = getPinIdx(config.data_pin);
//DATA_PORT初始化端口
GPIO_Init(getPortIdx(config.data_port), &GPIO_InitStructure);

//初始化参数
DTH8x[ch].isUsed = 1;
DTH8x[ch].config = config;
DTH8x[ch].state.hum = 0.0;
DTH8x[ch].state.tem = 0.0;


err = DTH8x_connectionReset(ch);

return err;
}

int DTH8x_GetConfig(unsigned char ch, DTH8x_config_t* config)
{
int err = 0;

if((ch >= DTH8x_CH_MAX) || (config == 0))
return err = -1;

if(DTH8x[ch].isUsed)
*config = DTH8x[ch].config;
else
return err = -2;


return err;
}


int DTH8x_GetData(unsigned char ch, DTH8x_Data_t* value)
{
int err = 0;

if((ch >= DTH8x_CH_MAX) || (value == 0))
return err = -1;

if(DTH8x[ch].isUsed)
*value = DTH8x[ch].state;
else
return err = -2;


return err;
}



 

 

 

/**************************************************.h文件**************************************************/

#ifndef __BSP_DTH8x_H

#define __BSP_DTH8x_H


#include "stm32f10x.h"


#define DTH8x_CH_MAX      16


enum __type
{
TEM=0,
HUM,
TEM_AND_HUM
};


//commond                        //adr commond r/w
#define WRITE_STATUS_REG   0x06  //000 0011    0
#define READ_STATUS_REG    0x07  //000 0011    1
#define TEM_MEASURE        0x03  //000 0001    1
#define HUM_MEASURE        0x05  //000 0010    1
#define RESET              0x1e  //000 1111    0

//config
typedef struct
{
unsigned char  sck_port;
unsigned char  sck_pin;
unsigned char  data_port;
unsigned char  data_pin;
}DTH8x_config_t;


//data
typedef struct
{
float tem;
float hum;
}DTH8x_Data_t;


typedef struct
{
unsigned char     isUsed;
DTH8x_config_t    config;
DTH8x_Data_t      state;
}DTH8x_t;


int DTH8x_setConfig(unsigned char ch, DTH8x_config_t config);
int DTH8x_GetConfig(unsigned char ch, DTH8x_config_t* config);
int DTH8x_Measure(unsigned char ch, enum __type type, unsigned char ischeckCrc);
int DTH8x_GetData(unsigned char ch, DTH8x_Data_t* value);


#endif

/**************************************************.c文件**************************************************/

#include "bsp_DTH8x.h"
#include <stdio.h>


DTH8x_t  DTH8x[DTH8x_CH_MAX] = {0};


//SCK
#define SCK_OUTPUT_H(port,pin)          GPIO_SetBits(port, pin)
#define SCK_OUTPUT_L(port,pin)          GPIO_ResetBits(port, pin)
//DATA
#define DATA_OUTPUT_H(port,pin)         GPIO_SetBits(port, pin)
#define DATA_OUTPUT_L(port,pin)         GPIO_ResetBits(port, pin)
#define DATA_INPUT_READ(port,pin)       GPIO_ReadInputDataBit(port, pin)


//ACK
enum __ack
{
NACK=0,
ACK
};


//tem cal
enum __tem_d1_cal
{
TEM_5V=0,
TEM_4V,
TEM_3_5V,
TEM_3V,
TEM_2_5V,
TEM_D1_ALL
};
typedef struct
{
float d1_C;
float d1_F;
}temD1_t;
temD1_t const temCal_d1[TEM_D1_ALL] = {
{-40.1, -40.2},
{-39.8, -39.6},
{-39.7, -39.5},
{-39.6, -39.3},
{-39.4, -38.9}
};


enum __tem_d2_cal
{
TEM_14BIT=0,
TEM_12BIT,
TEM_D2_ALL
};
typedef struct
{
float d2_C;
float d2_F;
}temD2_t;
temD2_t const temCal_d2[TEM_D2_ALL] = {
{0.01, 0.018}, 
{0.04, 0.072}
};


//hum cal
enum __hum_cal
{
HUM_12BIT=0,
HUM_8BIT,
HUM_ALL
};
typedef struct
{
float c1;
float c2;
float c3;
}humCal_t;
humCal_t const humCal[HUM_ALL] = {
{-2.0468, 0.0367, -0.0000015955}, 
{-2.0468, 0.5872, -0.00040845}
};


typedef struct
{
float t1;
float t2;
}humCmpe_t;
humCmpe_t const humCmp[HUM_ALL] = {
{0.01, 0.00008}, 
{0.01, 0.00128}
};


//cal
#define HUM_RH_LINEAR(c1,c2,c3,H)                ( c1 + (c2*H) + (c3*H*H) )               //相对湿度
#define TEM_TC(d1,d2,T)                          ( d1 + (d2*T) )                          //实际温度
#define HUM_RH_TRUE(t1,t2,H,RH_LINEAR,TC)        ( ( (TC-25)*(t1+(t2*H)) ) + RH_LINEAR )  //实际湿度


//void delay_nus(unsigned long n)
//{
// unsigned long j = 0;
//
// while(n--)
// {
// j = 12;
// while(j--);
// }
//}


static GPIO_TypeDef* getPortIdx(INT8U port)
{
INT8U PortIdx = port;
GPIO_TypeDef* GPIOx = NULL;

switch(PortIdx)
{
case 0: GPIOx = GPIOA; break;
case 1: GPIOx = GPIOB; break;
case 2: GPIOx = GPIOC; break;
case 3: GPIOx = GPIOD; break;
case 4: GPIOx = GPIOE; break;
case 5: GPIOx = GPIOF; break;
case 6: GPIOx = GPIOG; break;
default:break;
}

return GPIOx;
}


static unsigned short getPinIdx(INT8U pin)
{
return (unsigned short)(1<<pin);
}


int DTH8x_DATA_GpioModeSet(unsigned char ch, GPIOMode_TypeDef gpioMode)
{
int err = 0;
GPIO_InitTypeDef GPIO_InitStructure;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
err = -2;

//端口速度
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
//端口模式,此为输出推挽模式
GPIO_InitStructure.GPIO_Mode = gpioMode;
//DATA_PIN引脚设置
GPIO_InitStructure.GPIO_Pin = getPinIdx(DTH8x[ch].config.data_pin);
//DATA_PORT初始化端口
GPIO_Init(getPortIdx(DTH8x[ch].config.data_port), &GPIO_InitStructure);

return err;
}


int DTH8x_transferStart(unsigned char ch)
{
int err = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
return err = -1;

//init state
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
DATA_OUTPUT_L (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}
return err;
}


int DTH8x_connectionReset(unsigned char ch)
{
int err = 0;
unsigned char i = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
return err = -1;


//init state
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
for(i = 0; i < 9; i++)
{
__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
}

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}
err = DTH8x_transferStart(ch);

return err;
}


int DTH8x_writeByte(unsigned char ch, unsigned char value)
{
int err = 0;
int ack = 0;
unsigned char i = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if(!DTH8x[ch].isUsed)
return err = -1;

//write
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

for(i = 0x80; i > 0; i/=2)
{
if(i&value)
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
else
DATA_OUTPUT_L (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
}

//release DATA-line
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

//data-line gpio set input
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_IPU);

//clk #9 for ack
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
//check ack
ack = DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

//data-line gpio set output
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_Out_PP);

//release DATA-line
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}

if(ack)
return err = -3;

return err;
}


unsigned char DTH8x_readByte(unsigned char ch, unsigned char ack, int* errCode)
{
unsigned char value = 0;
unsigned char i = 0;

if((ch >= DTH8x_CH_MAX) || (errCode == 0))
{
*errCode = -1;
return value;
}

if(!DTH8x[ch].isUsed)
{
*errCode = -2;
return value;
}

//read
{
#ifdef RTOS_UCOS
OS_CPU_SR_DEF();
OS_ENTER_CRITICAL();//进入临界区
#endif

DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

//data-line gpio set input
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_IPU);

for(i = 0x80; i > 0; i/=2)
{
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

if(DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
value = value | i;


__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));
}

 //data-line gpio set output
 DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_Out_PP);

if(ack)
DATA_OUTPUT_L (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));
else
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

__nop();__nop();__nop();
SCK_OUTPUT_H (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

__nop();__nop();__nop();
SCK_OUTPUT_L (getPortIdx(DTH8x[ch].config.sck_port), getPinIdx(DTH8x[ch].config.sck_pin));

__nop();__nop();__nop();
DATA_OUTPUT_H (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin));

#ifdef RTOS_UCOS
OS_EXIT_CRITICAL();//退出临界区
#endif
}

*errCode = 0;

return value;
}


//-----------------------------------------------
// crc caculate
//-----------------------------------------------
char DTH8x_crc8(char byte,char crc8)
{
 char i;
 char temp;

 crc8^=byte;
 for(i=0;i<8;i++)
 {
  temp=crc8;
  crc8<<=1;
  if((temp&0x80)!=0)
   crc8^=0x31;
 }
 
 return crc8;
}
//-----------------------------------------------
// swap crc byte
//-----------------------------------------------
char DTH8x_swapcrc(char byte)
{
 unsigned char i;
 char temp=0;
 
 for (i=0x80;i>0;i/=2)
 {
  if((byte&i)!=0)
   temp|=0x80;
  if(i==0x01)
   break;
  temp>>=1;
  temp&=0x7f;
 }
 
 return temp;
}


int DTH8x_CRC8_check(unsigned char commond,unsigned char adValueH,unsigned char adValueL,unsigned char checksum)
{
int isOk = 0;
unsigned char crcvalue = 0;


crcvalue = DTH8x_crc8(commond,crcvalue); //first byte ,commond
crcvalue = DTH8x_crc8(adValueH,crcvalue);//second byte,adValueH
crcvalue = DTH8x_crc8(adValueL,crcvalue);//thrid byte,adValueL
crcvalue = DTH8x_swapcrc(crcvalue);      //swap high and low bit

if(crcvalue==checksum)                   //checksum == crcvalue
isOk=1;

return isOk;
}


static int DTH8x_getAd(unsigned char ch, enum __type type, unsigned char isCheckCrc, unsigned short* value)
{
int err = 0;
unsigned char commond = 0;
unsigned char adValueH = 0;
unsigned char adValueL = 0;
unsigned short adValue = 0;
unsigned char checkSum = 0;
unsigned long int i = 0;

if((ch >= DTH8x_CH_MAX) || (value == 0))
err = -1;

if(!DTH8x[ch].isUsed)
err = -2;

//开始读取
{
//连接测量
err = DTH8x_transferStart(ch);
if(!err)
{
switch(type)
{
case TEM: commond = TEM_MEASURE; break;
case HUM: commond = HUM_MEASURE; break;
default: err = -1;               break;
}
}

if(!err)
{
//send commond
err = DTH8x_writeByte(ch,commond);

//data-line gpio set input
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_IPU);


//等待ACK,超时500ms
#ifdef RTOS_UCOS
for(i = 0; i < 100; i++)
{
if(!DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
break;

OSTimeDly(OSmsToTick(5));
}
#else
for(i = 0; i < SystemCoreClock/72; i++) //时钟为72M
{
if(!DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
break;
}
#endif


if(DATA_INPUT_READ (getPortIdx(DTH8x[ch].config.data_port), getPinIdx(DTH8x[ch].config.data_pin)))
err = -4;
}
//data-line gpio set output
DTH8x_DATA_GpioModeSet(ch,GPIO_Mode_Out_PP);

if(!err)
adValueH = DTH8x_readByte(ch,ACK,&err);//MSB


if(!err)
{
adValueL = DTH8x_readByte(ch,ACK,&err);
adValue = (unsigned short)(adValueH<<8) + adValueL;
}

if(!err)
checkSum = DTH8x_readByte(ch,NACK,&err);//check sum


// printf("***%s***: adValueH = 0x%02x, adValueL = 0x%02x, checkSum = 0x%02x, adValue = 0x%02x\r\n", \
//        (type==TEM?"TEM":"HUM"), adValueH, adValueL, checkSum, adValue);

if((!err) && (isCheckCrc))
{
if(!DTH8x_CRC8_check(commond,adValueH,adValueL,checkSum))
err = -5;
}

if(!err)
*value = adValue;
}

return err;
}


int DTH8x_Measure(unsigned char ch, enum __type type, unsigned char ischeckCrc)
{
int err = 0;
unsigned short temValue = 0;
unsigned short humValue = 0;

if(ch >= DTH8x_CH_MAX)
return err = -1;


if(!DTH8x[ch].isUsed)
return err = -2;

//计算真实值
switch(type)
{
case TEM:
{
err = DTH8x_getAd(ch, TEM, ischeckCrc, &temValue);
if(err == 0)
{
float d1 = temCal_d1[TEM_3_5V].d1_C;
float d2 = temCal_d2[TEM_14BIT].d2_C;
DTH8x[ch].state.tem = TEM_TC(d1,d2,temValue); 
}
}
break;
case HUM:
{
err = DTH8x_getAd(ch, HUM, ischeckCrc, &humValue);
if(err == 0)
{
float c1 = humCal[HUM_12BIT].c1;
float c2 = humCal[HUM_12BIT].c2;
float c3 = humCal[HUM_12BIT].c3;
float RH_linear = HUM_RH_LINEAR(c1,c2,c3,humValue);
float t1 = humCmp[HUM_12BIT].t1;
float t2 = humCmp[HUM_12BIT].t2;
DTH8x[ch].state.hum = HUM_RH_TRUE(t1,t2,humValue,RH_linear,DTH8x[ch].state.tem);
}
}
break;
case TEM_AND_HUM:
{
err = DTH8x_getAd(ch, TEM, ischeckCrc, &temValue);
if(err == 0)
{
float d1 = temCal_d1[TEM_3_5V].d1_C;
float d2 = temCal_d2[TEM_14BIT].d2_C;
DTH8x[ch].state.tem = TEM_TC(d1,d2,temValue); 
}

if(!err)
err = DTH8x_getAd(ch, HUM, ischeckCrc, &humValue);

if(err == 0)
{
float c1 = humCal[HUM_12BIT].c1;
float c2 = humCal[HUM_12BIT].c2;
float c3 = humCal[HUM_12BIT].c3;
float RH_linear = HUM_RH_LINEAR(c1,c2,c3,humValue);
float t1 = humCmp[HUM_12BIT].t1;
float t2 = humCmp[HUM_12BIT].t2;
DTH8x[ch].state.hum = HUM_RH_TRUE(t1,t2,humValue,RH_linear,DTH8x[ch].state.tem);
}
}
break;
default: err = -1;
break;
}

//异常复位
if(err)
{
printf("DTH8x_Measure, ch = %d, err = %d\r\n", ch, err);
DTH8x_connectionReset(ch);
}
else
{
//printf("ch = %d, tem = %.2fC, hum=%.2f%%\r\n", ch,DTH8x[ch].state.tem,DTH8x[ch].state.hum);
}

return err;
}


int DTH8x_setConfig(unsigned char ch, DTH8x_config_t config)
{
int err = 0;
GPIO_InitTypeDef GPIO_InitStructure;

if(ch >= DTH8x_CH_MAX)
return err = -1;

if((getPortIdx(config.data_port) == 0) || (getPortIdx(config.sck_port) == 0) 
   || (getPinIdx(config.data_pin) > GPIO_Pin_All) || (getPinIdx(config.sck_pin) > GPIO_Pin_All))
return err = -1;

if((getPortIdx(config.data_port) == GPIOA)||(getPortIdx(config.sck_port) == GPIOA))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
else if((getPortIdx(config.data_port) == GPIOB)||(getPortIdx(config.sck_port) == GPIOB))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
else if((getPortIdx(config.data_port) == GPIOC)||(getPortIdx(config.sck_port) == GPIOC))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
else if((getPortIdx(config.data_port) == GPIOD)||(getPortIdx(config.sck_port) == GPIOD))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
else if((getPortIdx(config.data_port) == GPIOE)||(getPortIdx(config.sck_port) == GPIOE))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
else if((getPortIdx(config.data_port) == GPIOF)||(getPortIdx(config.sck_port) == GPIOF))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
else if((getPortIdx(config.data_port) == GPIOG)||(getPortIdx(config.sck_port) == GPIOG))
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
else
return err = -1;


//端口速度
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
//端口模式,此为输出推挽模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//SCK_PIN引脚设置
GPIO_InitStructure.GPIO_Pin = getPinIdx(config.sck_pin);
//SCK_PORT初始化端口
GPIO_Init(getPortIdx(config.sck_port), &GPIO_InitStructure);
//DATA_PIN引脚设置
GPIO_InitStructure.GPIO_Pin = getPinIdx(config.data_pin);
//DATA_PORT初始化端口
GPIO_Init(getPortIdx(config.data_port), &GPIO_InitStructure);

//初始化参数
DTH8x[ch].isUsed = 1;
DTH8x[ch].config = config;
DTH8x[ch].state.hum = 0.0;
DTH8x[ch].state.tem = 0.0;


err = DTH8x_connectionReset(ch);

return err;
}

int DTH8x_GetConfig(unsigned char ch, DTH8x_config_t* config)
{
int err = 0;

if((ch >= DTH8x_CH_MAX) || (config == 0))
return err = -1;

if(DTH8x[ch].isUsed)
*config = DTH8x[ch].config;
else
return err = -2;


return err;
}


int DTH8x_GetData(unsigned char ch, DTH8x_Data_t* value)
{
int err = 0;

if((ch >= DTH8x_CH_MAX) || (value == 0))
return err = -1;

if(DTH8x[ch].isUsed)
*value = DTH8x[ch].state;
else
return err = -2;


return err;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值