1 /*
2 * Copyright (c) 2022 Unionman Technology Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <sys/ioctl.h>
22
23 #include <linux/i2c.h>
24 #include <linux/i2c-dev.h>
25
26 #include "securec.h"
27 #include "hilog/log.h"
28
29 #include "i2cinterface.h"
30
31 /* 函数返回值说明 return 0 代表正常运行 return -1 代表驱动无法打开
32 return -2 代表分配缓存失败 return -3 代表读取/写入失败
33 return -4 代表CRC校验失败 return -5 代表保存数据失败 */
34
35 // 转换温湿度并保存在结构体中
ConvertTempAndHum(sRHAndTemp_t * tempRH,uint8_t * rawTemp,uint8_t * rawHum)36 void ConvertTempAndHum(sRHAndTemp_t *tempRH, uint8_t *rawTemp, uint8_t *rawHum)
37 {
38 tempRH->TemperatureC = ConvertTemperature(rawTemp);
39 tempRH->Humidity = ConvertHumidity(rawHum);
40 tempRH->TemperatureF = 1.8f * tempRH->TemperatureC + 32L;
41 }
42
43 // 温度转换函数
ConvertTemperature(uint8_t * rawTemp)44 float ConvertTemperature(uint8_t *rawTemp)
45 {
46 uint16_t rawValue = 0;
47 rawValue = rawTemp[0];
48 rawValue = (rawValue << 8L) | rawTemp[1];
49 return 175.0f * (float)rawValue / 65535.0f - 45.0f;
50 }
51
52 // 湿度转换函数
ConvertHumidity(uint8_t * rawHum)53 float ConvertHumidity(uint8_t *rawHum)
54 {
55 uint16_t rawValue = 0;
56 rawValue = rawHum[0];
57 rawValue = (rawValue << 8L) | rawHum[1];
58 return 100.0f * (float)rawValue / 65535.0f;
59 }
60
61 // CRC校验
CheckCrc(uint8_t * data)62 uint8_t CheckCrc(uint8_t *data)
63 {
64 uint8_t bit = 0;
65 uint8_t crc = 0xFF;
66
67 for (uint8_t dataCounter = 0; dataCounter < 2L; dataCounter++) {
68 crc ^= (data[dataCounter]);
69 for (bit = 8L; bit > 0; --bit) {
70 if (crc & 0x80) {
71 crc = (crc << 1) ^ 0x31;
72 } else {
73 crc = (crc << 1);
74 }
75 }
76 }
77 return crc;
78 }
79
SoftReset(char * devName,char addr)80 int SoftReset(char *devName, char addr)
81 {
82 int fd = -1;
83 int ret = -1;
84 uint8_t _pBuf[2L] = {0};
85
86 struct i2c_rdwr_ioctl_data i2c_data;
87
88 // 关闭周期测量
89 SendCommand(devName, addr, SHT3X_CMD_STOP_PERIODIC_ACQUISITION_MODE);
90 usleep(50L * 1000L); // 等待发送控制命令完成
91
92 fd = open(devName, O_RDWR);
93 if (fd < 0) {
94 HILOG_ERROR(LOG_CORE, "Can not have dev %s \n", devName);
95 return -1;
96 }
97
98 i2c_data.nmsgs = 1;
99 i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs * sizeof(struct i2c_msg));
100 if (i2c_data.msgs == NULL) {
101 HILOG_ERROR(LOG_CORE, "malloc error \n");
102 close(fd);
103 return -2L;
104 }
105
106 ioctl(fd, I2C_TIMEOUT, 1);
107 ioctl(fd, I2C_RETRIES, 2L);
108
109 _pBuf[0] = SHT3X_CMD_SOFT_RESET >> 8L;
110 _pBuf[1] = SHT3X_CMD_SOFT_RESET & 0xFF;
111
112 // 写寄存器
113 i2c_data.msgs[0].len = 2L;
114 i2c_data.msgs[0].addr = addr;
115 i2c_data.msgs[0].flags = 0; // 写:0 读:1
116 i2c_data.msgs[0].buf = _pBuf;
117
118 ret = ioctl(fd, I2C_RDWR, (unsigned long)&i2c_data);
119 if (ret < 0) {
120 HILOG_ERROR(LOG_CORE, "SoftReset %c error \n", addr);
121 close(fd);
122 free(i2c_data.msgs);
123 return -3L;
124 }
125 free(i2c_data.msgs);
126 close(fd);
127
128 return 0;
129 }
130
SendCommand(char * devName,char addr,uint16_t modeCommand)131 int SendCommand(char *devName, char addr, uint16_t modeCommand)
132 {
133 int fd = -1;
134 int ret = -1;
135 uint8_t _pBuf[2L] = {0};
136
137 struct i2c_rdwr_ioctl_data i2c_data;
138
139 fd = open(devName, O_RDWR);
140 if (fd < 0) {
141 HILOG_ERROR(LOG_CORE, "can not have dev %s \n", devName);
142 return -1;
143 }
144
145 i2c_data.nmsgs = 1;
146 i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs * sizeof(struct i2c_msg));
147 if (i2c_data.msgs == NULL) {
148 HILOG_ERROR(LOG_CORE, "malloc error \n");
149 close(fd);
150 return -2L;
151 }
152
153 ioctl(fd, I2C_TIMEOUT, 1);
154 ioctl(fd, I2C_RETRIES, 2L);
155
156 _pBuf[0] = modeCommand >> 8L;
157 _pBuf[1] = modeCommand & 0xFF;
158 // 写寄存器
159 i2c_data.msgs[0].len = 2L;
160 i2c_data.msgs[0].addr = addr;
161 i2c_data.msgs[0].flags = 0; // 写:0 读:1
162 i2c_data.msgs[0].buf = _pBuf;
163
164 ret = ioctl(fd, I2C_RDWR, (unsigned long)&i2c_data);
165 if (ret < 0) {
166 HILOG_ERROR(LOG_CORE, "SendCommand %c error \n", addr);
167 close(fd);
168 free(i2c_data.msgs);
169 return -3L;
170 }
171 free(i2c_data.msgs);
172 close(fd);
173
174 return 0;
175 }
176
177 // 读状态寄存器
ReadStatusReg(char * devName,char addr,sStatusReg_t * regRaw)178 int ReadStatusReg(char *devName, char addr, sStatusReg_t *regRaw)
179 {
180 uint8_t register1[3L] = {0};
181 uint16_t data = 0;
182
183 int fd = -1;
184 int ret = -1;
185
186 uint8_t _pBuf[2L] = {0};
187
188 struct i2c_rdwr_ioctl_data i2c_data;
189
190 fd = open(devName, O_RDWR);
191 if (fd < 0) {
192 HILOG_ERROR(LOG_CORE, "can not have dev %s \n", devName);
193 return -1;
194 }
195
196 i2c_data.nmsgs = 2L;
197 i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs * sizeof(struct i2c_msg));
198 if (i2c_data.msgs == NULL) {
199 HILOG_ERROR(LOG_CORE, "malloc error \n");
200 close(fd);
201 return -2L;
202 }
203
204 ioctl(fd, I2C_TIMEOUT, 1);
205 ioctl(fd, I2C_RETRIES, 2L);
206
207 _pBuf[0] = SHT3X_CMD_READ_STATUS_REG >> 8L;
208 _pBuf[1] = SHT3X_CMD_READ_STATUS_REG & 0xFF;
209 // 写寄存器
210 i2c_data.msgs[0].len = 2L;
211 i2c_data.msgs[0].addr = addr;
212 i2c_data.msgs[0].flags = 0; // 写:0 读:1
213 i2c_data.msgs[0].buf = _pBuf;
214 // 读取数据
215 i2c_data.msgs[1].len = 3L;
216 i2c_data.msgs[1].addr = addr;
217 i2c_data.msgs[1].flags = 1; // 写:0 读:1
218 i2c_data.msgs[1].buf = register1;
219
220 ret = ioctl(fd, I2C_RDWR, (unsigned long)&i2c_data);
221 if (ret < 0) {
222 HILOG_ERROR(LOG_CORE, "ReadStatusRegister read data %c error \n", addr);
223 close(fd);
224 free(i2c_data.msgs);
225 return -3L;
226 }
227 free(i2c_data.msgs);
228 close(fd);
229
230 if (CheckCrc(register1) != register1[2L]) {
231 HILOG_ERROR(LOG_CORE, "ReadStatusRegister data checkCrc fail \n");
232 return -4L;
233 }
234
235 data = (register1[0] << 8L) | register1[1];
236 ret = memcpy_s(regRaw, sizeof(sStatusReg_t), &data, 2L);
237 if (ret != 0) {
238 HILOG_ERROR(LOG_CORE, "ReadStatusRegister memcpy_s fail! \n");
239 return -5L;
240 }
241
242 return 0;
243 }
244
245 // 读温湿度
ReadTempAndHum(char * devName,char addr,sRHAndTemp_t * tempRH)246 int ReadTempAndHum(char *devName, char addr, sRHAndTemp_t *tempRH)
247 {
248 int fd = -1;
249 int ret = -1;
250
251 uint8_t rawData[6L] = {0};
252 uint8_t rawTemp[3L] = {0};
253 uint8_t rawHum[3L] = {0};
254
255 struct i2c_rdwr_ioctl_data i2c_data;
256
257 fd = open(devName, O_RDWR);
258 if (fd < 0) {
259 HILOG_ERROR(LOG_CORE, "can not have dev %s \n", devName);
260 return -1;
261 }
262
263 i2c_data.nmsgs = 1;
264 i2c_data.msgs = (struct i2c_msg *)malloc(i2c_data.nmsgs * sizeof(struct i2c_msg));
265 if (i2c_data.msgs == NULL) {
266 HILOG_ERROR(LOG_CORE, "malloc error \n");
267 close(fd);
268 return -2L;
269 }
270
271 ioctl(fd, I2C_TIMEOUT, 1);
272 ioctl(fd, I2C_RETRIES, 2L);
273
274 // 读取数据
275 i2c_data.msgs[0].len = 6L;
276 i2c_data.msgs[0].addr = addr;
277 i2c_data.msgs[0].flags = 1; // 写:0 读:1
278 i2c_data.msgs[0].buf = rawData;
279
280 ret = ioctl(fd, I2C_RDWR, (unsigned long)&i2c_data);
281 if (ret < 0) {
282 HILOG_ERROR(LOG_CORE, "ReadTempAndHum read data 0x%c error \n", addr);
283 close(fd);
284 free(i2c_data.msgs);
285 return -3L;
286 }
287 free(i2c_data.msgs);
288 close(fd);
289
290 ret = memcpy_s(rawTemp, sizeof(rawTemp), rawData, 3L);
291 if (ret != 0) {
292 HILOG_ERROR(LOG_CORE, "ReadTempAndHum memcpy_s fail! \n");
293 return -5L;
294 }
295
296 ret = memcpy_s(rawHum, sizeof(rawHum), rawData + 3L, 3L);
297 if (ret != 0) {
298 HILOG_ERROR(LOG_CORE, "ReadTempAndHum memcpy_s fail! \n");
299 return -5L;
300 }
301
302 if ((CheckCrc(rawTemp) != rawTemp[2L]) || (CheckCrc(rawHum) != rawHum[2L])) {
303 HILOG_ERROR(LOG_CORE, "ReadTempAndHum data checkCrc fail \n");
304 return -4L;
305 }
306
307 ConvertTempAndHum(tempRH, rawTemp, rawHum);
308
309 return 0;
310 }
311
312 // 设置mps与刷新率
ModeSet(char * devName,char addr,uint8_t mps,uint8_t repeatability)313 int ModeSet(char *devName, char addr, uint8_t mps, uint8_t repeatability)
314 {
315 int ret;
316 if (mps == 0) {
317 ret = MpsHalfHz(devName, addr, repeatability);
318 } else if (mps == 1) {
319 ret = Mps1Hz(devName, addr, repeatability);
320 } else if (mps == 2L) {
321 ret = Mps2Hz(devName, addr, repeatability);
322 } else if (mps == 3L) {
323 ret = Mps4Hz(devName, addr, repeatability);
324 } else if (mps == 4L) {
325 ret = Mps10Hz(devName, addr, repeatability);
326 } else {
327 HILOG_ERROR(LOG_CORE, " mps int for range[0,4]\n repeatability int for range[0,2] \n");
328 ret = -3L;
329 }
330 return ret;
331 }
332
333 // mps为0.5hz时候选择刷新率
MpsHalfHz(char * devName,char addr,uint8_t repeatability)334 int MpsHalfHz(char *devName, char addr, uint8_t repeatability)
335 {
336 int ret;
337 if (repeatability == 0) {
338 SendCommand(devName, addr, SHT3X_CMD_SETMODE_L_FREQUENCY_HALF_HZ);
339 ret = 0;
340 } else if (repeatability == 1) {
341 SendCommand(devName, addr, SHT3X_CMD_SETMODE_M_FREQUENCY_HALF_HZ);
342 ret = 0;
343 } else if (repeatability == 2L) {
344 SendCommand(devName, addr, SHT3X_CMD_SETMODE_H_FREQUENCY_HALF_HZ);
345 ret = 0;
346 } else {
347 HILOG_ERROR(LOG_CORE, " mps int for range[0,4]\n repeatability int for range[0,2] \n");
348 ret = -3L;
349 }
350 return ret;
351 }
352
353 // mps为1hz时候选择刷新率
Mps1Hz(char * devName,char addr,uint8_t repeatability)354 int Mps1Hz(char *devName, char addr, uint8_t repeatability)
355 {
356 int ret;
357 if (repeatability == 0) {
358 SendCommand(devName, addr, SHT3X_CMD_SETMODE_L_FREQUENCY_1_HZ);
359 ret = 0;
360 } else if (repeatability == 1) {
361 SendCommand(devName, addr, SHT3X_CMD_SETMODE_M_FREQUENCY_1_HZ);
362 ret = 0;
363 } else if (repeatability == 2L) {
364 SendCommand(devName, addr, SHT3X_CMD_SETMODE_H_FREQUENCY_1_HZ);
365 ret = 0;
366 } else {
367 HILOG_ERROR(LOG_CORE, " mps int for range[0,4]\n repeatability int for range[0,2] \n");
368 ret = -3L;
369 }
370 return ret;
371 }
372
373 // mps为2hz时候选择刷新率
Mps2Hz(char * devName,char addr,uint8_t repeatability)374 int Mps2Hz(char *devName, char addr, uint8_t repeatability)
375 {
376 int ret;
377 if (repeatability == 0) {
378 SendCommand(devName, addr, SHT3X_CMD_SETMODE_L_FREQUENCY_2_HZ);
379 ret = 0;
380 } else if (repeatability == 1) {
381 SendCommand(devName, addr, SHT3X_CMD_SETMODE_M_FREQUENCY_2_HZ);
382 ret = 0;
383 } else if (repeatability == 2L) {
384 SendCommand(devName, addr, SHT3X_CMD_SETMODE_H_FREQUENCY_2_HZ);
385 ret = 0;
386 } else {
387 HILOG_ERROR(LOG_CORE, " mps int for range[0,4]\n repeatability int for range[0,2] \n");
388 ret = -3L;
389 }
390 return ret;
391 }
392
393 // mps为4hz时候选择刷新率
Mps4Hz(char * devName,char addr,uint8_t repeatability)394 int Mps4Hz(char *devName, char addr, uint8_t repeatability)
395 {
396 int ret;
397 if (repeatability == 0) {
398 SendCommand(devName, addr, SHT3X_CMD_SETMODE_L_FREQUENCY_4_HZ);
399 ret = 0;
400 } else if (repeatability == 1) {
401 SendCommand(devName, addr, SHT3X_CMD_SETMODE_M_FREQUENCY_4_HZ);
402 ret = 0;
403 } else if (repeatability == 2L) {
404 SendCommand(devName, addr, SHT3X_CMD_SETMODE_H_FREQUENCY_4_HZ);
405 ret = 0;
406 } else {
407 HILOG_ERROR(LOG_CORE, " mps int for range[0,4]\n repeatability int for range[0,2] \n");
408 ret = -3L;
409 }
410 return ret;
411 }
412
413 // mps为10hz时候选择刷新率
Mps10Hz(char * devName,char addr,uint8_t repeatability)414 int Mps10Hz(char *devName, char addr, uint8_t repeatability)
415 {
416 int ret;
417 if (repeatability == 0) {
418 SendCommand(devName, addr, SHT3X_CMD_SETMODE_L_FREQUENCY_10_HZ);
419 ret = 0;
420 } else if (repeatability == 1) {
421 SendCommand(devName, addr, SHT3X_CMD_SETMODE_M_FREQUENCY_10_HZ);
422 ret = 0;
423 } else if (repeatability == 2L) {
424 SendCommand(devName, addr, SHT3X_CMD_SETMODE_H_FREQUENCY_10_HZ);
425 ret = 0;
426 } else {
427 HILOG_ERROR(LOG_CORE, " mps int for range[0,4]\n repeatability int for range[0,2] \n");
428 ret = -3L;
429 }
430 return ret;
431 }