sht3x.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #include <rthw.h>
  2. #include <rtthread.h>
  3. #include <rtdevice.h>
  4. #include <string.h>
  5. #define DBG_ENABLE
  6. #define DBG_SECTION_NAME "sht3x"
  7. #define DBG_LEVEL DBG_LOG
  8. #define DBG_COLOR
  9. #include <rtdbg.h>
  10. #include "sht3x.h"
  11. #ifdef PKG_USING_SHT3X
  12. #define CRC_POLY 0x31
  13. /**
  14. * This function write 2-byte cmd to SHT3x
  15. *
  16. * @param dev the pointer of device driver structure
  17. * @param cmd the 16bit command to be sent to SHT3x
  18. *
  19. * @return the cmd transfer status, RT_EOK reprensents setting successfully.
  20. */
  21. static rt_err_t write_cmd(sht3x_device_t dev, rt_uint16_t cmd)
  22. {
  23. struct rt_i2c_msg msgs;
  24. rt_uint8_t buf[2] ;
  25. buf[0] = cmd >> 8 ;
  26. buf[1] = cmd & 0xFF ;
  27. msgs.addr = dev->sht3x_addr;
  28. msgs.flags = RT_I2C_WR;
  29. msgs.buf = buf;
  30. msgs.len = 2;
  31. if (rt_i2c_transfer(dev->i2c, &msgs, 1) == 1)
  32. return RT_EOK;
  33. else
  34. return -RT_ERROR;
  35. }
  36. /**
  37. * This function read len bytes from dev and store the bytes in to buf
  38. *
  39. * @param dev the pointer of device driver structure
  40. * @param buf the pointer to buffer array
  41. * @param len the number of bytes to be read
  42. *
  43. * @return the i2c read status, RT_EOK represents success.
  44. */
  45. static rt_err_t read_bytes(sht3x_device_t dev, rt_uint8_t * buf, rt_uint8_t len){
  46. if(rt_i2c_master_recv(dev->i2c, dev->sht3x_addr, RT_I2C_RD, buf, len) == len){
  47. return RT_EOK ;
  48. }else
  49. {
  50. return - RT_ERROR ;
  51. }
  52. }
  53. /**
  54. * This function calculate CRC value of bytes in buffer
  55. * CRC_POLY is predefined as 0x31
  56. *
  57. * @param buf the pointer to buffer array
  58. * @param len the length of buffer array
  59. *
  60. * @return calculated CRC value.
  61. */
  62. static rt_uint8_t crc8(rt_uint8_t * buf, rt_uint8_t len){
  63. rt_uint8_t crc = 0xFF ;
  64. rt_uint8_t i, j ;
  65. for(j = len; j; j --){
  66. crc ^= *buf ++ ;
  67. for( i = 8; i; i --){
  68. crc = (crc & 0x80) ? (crc << 1) ^ CRC_POLY : (crc << 1) ;
  69. }
  70. }
  71. return crc ;
  72. }
  73. /**
  74. * This function read temperature and humidity by single shot mode
  75. * Attention:
  76. * - rt_thread_mdelay() is called to wait for SHT3x to be ready to read
  77. * - the temperature and humidity is stored in the device driver structure
  78. *
  79. * @param dev the pointer of device driver structure
  80. *
  81. * @return the status of read data from SHT3x, RT_EOK means success.
  82. */
  83. rt_err_t sht3x_read_singleshot(sht3x_device_t dev)
  84. {
  85. rt_uint8_t temp[6] ;
  86. rt_err_t result;
  87. RT_ASSERT(dev);
  88. result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
  89. if (result == RT_EOK)
  90. {
  91. if( write_cmd(dev, dev->cmd_readout) == RT_EOK)
  92. {
  93. // wait about 5 ms
  94. rt_thread_mdelay(5);
  95. if(read_bytes(dev, temp, 6) == RT_EOK){
  96. if(crc8(temp, 2) == temp[2]){
  97. dev->temperature = -45.0 + (temp[1] | temp[0] << 8) * 175.0 / (0xFFFF - 1) ; //sensor temperature convert to reality
  98. result = RT_EOK ;
  99. }else{
  100. result = -RT_ERROR ;
  101. }
  102. if(crc8(temp + 3, 2) == temp[5]){
  103. dev->humidity = (temp[4] | temp[3] << 8) * 0.0015259022 ; //sensor humidity convert to reality
  104. }else{
  105. result = -RT_ERROR ;
  106. }
  107. }else
  108. {
  109. result = -RT_ERROR ;
  110. }
  111. }
  112. else
  113. {
  114. result = -RT_ERROR ;
  115. }
  116. rt_mutex_release(dev->lock);
  117. }
  118. else
  119. {
  120. LOG_E("Taking mutex of SHT3x failed.");
  121. result = -RT_ERROR;
  122. }
  123. return result;
  124. }
  125. /**
  126. * This function resets all parameter with default
  127. *
  128. * @param dev the pointer of device driver structure
  129. *
  130. * @return the softreset status, RT_EOK reprensents setting successfully.
  131. */
  132. rt_err_t sht3x_softreset(sht3x_device_t dev)
  133. {
  134. RT_ASSERT(dev);
  135. if( write_cmd(dev, CMD_SOFT_RESET) == RT_EOK)
  136. {
  137. return RT_EOK;
  138. }else{
  139. return RT_ERROR ;
  140. }
  141. }
  142. /**
  143. * This function clear the status register in SHT3x
  144. *
  145. * @param dev the pointer of device driver structure
  146. *
  147. * @return the command transfer status, RT_EOK means success.
  148. */
  149. rt_err_t sht3x_clear_status(sht3x_device_t dev)
  150. {
  151. RT_ASSERT(dev);
  152. if( write_cmd(dev, CMD_CLEAR_STATUS) == RT_EOK)
  153. {
  154. return RT_EOK ;
  155. }else{
  156. return RT_ERROR ;
  157. }
  158. }
  159. /**
  160. * This function read the status register from SHT3x
  161. * Attention:
  162. * - the status word is stored in device driver structure
  163. *
  164. * @param dev the pointer of device driver structure
  165. *
  166. * @return the command transfer status, RT_EOK means success.
  167. */
  168. rt_err_t sht3x_read_status(sht3x_device_t dev)
  169. {
  170. rt_uint8_t buf[3];
  171. RT_ASSERT(dev);
  172. if( write_cmd(dev, CMD_READ_STATUS) == RT_EOK)
  173. {
  174. read_bytes(dev, buf, 3);
  175. if( crc8(buf, 2) == buf[2])
  176. {
  177. dev->status.status_word = ( buf[0] << 8 ) | buf[1];
  178. return RT_EOK ;
  179. }
  180. }
  181. return -RT_ERROR ;
  182. }
  183. rt_err_t sht3x_enable_heater(sht3x_device_t dev)
  184. {
  185. RT_ASSERT(dev);
  186. if( write_cmd(dev, CMD_HEATER_ENABLE) == RT_EOK)
  187. {
  188. return RT_EOK ;
  189. }else
  190. {
  191. return -RT_ERROR ;
  192. }
  193. }
  194. /**
  195. *
  196. *
  197. *
  198. *
  199. */
  200. rt_err_t sht3x_disable_heater(sht3x_device_t dev)
  201. {
  202. RT_ASSERT(dev);
  203. if( write_cmd(dev, CMD_HEATER_DISABLE) == RT_EOK)
  204. {
  205. return RT_EOK ;
  206. }else
  207. {
  208. return -RT_ERROR ;
  209. }
  210. }
  211. /**
  212. *
  213. *
  214. *
  215. *
  216. */
  217. rt_err_t sht3x_acc_resp_time(sht3x_device_t dev)
  218. {
  219. RT_ASSERT(dev);
  220. if( write_cmd(dev, CMD_ART) == RT_EOK)
  221. {
  222. return RT_EOK ;
  223. }else
  224. {
  225. return -RT_ERROR ;
  226. }
  227. }
  228. /**
  229. *
  230. *
  231. *
  232. *
  233. */
  234. rt_err_t sht3x_break(sht3x_device_t dev)
  235. {
  236. RT_ASSERT(dev);
  237. if( write_cmd(dev, CMD_BREAK) == RT_EOK)
  238. {
  239. return RT_EOK ;
  240. }else
  241. {
  242. return -RT_ERROR ;
  243. }
  244. }
  245. /**
  246. * This function initializes sht3x registered device driver
  247. *
  248. * @param i2c_bus_name the name of i2c device used by SHT3x device
  249. * @param sht3x_addr the address of SHT3x device
  250. *
  251. * @return the pointer to sht3x device driver structure.
  252. */
  253. sht3x_device_t sht3x_init(const char *i2c_bus_name, rt_uint8_t sht3x_addr)
  254. {
  255. sht3x_device_t dev;
  256. RT_ASSERT(i2c_bus_name);
  257. dev = rt_calloc(1, sizeof(struct sht3x_device));
  258. if (dev == RT_NULL)
  259. {
  260. LOG_E("Can't allocate memory for sht3x device on '%s' ", i2c_bus_name);
  261. return RT_NULL;
  262. }
  263. if(sht3x_addr == SHT3X_ADDR_PD || sht3x_addr == SHT3X_ADDR_PU){
  264. dev->sht3x_addr = sht3x_addr ;
  265. }else{
  266. LOG_E("Illegal sht3x address:'%x'", sht3x_addr);
  267. rt_free(dev);
  268. return RT_NULL;
  269. }
  270. dev->i2c = rt_i2c_bus_device_find(i2c_bus_name);
  271. if (dev->i2c == RT_NULL)
  272. {
  273. LOG_E("Can't find sht3x device on '%s' ", i2c_bus_name);
  274. rt_free(dev);
  275. return RT_NULL;
  276. }
  277. dev->lock = rt_mutex_create("mutex_sht3x", RT_IPC_FLAG_FIFO);
  278. if (dev->lock == RT_NULL)
  279. {
  280. LOG_E("Can't create mutex for sht3x device on '%s' ", i2c_bus_name);
  281. rt_free(dev);
  282. return RT_NULL;
  283. }
  284. // I2C streching disabled, medium repeatability for default single shot readout
  285. dev->cmd_readout = CMD_MEAS_POLLING_M ;
  286. return dev;
  287. }
  288. /**
  289. * This function releases memory and deletes mutex lock
  290. *
  291. * @param dev the pointer of device driver structure
  292. */
  293. void sht3x_deinit(sht3x_device_t dev)
  294. {
  295. RT_ASSERT(dev);
  296. rt_mutex_delete(dev->lock);
  297. rt_free(dev);
  298. }
  299. /**
  300. *
  301. *
  302. *
  303. *
  304. *
  305. */
  306. void sht3x(int argc, char *argv[])
  307. {
  308. static sht3x_device_t dev = RT_NULL;
  309. rt_uint8_t sht_addr = SHT3X_ADDR_PD ;
  310. if (argc > 1)
  311. {
  312. if (!strcmp(argv[1], "probe"))
  313. {
  314. if (argc >= 3)
  315. {
  316. /* initialize the sensor when first probe */
  317. if (!dev || strcmp(dev->i2c->parent.parent.name, argv[2]))
  318. {
  319. /* deinit the old device */
  320. if (dev)
  321. {
  322. sht3x_deinit(dev);
  323. }
  324. if( argc > 3)
  325. {
  326. if( strcmp("pd", argv[2]))
  327. {
  328. sht_addr = SHT3X_ADDR_PD ;
  329. }
  330. else if( strcmp("pu", argv[2]))
  331. {
  332. sht_addr = SHT3X_ADDR_PU ;
  333. }
  334. else
  335. {
  336. rt_kprintf("Illegal sht3x address, using 0x44 by default\n");
  337. sht_addr = SHT3X_ADDR_PD ; // pulled down by default: 0x44
  338. }
  339. }
  340. dev = sht3x_init(argv[2], sht_addr);
  341. if(!dev){
  342. rt_kprintf("sht3x probe failed, check input args\n");
  343. }
  344. }
  345. }
  346. else
  347. {
  348. rt_kprintf("sht3x probe <dev_name> - probe sensor by given name\n");
  349. }
  350. }
  351. else if (!strcmp(argv[1], "read"))
  352. {
  353. if (dev)
  354. {
  355. /* read the sensor data */
  356. sht3x_read_singleshot(dev);
  357. rt_kprintf("read sht3x sensor humidity : %d.%d %\n", (int)dev->humidity, (int)(dev->humidity * 10) % 10);
  358. rt_kprintf("read sht3x sensor temperature: %d.%d \n", (int)dev->temperature, (int)(dev->temperature * 10) % 10);
  359. }
  360. else
  361. {
  362. rt_kprintf("Please using 'sht3x probe <dev_name>' first\n");
  363. }
  364. }
  365. else
  366. {
  367. rt_kprintf("Unknown command. Please enter 'sht3x' for help\n");
  368. }
  369. }
  370. else
  371. {
  372. rt_kprintf("Usage:\n");
  373. rt_kprintf("sht3x probe <dev_name> - probe sensor by given name\n");
  374. rt_kprintf("sht3x read - read sensor sht20 data\n");
  375. }
  376. }
  377. MSH_CMD_EXPORT(sht3x, sht3x sensor function);
  378. #endif /* PKG_USING_SHT3X */