打印
[活动专区]

【AT-START-F423测评】10.使用硬件I2C读取DHTC12温湿度数据

[复制链接]
1438|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创# @21小跑堂  

之前用模拟I2C的方式读取了BMP280的数据,这次换用硬件I2C实现对DHTC12温湿度的读取
在AT32 Work Bench中开启I2C1

默认使用PC0和PC1来通讯,参数设置参考DHTC12的手册


AT32已经提供了一个封装好的I2C操作库


不过还是想自己实现一下I2C通讯代码
#define AT32I2C_TIMEOUT 0xFFFF

void yuyy_hard_iic_reset_ctrl2_register(i2c_type *iicx)
{
  iicx->ctrl2_bit.saddr     = 0;
  iicx->ctrl2_bit.readh10   = 0;
  iicx->ctrl2_bit.cnt       = 0;
  iicx->ctrl2_bit.rlden     = 0;
  iicx->ctrl2_bit.dir       = 0;
}

uint8_t yuyy_hard_iic_wait_flag(i2c_type *iicx,uint32_t flag,flag_status status)
{
    uint16_t timeout = AT32I2C_TIMEOUT;
    while(i2c_flag_get(iicx, flag) != status)
    {
        timeout -= 1;
        if(timeout == 0)
            return 1;
    }
    return 0;
}

uint8_t yuyy_hard_iic_master_sendstop(i2c_type *iicx)
{
    i2c_stop_generate(iicx);
    if(yuyy_hard_iic_wait_flag(iicx,I2C_STOPF_FLAG,SET))
        return 1;
    i2c_flag_clear(iicx, I2C_STOPF_FLAG);
    return 0;
}

uint8_t yuyy_hard_iic_master_sendstart(i2c_type *iicx,uint8_t devaddr,i2c_start_mode_type startmode,i2c_reload_stop_mode_type stopmode,uint8_t datalen)
{
    uint16_t timeout = AT32I2C_TIMEOUT;
    if(yuyy_hard_iic_wait_flag(iicx,I2C_BUSYF_FLAG,RESET))
        return 1;
    i2c_transmit_set(iicx, devaddr<<1, datalen, stopmode, startmode);
    return 0;
}

uint8_t yuyy_hard_iic_master_senddatas(i2c_type *iicx,uint8_t *datas,uint8_t datalen)
{
    uint8_t i=0;

    while(i<datalen)
    {
        if(yuyy_hard_iic_wait_flag(iicx,I2C_TDIS_FLAG,SET))
        {
            if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
            {
                i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
                return 3;
            }
            yuyy_hard_iic_master_sendstop(iicx);
            return 2;
        }
        if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
        {
            i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
            return 3;
        }
        i2c_data_send(iicx, datas[i]);
        i += 1;
    }
    return 0;
}

uint8_t yuyy_hard_iic_master_readdatas(i2c_type *iicx,uint8_t *datas,uint8_t datalen)
{
    uint8_t i=0;
   
    while(i<datalen)
    {
        if(yuyy_hard_iic_wait_flag(iicx,I2C_RDBF_FLAG,SET))
        {
            if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
            {
                i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
                return 3;
            }
            yuyy_hard_iic_master_sendstop(iicx);
            return 2;
        }
        datas[i] = i2c_data_receive(iicx);
        i += 1;
    }
    return 0;
}

