[文章]【HarmonyOS_Hi3861学习笔记】【连载】--oled上显示温湿度信息

阅读量0
0
0
写在前面的话:这个demo需要结合前面的oled部分。另外在调试aht20的驱动的时候遇到有问题,卡了差不多两三天吧。今天晚上才解决掉。明天上午单独发个贴说明怎定位问题并解决问题的。
AHT20和OLED一样都是I2C驱动的。有了前面oled的基础了,移植这个的驱动就简单很多了。
查看原理图可以看到,AHT20和OLED共用相同的I2C,都是GPIO13_I2C0_SDA、GPIO4_I2C0_SCL.只是地址有区分而已。
[attach]992095[/attach]

查看AHT20 的数据手册,得到其地址为0x38,读命令为0x71,写命令为0x70;
[attach]992096[/attach]
剩下的就是根据手册中的读取流程读取数据就行了。
读取流程\n
读取流程


如下是demo程序

  1. static hi_u32 aht20_i2c_write(hi_u8 *sendbuf, hi_u32 send_len)
  2. {
  3.     hi_u32 status;
  4.     hi_i2c_data aht20_i2c_data = { 0 };

  5.     aht20_i2c_data.send_buf = sendbuf;
  6.     aht20_i2c_data.send_len = send_len;
  7.     status = hi_i2c_write(HI_I2C_IDX_0, AHT20_SLAVE_WRITE_ADDR, &aht20_i2c_data);
  8.     if (status != HI_ERR_SUCCESS) {
  9.         printf("===== Error: AHT20 I2C write status = 0x%x! =====rn", status);
  10.         return status;
  11.     }

  12.     return HI_ERR_SUCCESS;
  13. }

  14. static hi_u32 aht20_i2c_read(hi_u8 *recvbuf, hi_u32 read_len)
  15. {
  16.     hi_u32 status;
  17.     hi_i2c_data aht20_i2c_data = {0};

  18.     aht20_i2c_data.receive_buf = recvbuf;
  19.     aht20_i2c_data.receive_len = read_len;
  20.     status = hi_i2c_read(HI_I2C_IDX_0, AHT20_SLAVE_READ_ADDR, &aht20_i2c_data);
  21.     if (status != HI_ERR_SUCCESS) {
  22.         printf("===== Error: AHT20 I2C read status = 0x%x! =====rn", status);
  23.         return status;
  24.     }

  25.     return HI_ERR_SUCCESS;
  26. }

  27. /**
  28.   * [url=home.php?mod=space&uid=2666770]@Brief[/url]  读AHT20 设备状态字
  29.   * [url=home.php?mod=space&uid=3142012]@param[/url]  void
  30.   * @retval hi_u8 设备状态字
  31.   */
  32. static hi_u8 AHT20_ReadStatusCmd(void)
  33. {
  34.     hi_u8 tmp = 0;
  35.         aht20_i2c_read(&tmp, 1);
  36.         return tmp;
  37. }

  38. /**
  39.   * @brief  读AHT20 设备状态字 中的Bit3: 校准使能位
  40.   * @param  void
  41.   * @retval hi_u8 校准使能位:1 - 已校准; 0 - 未校准
  42.   */
  43. static hi_u8 AHT20_ReadCalEnableCmd(void)
  44. {
  45.         hi_u8 tmp;
  46.         tmp = AHT20_ReadStatusCmd();
  47.         return (tmp>>3)&0x01;
  48. }

  49. /**
  50.   * @brief  读AHT20 设备状态字 中的Bit7: 忙标志
  51.   * @param  void
  52.   * @retval hi_u8 忙标志:1 - 设备忙; 0 - 设备空闲
  53.   */
  54. static hi_u8 AHT20_ReadBusyCmd(void)
  55. {
  56.         hi_u8 tmp;
  57.         tmp = AHT20_ReadStatusCmd();
  58.         return (tmp>>7)&0x01;
  59. }

  60. //发送获取状态字命令
  61. static hi_u32 AHT20_StatusCmd(void)
  62. {
  63.     hi_u8 cmd[1] = {AHT20_STATUS_REG};
  64.     return aht20_i2c_write(cmd, 1);

  65. }
  66. /**
  67.   * @brief  AHT20 芯片初始化命令
  68.   * @param  void
  69.   * @retval void
  70.   */
  71. static hi_u32 AHT20_IcInitCmd(void)
  72. {
  73.         hi_u8 cmd[3] = {AHT20_INIT_REG, AHT20_INIT_REG_ARG0, AHT20_INIT_REG_ARG1};
  74.         return aht20_i2c_write(cmd, 3);
  75. }

  76. /**
  77.   * @brief  AHT20 触发测量命令
  78.   * @param  void
  79.   * @retval void
  80.   */
  81. static hi_u32 AHT20_TrigMeasureCmd(void)
  82. {
  83.         hi_u8 cmd[3] = {AHT20_TrigMeasure_REG, AHT20_TrigMeasure_REG_ARG0, AHT20_TrigMeasure_REG_ARG1};
  84.         return aht20_i2c_write(cmd, 3);
  85. }

  86. /**
  87.   * @brief  AHT20 软复位命令
  88.   * @param  void
  89.   * @retval void
  90.   */
  91. static hi_u32 AHT20_SoftResetCmd(void)
  92. {
  93.         hi_u8 cmd[1] = {AHT20_SoftReset};
  94.         return aht20_i2c_write(cmd, 3);
  95. }

  96. /**
  97.   * @brief  AHT20 设备初始化
  98.   * @param  void
  99.   * @retval uint8_t:0 - 初始化AHT20设备成功; 1 - 初始化AHT20失败,可能设备不存在或器件已损坏
  100.   */
  101. static hi_u8 AHT20_Init(void)
  102. {
  103.         hi_u8 rcnt = 2+1;//软复位命令 重试次数,2次
  104.         hi_u8 icnt = 2+1;//初始化命令 重试次数,2次
  105.         hi_u32 retVal = 0;  //记录返回状态

  106.     usleep(40000);
  107.         while(--rcnt)
  108.         {
  109.                 icnt = 2+1;
  110.                 retVal = AHT20_StatusCmd();
  111.         if(retVal != HI_ERR_SUCCESS)
  112.             return retVal;

  113.                 // 读取温湿度之前,首先检查[校准使能位]是否为1
  114.                 while((!AHT20_ReadCalEnableCmd()) && (--icnt))// 2次重试机会
  115.                 {
  116.                         usleep(20000);
  117.                         // 如果不为1,要发送初始化命令
  118.                         AHT20_IcInitCmd();
  119.                         usleep(40000);
  120.                 }
  121.                
  122.                 if(icnt)//[校准使能位]为1,校准正常
  123.                 {
  124.                         break;//退出rcnt循环
  125.                 }
  126.                 else//[校准使能位]为0,校准错误
  127.                 {
  128.                         AHT20_SoftResetCmd();//软复位AHT20器件,重试
  129.                         usleep(40000);//这个时间不确定,手册没讲
  130.                 }
  131.         }
  132.         
  133.         if(rcnt)
  134.         {
  135.                 usleep(10000);//这个时间不确定,手册没讲
  136.                 return 0;// AHT20设备初始化正常
  137.         }
  138.         else
  139.         {
  140.                 return 1;// AHT20设备初始化失败
  141.         }
  142. }

  143. /**
  144.   * @brief  AHT20 设备读取 相对湿度和温度(原始数据20Bit)
  145.   * @param  hi_u32 *HT:存储20Bit原始数据的uint32数组
  146.   * @retval uint8_t:0-读取数据正常; 1-读取设备失败,设备一直处于忙状态,不能获取数据
  147.   */
  148. static hi_u8 AHT20_ReadHT(hi_u32 *HT)
  149. {
  150.         hi_u8 cnt=3+1;//忙标志 重试次数,3次
  151.         hi_u8 tmp[6];
  152.         hi_u32 RetuData = 0;
  153.         
  154.         // 发送触发测量命令
  155.         AHT20_TrigMeasureCmd();
  156.         
  157.         do{
  158.                 usleep(76000);//等待75ms待测量完成,忙标志Bit7为0
  159.         }while(AHT20_ReadBusyCmd() && (--cnt));//重试3次
  160.         
  161.         if(cnt)//设备闲,可以读温湿度数据
  162.         {
  163.                 usleep(5000);
  164.                 // 读温湿度数据
  165.                 aht20_i2c_read(tmp, 6);
  166.                 // 计算相对湿度RH。原始值,未计算为标准单位%。
  167.                 RetuData = 0;
  168.                 RetuData = (RetuData|tmp[1]) << 8;
  169.                 RetuData = (RetuData|tmp[2]) << 8;
  170.                 RetuData = (RetuData|tmp[3]);
  171.                 RetuData = RetuData >> 4;
  172.                 HT[0] = RetuData;
  173.                
  174.                 // 计算温度T。原始值,未计算为标准单位°C。
  175.                 RetuData = 0;
  176.                 RetuData = (RetuData|tmp[3]) << 8;
  177.                 RetuData = (RetuData|tmp[4]) << 8;
  178.                 RetuData = (RetuData|tmp[5]);
  179.                 RetuData = RetuData&0x0fffff;
  180.                 HT[1] = RetuData;
  181.                
  182.                 return 0;
  183.         }
  184.         else//设备忙,返回读取失败
  185.         {
  186.                 return 1;
  187.         }
  188. }

  189. /**
  190.   * @brief  AHT20 温湿度信号转换(由20Bit原始数据,转换为标准单位RH=%,T=°C)
  191.   * @param  struct m_AHT20* aht:存储AHT20传感器信息的结构体
  192.   * @retval uint8_t:0-计算数据正常; 1-计算数据失败,计算值超出元件手册规格范围
  193.   */
  194. static hi_u8 StandardUnitCon(struct m_AHT20* aht)
  195. {
  196.         aht->RH = (double)aht->HT[0] *100 / 1048576;//2^20=1048576 //原式:(double)aht->HT[0] / 1048576 *100,为了浮点精度改为现在的
  197.         aht->Temp = (double)aht->HT[1] *200 / 1048576 -50;
  198.         
  199.         //限幅,RH=0~100%; Temp=-40~85°C
  200.         if((aht->RH >=0)&&(aht->RH <=100) && (aht->Temp >=-40)&&(aht->Temp <=85))
  201.         {
  202.                 aht->flag = 0;
  203.                 return 0;//测量数据正常
  204.         }
  205.         else
  206.         {
  207.                 aht->flag = 1;
  208.                 return 1;//测量数据超出范围,错误
  209.         }
  210. }

  211. #define AHT20_TASK_STACK_SIZE 1024
  212. #define AHT20_TASK_PRIO 26
  213. struct m_AHT20 AHT20_Reseult = {0};

  214. static void *AHT20_Task(const char *arg)
  215. {
  216.     hi_u8 result = 0;
  217.    
  218.     hi_u32 ht_raw[2] = {0};
  219.     (void)arg;
  220.     usleep(100000);
  221.     result = AHT20_Init();
  222.     if(result == 0)
  223.         printf("AHT20 Init Successrn");
  224.     else
  225.         printf("AHT20 Init Failedrn");
  226.    
  227.     while(1)
  228.     {
  229.         result = AHT20_ReadHT(ht_raw);
  230.         if(result)
  231.             printf("read HT data Failedrn");
  232.         else
  233.         {
  234.             AHT20_Reseult.HT[0] = ht_raw[0];
  235.             AHT20_Reseult.HT[1] = ht_raw[1];
  236.             result = StandardUnitCon(&AHT20_Reseult);
  237.             if(result)
  238.                 printf("cal HT data Failedrn");
  239.             else
  240.             {
  241.                 printf("HT:%.2f temp:%.2frn", AHT20_Reseult.RH, AHT20_Reseult.Temp);
  242.                 OLED_ShowFloat(56,32,AHT20_Reseult.RH,2,16);
  243.                 OLED_ShowFloat(56,48,AHT20_Reseult.Temp,2,16);
  244.                 OLED_Refresh();
  245.             }
  246.             
  247.         }

  248.         usleep(1000000);
  249.     }
  250.     return NULL;
  251. }

  252. static void AHT20ExampleEntry(void)
  253. {
  254.     osThreadAttr_t attr;

  255.     attr.name = "AHT20Task";
  256.     attr.attr_bits = 0U;
  257.     attr.cb_mem = NULL;
  258.     attr.cb_size = 0U;
  259.     attr.stack_mem = NULL;
  260.     attr.stack_size = AHT20_TASK_STACK_SIZE;
  261.     attr.priority = AHT20_TASK_PRIO;

  262.     if (osThreadNew((osThreadFunc_t)AHT20_Task, NULL, &attr) == NULL) {
  263.         printf("[AHT20 Example] Falied to create AHT20Task!n");
  264.     }
  265. }

  266. SYS_RUN(AHT20ExampleEntry);
