[活动专区] 【AT-START-F423测评】10.使用硬件I2C读取DHTC12温湿度数据

[复制链接]
1975|0
 楼主| yuyy1989 发表于 2023-11-4 17:23 | 显示全部楼层 |阅读模式
#申请原创# @21小跑堂  

之前用模拟I2C的方式读取了BMP280的数据,这次换用硬件I2C实现对DHTC12温湿度的读取
在AT32 Work Bench中开启I2C1
QQ截图20231104170022.png
默认使用PC0和PC1来通讯,参数设置参考DHTC12的手册

QQ截图20231104170137.png
AT32已经提供了一个封装好的I2C操作库

QQ截图20231104171242.png
不过还是想自己实现一下I2C通讯代码
  1. #define AT32I2C_TIMEOUT 0xFFFF

  2. void yuyy_hard_iic_reset_ctrl2_register(i2c_type *iicx)
  3. {
  4.   iicx->ctrl2_bit.saddr     = 0;
  5.   iicx->ctrl2_bit.readh10   = 0;
  6.   iicx->ctrl2_bit.cnt       = 0;
  7.   iicx->ctrl2_bit.rlden     = 0;
  8.   iicx->ctrl2_bit.dir       = 0;
  9. }

  10. uint8_t yuyy_hard_iic_wait_flag(i2c_type *iicx,uint32_t flag,flag_status status)
  11. {
  12.     uint16_t timeout = AT32I2C_TIMEOUT;
  13.     while(i2c_flag_get(iicx, flag) != status)
  14.     {
  15.         timeout -= 1;
  16.         if(timeout == 0)
  17.             return 1;
  18.     }
  19.     return 0;
  20. }

  21. uint8_t yuyy_hard_iic_master_sendstop(i2c_type *iicx)
  22. {
  23.     i2c_stop_generate(iicx);
  24.     if(yuyy_hard_iic_wait_flag(iicx,I2C_STOPF_FLAG,SET))
  25.         return 1;
  26.     i2c_flag_clear(iicx, I2C_STOPF_FLAG);
  27.     return 0;
  28. }

  29. 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)
  30. {
  31.     uint16_t timeout = AT32I2C_TIMEOUT;
  32.     if(yuyy_hard_iic_wait_flag(iicx,I2C_BUSYF_FLAG,RESET))
  33.         return 1;
  34.     i2c_transmit_set(iicx, devaddr<<1, datalen, stopmode, startmode);
  35.     return 0;
  36. }

  37. uint8_t yuyy_hard_iic_master_senddatas(i2c_type *iicx,uint8_t *datas,uint8_t datalen)
  38. {
  39.     uint8_t i=0;

  40.     while(i<datalen)
  41.     {
  42.         if(yuyy_hard_iic_wait_flag(iicx,I2C_TDIS_FLAG,SET))
  43.         {
  44.             if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
  45.             {
  46.                 i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
  47.                 return 3;
  48.             }
  49.             yuyy_hard_iic_master_sendstop(iicx);
  50.             return 2;
  51.         }
  52.         if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
  53.         {
  54.             i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
  55.             return 3;
  56.         }
  57.         i2c_data_send(iicx, datas[i]);
  58.         i += 1;
  59.     }
  60.     return 0;
  61. }

  62. uint8_t yuyy_hard_iic_master_readdatas(i2c_type *iicx,uint8_t *datas,uint8_t datalen)
  63. {
  64.     uint8_t i=0;
  65.    
  66.     while(i<datalen)
  67.     {
  68.         if(yuyy_hard_iic_wait_flag(iicx,I2C_RDBF_FLAG,SET))
  69.         {
  70.             if(i2c_flag_get(iicx, I2C_ACKFAIL_FLAG) != RESET)
  71.             {
  72.                 i2c_flag_clear(iicx, I2C_ACKFAIL_FLAG);
  73.                 return 3;
  74.             }
  75.             yuyy_hard_iic_master_sendstop(iicx);
  76.             return 2;
  77.         }
  78.         datas[i] = i2c_data_receive(iicx);
  79.         i += 1;
  80.     }
  81.     return 0;
  82. }

  83. 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)
  84. {
  85.     uint8_t err = 0,regdata[2];
  86.     err = yuyy_hard_iic_master_sendstart(iicx,devaddr,I2C_GEN_START_WRITE,I2C_SOFT_STOP_MODE,regaddrlen+datalen);
  87.     if(err == 0 && regaddrlen > 0)
  88.     {
  89.         regdata[0] = (regaddr >> 8)&0xFF;
  90.         regdata[1] = regaddr&0xFF;
  91.         if(regaddrlen == 1)
  92.             regdata[0] = regaddr&0xFF;
  93.         err = yuyy_hard_iic_master_senddatas(iicx,regdata,regaddrlen);
  94.     }
  95.     if(err == 0)
  96.         err = yuyy_hard_iic_master_senddatas(iicx,datas,datalen);
  97.     if(err == 0 && yuyy_hard_iic_wait_flag(iicx,I2C_TDC_FLAG,SET))
  98.             err = 4;
  99.     if(err == 0)
  100.         err = yuyy_hard_iic_master_sendstop(iicx);
  101.     if(err != 0)
  102.         yuyy_hard_iic_reset_ctrl2_register(iicx);
  103.     return err;
  104. }
  105. 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)
  106. {
  107.     uint8_t err = 0,regdata[2];
  108.     if(regaddrlen > 0)
  109.     {
  110.         regdata[0] = (regaddr >> 8)&0xFF;
  111.         regdata[1] = regaddr&0xFF;
  112.         if(regaddrlen == 1)
  113.             regdata[0] = regaddr&0xFF;
  114.         err = yuyy_hard_iic_master_sendstart(iicx,devaddr,I2C_GEN_START_WRITE,I2C_SOFT_STOP_MODE,regaddrlen);
  115.         if(err == 0)
  116.             err = yuyy_hard_iic_master_senddatas(iicx,regdata,regaddrlen);
  117.         if(err == 0 && yuyy_hard_iic_wait_flag(iicx,I2C_TDC_FLAG,SET))
  118.             err = 4;
  119.     }
  120.     if(err == 0)
  121.         i2c_transmit_set(iicx, devaddr<<1, datalen, I2C_SOFT_STOP_MODE, I2C_GEN_START_READ);
  122.     if(err == 0)
  123.         err = yuyy_hard_iic_master_readdatas(iicx,datas,datalen);
  124.     if(err == 0)
  125.         err = yuyy_hard_iic_master_sendstop(iicx);
  126.     if(err != 0)
  127.         yuyy_hard_iic_reset_ctrl2_register(iicx);
  128.     return err;
  129. }