uint8_t yuyy_hard_iic_master_sendregdatas(i2c_type *iicx,uint8_t devaddr,uint16_t regaddr,uint8_t regaddrlen,uint8_t *datas,uint8_t datalen)
{
    uint8_t err = 0,regdata[2];
    err = yuyy_hard_iic_master_sendstart(iicx,devaddr,I2C_GEN_START_WRITE,I2C_SOFT_STOP_MODE,regaddrlen+datalen);
    if(err == 0 && regaddrlen > 0)
    {
        regdata[0] = (regaddr >> 8)&0xFF;
        regdata[1] = regaddr&0xFF;
        if(regaddrlen == 1)
            regdata[0] = regaddr&0xFF;
        err = yuyy_hard_iic_master_senddatas(iicx,regdata,regaddrlen);
    }
    if(err == 0)
        err = yuyy_hard_iic_master_senddatas(iicx,datas,datalen);
    if(err == 0 && yuyy_hard_iic_wait_flag(iicx,I2C_TDC_FLAG,SET))
            err = 4;
    if(err == 0)
        err = yuyy_hard_iic_master_sendstop(iicx);
    if(err != 0)
        yuyy_hard_iic_reset_ctrl2_register(iicx);
    return err;
}
uint8_t yuyy_hard_iic_master_readregdatas(i2c_type *iicx,uint8_t devaddr,uint16_t regaddr,uint8_t regaddrlen,uint8_t *datas,uint8_t datalen)
{
    uint8_t err = 0,regdata[2];
    if(regaddrlen > 0)
    {
        regdata[0] = (regaddr >> 8)&0xFF;
        regdata[1] = regaddr&0xFF;
        if(regaddrlen == 1)
            regdata[0] = regaddr&0xFF;
        err = yuyy_hard_iic_master_sendstart(iicx,devaddr,I2C_GEN_START_WRITE,I2C_SOFT_STOP_MODE,regaddrlen);
        if(err == 0)
            err = yuyy_hard_iic_master_senddatas(iicx,regdata,regaddrlen);
        if(err == 0 && yuyy_hard_iic_wait_flag(iicx,I2C_TDC_FLAG,SET))
            err = 4;
    }
    if(err == 0)
        i2c_transmit_set(iicx, devaddr<<1, datalen, I2C_SOFT_STOP_MODE, I2C_GEN_START_READ);
    if(err == 0)
        err = yuyy_hard_iic_master_readdatas(iicx,datas,datalen);
    if(err == 0)
        err = yuyy_hard_iic_master_sendstop(iicx);
    if(err != 0)
        yuyy_hard_iic_reset_ctrl2_register(iicx);
    return err;
}
DHTC12通讯代码
#define DHTC12_I2C_ADDR 0x44

static uint16_t HumA,HumB;

uint8_t yuyy_dhtc12_writecmd(YUYY_DHTC12_DEV_t *dhtc12_dev,uint16_t cmd)
{
        return dhtc12_dev->iic_senddatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,cmd,2,NULL,0);
}

uint8_t yuyy_dhtc12_readdatas(YUYY_DHTC12_DEV_t *dhtc12_dev,uint8_t *rdatas,uint8_t rlen)
{
        return dhtc12_dev->iic_readdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,0,0,rdatas,rlen);
}

uint8_t yuyy_dhtc12_readcmd(YUYY_DHTC12_DEV_t *dhtc12_dev,uint16_t cmd,uint8_t *rdatas,uint8_t rlen)
{
        return dhtc12_dev->iic_readdatas_func(dhtc12_dev->iicx,DHTC12_I2C_ADDR,cmd,2,rdatas,rlen);
}

//初始化,获取湿度运算系数
void yuyy_dhtc12_init(YUYY_DHTC12_DEV_t *dhtc12_dev)
{
    uint8_t x;
    if(!dhtc12_dev->delayms_func)
        dhtc12_dev->delayms_func = yuyy_delay_ms;
    //复位传感器
    yuyy_dhtc12_writecmd(dhtc12_dev,0x30A2);
    yuyy_dhtc12_readcmd(dhtc12_dev,0xD208,&x,1);
    HumA = (x<<8)&0xFF00;
    yuyy_dhtc12_readcmd(dhtc12_dev,0xD209,&x,1);
    HumA |= x;
   
    yuyy_dhtc12_readcmd(dhtc12_dev,0xD20A,&x,1);
    HumB = (x<<8)&0xFF00;
    yuyy_dhtc12_readcmd(dhtc12_dev,0xD20B,&x,1);
    HumB |= x;
    //HumA=0x7168;  HumB=0x2D73;
    //ReadDatSH[6]={0xF3, 0xA9, 0xC0, 0x41, 0xB4, 0x87}
    //27.6 48.4%
}

