aht20.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: aht20.c
  4. 文件版本: 01.01
  5. 创建作者: Ewen
  6. 创建日期: 2025-11-10
  7. 功能说明: aht20驱动程序。
  8. 其它说明:
  9. 修改记录:
  10. /*------------------------------ 头文件 ---------------------------------------
  11. */
  12. #include <fcntl.h>
  13. #include <sys/ioctl.h>
  14. #include <linux/i2c.h>
  15. #include <linux/i2c-dev.h>
  16. #include <errno.h>
  17. #include "head.h"
  18. #ifdef TMP_CHIP_AHT20
  19. /*------------------------------ 宏定义 ---------------------------------------
  20. */
  21. #define I2C_DEV "/dev/i2c-5"
  22. // 以下定义见AHT20 datasheet
  23. // AHT20 设备地址
  24. #define AHT20_I2C_ADDR 0x38
  25. // AHT20 命令字
  26. #define AHT20_CMD_INIT 0xBE
  27. #define AHT20_CMD_MEAS 0xAC
  28. #define AHT20_CMD_RESET 0xBA
  29. /*------------------------------ 全局变量 -------------------------------------
  30. */
  31. struct aht20 aht20;
  32. int g_aht20_fd;
  33. /*------------------------------ 函数声明 -------------------------------------
  34. */
  35. // AHT20 初始化
  36. static int _aht20_init(int fd) {
  37. uint8_t init_cmd[3] = {AHT20_CMD_INIT, 0x08, 0x00};
  38. if (write(fd, init_cmd, sizeof(init_cmd)) != sizeof(init_cmd))
  39. {
  40. printf("Failed to send init command: %s\n", strerror(errno));
  41. return -1;
  42. }
  43. return 0;
  44. }
  45. // AHT20 软复位
  46. static int _aht20_soft_reset(int fd) {
  47. uint8_t reset_cmd = AHT20_CMD_RESET;
  48. if (write(fd, &reset_cmd, sizeof(reset_cmd)) != sizeof(reset_cmd))
  49. {
  50. printf("Failed to send reset command: %s\n", strerror(errno));
  51. return -1;
  52. }
  53. return 0;
  54. }
  55. // 读取温湿度数据
  56. static int _aht20_read_data(int fd, float* temperature, float* humidity)
  57. {
  58. uint8_t cmd[3] = {AHT20_CMD_MEAS, 0x33, 0x00};
  59. uint8_t data[6] = {0};
  60. uint32_t temp_raw = 0, humi_raw = 0;
  61. // 发送测量命令
  62. if (write(fd, cmd, sizeof(cmd)) != sizeof(cmd)) {
  63. printf("Failed to send measure command: %s\n", strerror(errno));
  64. return -1;
  65. }
  66. // 等待测量完成(最多100ms)
  67. int timeout = 0;
  68. while (timeout < 100) {
  69. msleep(1);
  70. if (read(fd, data, 1) == 1) {
  71. if (!(data[0] & 0x80)) { // 检查忙标志位
  72. break;
  73. }
  74. }
  75. timeout++;
  76. }
  77. if (timeout >= 100) {
  78. printf("AHT20 measurement timeout\r\n");
  79. return -1;
  80. }
  81. // 读取测量数据
  82. if (read(fd, data, sizeof(data)) != sizeof(data)) {
  83. printf("Failed to read measurement data: %s\r\n", strerror(errno));
  84. return -1;
  85. }
  86. // 检查数据状态位
  87. if ((data[0] & 0x68) != 0x08) {
  88. printf("AHT20 data not ready or invalid\r\n");
  89. return -1;
  90. }
  91. // 解析湿度数据(20位)
  92. humi_raw = ((uint32_t)data[1] << 12) |
  93. ((uint32_t)data[2] << 4) |
  94. ((uint32_t)data[3] >> 4);
  95. // 解析温度数据(20位)
  96. temp_raw = (((uint32_t)data[3] & 0x0F) << 16) |
  97. ((uint32_t)data[4] << 8) |
  98. data[5];
  99. // 转换为实际值
  100. *humidity = (float)humi_raw * 100.0 / (1 << 20);
  101. *temperature = (float)temp_raw * 200.0 / (1 << 20) - 50.0;
  102. return 0;
  103. }
  104. int aht20_init(void)
  105. {
  106. memset(&aht20, 0, sizeof(aht20));
  107. // 打开I2C设备
  108. g_aht20_fd = open(I2C_DEV, O_RDWR);
  109. if (g_aht20_fd < 0) {
  110. printf("Failed to open I2C device %s: %s\n", I2C_DEV, strerror(errno));
  111. return -1;
  112. }
  113. // 设置从设备地址
  114. if (ioctl(g_aht20_fd, I2C_SLAVE, AHT20_I2C_ADDR) < 0) {
  115. printf("Failed to set I2C slave address: %s\n", strerror(errno));
  116. close(g_aht20_fd);
  117. return -1;
  118. }
  119. _aht20_soft_reset(g_aht20_fd);
  120. msleep(100);
  121. if(_aht20_init(g_aht20_fd) == 0)
  122. {
  123. printf("aht20 init success!\r\n");
  124. }
  125. else
  126. {
  127. printf("aht20 init failed!\r\n");
  128. close(g_aht20_fd);
  129. g_aht20_fd = -1;
  130. return -1;
  131. }
  132. aht20.us0 = bsp_ustimer_get_origin();
  133. return 0;
  134. }
  135. int aht20_exit(void)
  136. {
  137. if(g_aht20_fd >= 0)
  138. {
  139. close(g_aht20_fd);
  140. g_aht20_fd = -1;
  141. }
  142. return 0;
  143. }
  144. void aht20_task(void)
  145. {
  146. if(bsp_ustimer_get_duration(aht20.us0) < USTIMER_SEC*5 || g_aht20_fd < 0)
  147. {
  148. return;
  149. }
  150. aht20.us0 = bsp_ustimer_get_origin();
  151. _aht20_read_data(g_aht20_fd, &aht20.temp, &aht20.humi);
  152. // printf("aht20.temp=%.3f ℃, aht20.humi=%.3f %%RH\r\n", aht20.temp, aht20.humi);
  153. }
  154. float aht20_get_temp(void)
  155. {
  156. if(g_aht20_fd < 0)
  157. {
  158. // 校准系数判断 温度低于-85℃时为异常状态,温度补偿系数默认改为1.0,
  159. // 因此此处在初始化失败时返回-100.0℃
  160. return -100.0;
  161. }
  162. return aht20.temp;
  163. }
  164. float aht20_get_humi(void)
  165. {
  166. return aht20.humi;
  167. }
  168. #endif /* TMP_CHIP_AHT20 */