DHTC12通讯代码
  1. #define DHTC12_I2C_ADDR 0x44

  2. static uint16_t HumA,HumB;

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

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

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

  15. //初始化,获取湿度运算系数
  16. void yuyy_dhtc12_init(YUYY_DHTC12_DEV_t *dhtc12_dev)
  17. {
  18.     uint8_t x;
  19.     if(!dhtc12_dev->delayms_func)
  20.         dhtc12_dev->delayms_func = yuyy_delay_ms;
  21.     //复位传感器
  22.     yuyy_dhtc12_writecmd(dhtc12_dev,0x30A2);
  23.     yuyy_dhtc12_readcmd(dhtc12_dev,0xD208,&x,1);
  24.     HumA = (x<<8)&0xFF00;
  25.     yuyy_dhtc12_readcmd(dhtc12_dev,0xD209,&x,1);
  26.     HumA |= x;
  27.    
  28.     yuyy_dhtc12_readcmd(dhtc12_dev,0xD20A,&x,1);
  29.     HumB = (x<<8)&0xFF00;
  30.     yuyy_dhtc12_readcmd(dhtc12_dev,0xD20B,&x,1);
  31.     HumB |= x;
  32.     //HumA=0x7168;  HumB=0x2D73;
  33.     //ReadDatSH[6]={0xF3, 0xA9, 0xC0, 0x41, 0xB4, 0x87}
  34.     //27.6 48.4%
  35. }

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

  37. uint8_t yuyy_dhtc12_checkcrc(uint8_t Data[], uint8_t nbrOfBytes)
  38. {
  39.     uint8_t crc = 0xff; //0
  40.     uint8_t byteCtr,Bit;
  41.     //calculates 8-Bit checksum with given polynomial
  42.     for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
  43.     {
  44.         crc ^= (Data[byteCtr]);
  45.         for (Bit = 8; Bit > 0; --Bit)
  46.         {
  47.             if (crc & 0x80)
  48.                 crc = (crc << 1) ^ POLYNOMIAL;
  49.             else
  50.                 crc = (crc << 1);
  51.         }
  52.     }
  53.     if (crc != Data[nbrOfBytes])
  54.     {
  55.         Data[nbrOfBytes] = crc;
  56.         return 0x01;
  57.     }
  58.     else
  59.         return 0;
  60. }

  61. //单次触发温湿度测量
  62. uint8_t yuyy_dhtc12_readHT(YUYY_DHTC12_DEV_t *dhtc12_dev,float *tem,float *hum)
  63. {
  64.     uint8_t i=0,errRe,ReadDatSH[6],CalCRC[3],errorflag=0;
  65.     int16_t TemBuf;
  66.     uint16_t CapBuf;
  67.     errRe = yuyy_dhtc12_writecmd(dhtc12_dev,0x2C10);
  68.     if(errRe)
  69.         errRe = yuyy_dhtc12_writecmd(dhtc12_dev,0x2C10);
  70.     if(errRe)
  71.     {
  72.         return 0x10|errRe; //发送命令失败
  73.     }
  74.    
  75.     dhtc12_dev->delayms_func(100);
  76.     errRe = yuyy_dhtc12_readdatas(dhtc12_dev,ReadDatSH,6);

  77.     if(errRe)
  78.     {
  79.         return 0x20|errRe; //接收数据失败
  80.     }
  81.     CalCRC[0] = ReadDatSH[0];
  82.     CalCRC[1] = ReadDatSH[1];
  83.     CalCRC[2] = ReadDatSH[2];
  84.     errorflag = yuyy_dhtc12_checkcrc(CalCRC,2);
  85.     if(errorflag==0)
  86.     {
  87.         TemBuf = (int16_t)(((ReadDatSH[0]<<8)&0xFF00)|ReadDatSH[1]);
  88.         *tem = 40+(float)TemBuf/256.0;
  89.     }
  90.     CalCRC[0] = ReadDatSH[3];
  91.     CalCRC[1] = ReadDatSH[4];
  92.     CalCRC[2] = ReadDatSH[5];
  93.     errorflag <<= 1;
  94.     errorflag |= yuyy_dhtc12_checkcrc(CalCRC,2);
  95.     if(errorflag==0)
  96.     {
  97.         CapBuf = (uint16_t)(((ReadDatSH[3]<<8)&0xFF00)|ReadDatSH[4]);
  98.         *hum = (float)(CapBuf-HumB)*60.0/(float)(HumA-HumB)+30;
  99.         //20℃为5个湿度点  即1℃为0.25个湿度点  0.1℃为0.025
  100.         *hum = *hum+ 0.25*(*tem-25);
  101.         if(*hum>100)
  102.             *hum = 99.9;
  103.         else if(*hum<0)
  104.             *hum = 0;
  105.     }
  106.     return errorflag;       
  107. }
初始化和读取温湿度并打印出来
  1. YUYY_DHTC12_DEV_t dhtc12_dev;
  2. void dhtc12_init()
  3. {
  4.     dhtc12_dev.iicx = I2C1;
  5.     dhtc12_dev.iic_readdatas_func = (yuyy_iic_master_readdatas_func_t)yuyy_hard_iic_master_readregdatas;
  6.     dhtc12_dev.iic_senddatas_func = (yuyy_iic_master_senddatas_func_t)yuyy_hard_iic_master_sendregdatas;
  7.     yuyy_dhtc12_init(&dhtc12_dev);
  8. }

  9. void dhtc12_readTH()
  10. {
  11.     float humi,temp;
  12.     uint8_t result = yuyy_dhtc12_readHT(&dhtc12_dev,&temp,&humi);
  13.     if(YUYY_DHT11_OK == result)
  14.     {
  15.         printf("DHTC12 读取温度:%.1f℃ 湿度:%.1f%%\r\n",temp,humi);
  16.     }
  17.     else
  18.     {
  19.         printf("DHTC12 读取温度错误:%d\r\n",result);
  20.     }
  21. }
运行效果
QQ截图20231104172154.png

您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部