const uint16_t POLYNOMIAL = 0x131; //P(x)=x^8+x^5+x^4+1 = 100110001

uint8_t yuyy_dhtc12_checkcrc(uint8_t Data[], uint8_t nbrOfBytes)
{
    uint8_t crc = 0xff; //0
    uint8_t byteCtr,Bit;
    //calculates 8-Bit checksum with given polynomial
    for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
    {
        crc ^= (Data[byteCtr]);
        for (Bit = 8; Bit > 0; --Bit)
        {
            if (crc & 0x80)
                crc = (crc << 1) ^ POLYNOMIAL;
            else
                crc = (crc << 1);
        }
    }
    if (crc != Data[nbrOfBytes])
    {
        Data[nbrOfBytes] = crc;
        return 0x01;
    }
    else
        return 0;
}

//单次触发温湿度测量
uint8_t yuyy_dhtc12_readHT(YUYY_DHTC12_DEV_t *dhtc12_dev,float *tem,float *hum)
{
    uint8_t i=0,errRe,ReadDatSH[6],CalCRC[3],errorflag=0;
    int16_t TemBuf;
    uint16_t CapBuf;
    errRe = yuyy_dhtc12_writecmd(dhtc12_dev,0x2C10);
    if(errRe)
        errRe = yuyy_dhtc12_writecmd(dhtc12_dev,0x2C10);
    if(errRe)
    {
        return 0x10|errRe; //发送命令失败
    }
   
    dhtc12_dev->delayms_func(100);
    errRe = yuyy_dhtc12_readdatas(dhtc12_dev,ReadDatSH,6);

    if(errRe)
    {
        return 0x20|errRe; //接收数据失败
    }
    CalCRC[0] = ReadDatSH[0];
    CalCRC[1] = ReadDatSH[1];
    CalCRC[2] = ReadDatSH[2];
    errorflag = yuyy_dhtc12_checkcrc(CalCRC,2);
    if(errorflag==0)
    {
        TemBuf = (int16_t)(((ReadDatSH[0]<<8)&0xFF00)|ReadDatSH[1]);
        *tem = 40+(float)TemBuf/256.0;
    }
    CalCRC[0] = ReadDatSH[3];
    CalCRC[1] = ReadDatSH[4];
    CalCRC[2] = ReadDatSH[5];
    errorflag <<= 1;
    errorflag |= yuyy_dhtc12_checkcrc(CalCRC,2);
    if(errorflag==0)
    {
        CapBuf = (uint16_t)(((ReadDatSH[3]<<8)&0xFF00)|ReadDatSH[4]);
        *hum = (float)(CapBuf-HumB)*60.0/(float)(HumA-HumB)+30;
        //20℃为5个湿度点  即1℃为0.25个湿度点  0.1℃为0.025
        *hum = *hum+ 0.25*(*tem-25);
        if(*hum>100)
            *hum = 99.9;
        else if(*hum<0)
            *hum = 0;
    }
    return errorflag;       
}
初始化和读取温湿度并打印出来
YUYY_DHTC12_DEV_t dhtc12_dev;
void dhtc12_init()
{
    dhtc12_dev.iicx = I2C1;
    dhtc12_dev.iic_readdatas_func = (yuyy_iic_master_readdatas_func_t)yuyy_hard_iic_master_readregdatas;
    dhtc12_dev.iic_senddatas_func = (yuyy_iic_master_senddatas_func_t)yuyy_hard_iic_master_sendregdatas;
    yuyy_dhtc12_init(&dhtc12_dev);
}

void dhtc12_readTH()
{
    float humi,temp;
    uint8_t result = yuyy_dhtc12_readHT(&dhtc12_dev,&temp,&humi);
    if(YUYY_DHT11_OK == result)
    {
        printf("DHTC12 读取温度:%.1f℃ 湿度:%.1f%%\r\n",temp,humi);
    }
    else
    {
        printf("DHTC12 读取温度错误:%d\r\n",result);
    }
}
运行效果


使用特权

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

本版积分规则

149

主题

708

帖子

7

粉丝