复制代码

头文件内容
  1. #define ATH20_SLAVE_ADDRESS                0x38                /* I2C从机地址 */
  2. #define AHT20_SLAVE_READ_ADDR       (ATH20_SLAVE_ADDRESS<<1 | 0x01) //读命令
  3. #define AHT20_SLAVE_WRITE_ADDR      (ATH20_SLAVE_ADDRESS<<1 | 0x00) //写命令

  4. //****************************************
  5. // 定义 AHT20 内部地址
  6. //****************************************
  7. #define        AHT20_STATUS_REG                0x71        //状态字 寄存器地址

  8. #define        AHT20_INIT_REG                        0xBE        //初始化 寄存器地址
  9. #define        AHT20_INIT_REG_ARG0                0x08        //初始化 寄存器参数1
  10. #define        AHT20_INIT_REG_ARG1                0x00        //初始化 寄存器参数2

  11. #define        AHT20_SoftReset                        0xBA        //软复位 单指令

  12. #define        AHT20_TrigMeasure_REG        0xAC        //触发测量 寄存器地址
  13. #define        AHT20_TrigMeasure_REG_ARG0        0x33        //触发测量 寄存器参数1
  14. #define        AHT20_TrigMeasure_REG_ARG1        0x00        //触发测量 寄存器参数2

  15. // 存储AHT20传感器信息的结构体
  16. struct m_AHT20
  17. {
  18.         hi_u8 alive;        // 0-器件不存在; 1-器件存在
  19.         hi_u8 flag;        // 读取/计算错误标志位。0-读取/计算数据正常; 1-读取/计算设备失败
  20.         hi_u32 HT[2];        // 湿度、温度 原始传感器的值,20Bit
  21.         
  22.         float RH;                // 湿度,转换单位后的实际值,标准单位%
  23.         float Temp;                // 温度,转换单位后的实际值,标准单位°C
  24. };
复制代码
编译成功后,串口间隔1s打印温湿度信息以及oled上显示当前温湿度信息。

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友