#申请原创# @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);
}
}
运行效果
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
|