| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- #include <string.h>
- #define DBG_ENABLE
- #define DBG_SECTION_NAME "sht3x"
- #define DBG_LEVEL DBG_LOG
- #define DBG_COLOR
- #include <rtdbg.h>
- #include "sht3x.h"
- #ifdef PKG_USING_SHT3X
- #define CRC_POLY 0x31
- /**
- * This function write 2-byte cmd to SHT3x
- *
- * @param dev the pointer of device driver structure
- * @param cmd the 16bit command to be sent to SHT3x
- *
- * @return the cmd transfer status, RT_EOK reprensents setting successfully.
- */
- static rt_err_t write_cmd(sht3x_device_t dev, rt_uint16_t cmd)
- {
- struct rt_i2c_msg msgs;
- rt_uint8_t buf[2] ;
- buf[0] = cmd >> 8 ;
- buf[1] = cmd & 0xFF ;
- msgs.addr = dev->sht3x_addr;
- msgs.flags = RT_I2C_WR;
- msgs.buf = buf;
- msgs.len = 2;
- if (rt_i2c_transfer(dev->i2c, &msgs, 1) == 1)
- return RT_EOK;
- else
- return -RT_ERROR;
- }
- /**
- * This function read len bytes from dev and store the bytes in to buf
- *
- * @param dev the pointer of device driver structure
- * @param buf the pointer to buffer array
- * @param len the number of bytes to be read
- *
- * @return the i2c read status, RT_EOK represents success.
- */
- static rt_err_t read_bytes(sht3x_device_t dev, rt_uint8_t * buf, rt_uint8_t len)
- {
- if(rt_i2c_master_recv(dev->i2c, dev->sht3x_addr, RT_I2C_RD, buf, len) == len){
- return RT_EOK ;
- }else
- {
- return - RT_ERROR ;
- }
-
- }
- /**
- * This function calculate CRC value of bytes in buffer
- * CRC_POLY is predefined as 0x31
- *
- * @param buf the pointer to buffer array
- * @param len the length of buffer array
- *
- * @return calculated CRC value.
- */
- static rt_uint8_t crc8(rt_uint8_t * buf, rt_uint8_t len)
- {
- rt_uint8_t crc = 0xFF ;
- rt_uint8_t i, j ;
- for(j = len; j; j --){
- crc ^= *buf ++ ;
- for( i = 8; i; i --){
- crc = (crc & 0x80) ? (crc << 1) ^ CRC_POLY : (crc << 1) ;
- }
- }
- return crc ;
- }
- /**
- * This function read temperature and humidity by single shot mode
- * Attention:
- * - rt_thread_mdelay() is called to wait for SHT3x to be ready to read
- * - the temperature and humidity is stored in the device driver structure
- *
- * @param dev the pointer of device driver structure
- *
- * @return the status of read data from SHT3x, RT_EOK means success.
- */
- rt_err_t sht3x_read_singleshot(sht3x_device_t dev)
- {
- rt_uint8_t temp[6] ;
- rt_err_t result;
- RT_ASSERT(dev);
- result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
- if (result == RT_EOK)
- {
- if( write_cmd(dev, dev->cmd_readout) == RT_EOK)
- {
- // wait about 5 ms
- rt_thread_mdelay(5);
- if(read_bytes(dev, temp, 6) == RT_EOK){
- if(crc8(temp, 2) == temp[2]){
- dev->temperature = -45.0 + (temp[1] | temp[0] << 8) * 175.0 / (0xFFFF - 1) ; //sensor temperature convert to reality
- result = RT_EOK ;
- }else{
- result = -RT_ERROR ;
- }
- if(crc8(temp + 3, 2) == temp[5]){
- dev->humidity = (temp[4] | temp[3] << 8) * 0.0015259022 ; //sensor humidity convert to reality
- }else{
- result = -RT_ERROR ;
- }
- }else
- {
- result = -RT_ERROR ;
- }
- }
- else
- {
- result = -RT_ERROR ;
- }
- rt_mutex_release(dev->lock);
- }
- else
- {
- LOG_E("Taking mutex of SHT3x failed.");
- result = -RT_ERROR;
- }
-
- return result;
- }
- /**
- * This function resets all parameter with default
- *
- * @param dev the pointer of device driver structure
- *
- * @return the softreset status, RT_EOK reprensents setting successfully.
- */
- rt_err_t sht3x_softreset(sht3x_device_t dev)
- {
- RT_ASSERT(dev);
-
- if( write_cmd(dev, CMD_SOFT_RESET) == RT_EOK)
- {
- return RT_EOK;
- }else{
- return RT_ERROR ;
- }
- }
- /**
- * This function clear the status register in SHT3x
- *
- * @param dev the pointer of device driver structure
- *
- * @return the command transfer status, RT_EOK means success.
- */
- rt_err_t sht3x_clear_status(sht3x_device_t dev)
- {
- RT_ASSERT(dev);
- if( write_cmd(dev, CMD_CLEAR_STATUS) == RT_EOK)
- {
- return RT_EOK ;
- }else{
- return RT_ERROR ;
- }
- }
- /**
- * This function read the status register from SHT3x
- * Attention:
- * - the status word is stored in device driver structure
- *
- * @param dev the pointer of device driver structure
- *
- * @return the command transfer status, RT_EOK means success.
- */
- rt_err_t sht3x_read_status(sht3x_device_t dev)
- {
- rt_uint8_t buf[3];
- RT_ASSERT(dev);
- if( write_cmd(dev, CMD_READ_STATUS) == RT_EOK)
- {
- read_bytes(dev, buf, 3);
- if( crc8(buf, 2) == buf[2])
- {
- dev->status.status_word = ( buf[0] << 8 ) | buf[1];
- return RT_EOK ;
- }
- }
- return -RT_ERROR ;
- }
- /**
- * This function enable heater
- * @param dev the pointer of device driver structure
- *
- * @return the command transfer status, RT_EOK means success.
- */
- rt_err_t sht3x_enable_heater(sht3x_device_t dev)
- {
- RT_ASSERT(dev);
- if( write_cmd(dev, CMD_HEATER_ENABLE) == RT_EOK)
- {
- return RT_EOK ;
- }else
- {
- return -RT_ERROR ;
- }
- }
- /**
- * This function disable heater
- * @param dev the pointer of device driver structure
- *
- * @return the command transfer status, RT_EOK means success.
- */
- rt_err_t sht3x_disable_heater(sht3x_device_t dev)
- {
- RT_ASSERT(dev);
- if( write_cmd(dev, CMD_HEATER_DISABLE) == RT_EOK)
- {
- return RT_EOK ;
- }else
- {
- return -RT_ERROR ;
- }
- }
- /**
- * This function write accelerated response time command to SHT3x
- * @param dev the pointer of device driver structure
- *
- * @return the command transfer status, RT_EOK means success.
- */
- rt_err_t sht3x_acc_resp_time(sht3x_device_t dev)
- {
- RT_ASSERT(dev);
- if( write_cmd(dev, CMD_ART) == RT_EOK)
- {
- return RT_EOK ;
- }else
- {
- return -RT_ERROR ;
- }
- }
- /**
- * This function write break command to SHT3x to break out of continuous readout mode
- * @param dev the pointer of device driver structure
- *
- * @return the command transfer status, RT_EOK means success.
- */
- rt_err_t sht3x_break(sht3x_device_t dev)
- {
- RT_ASSERT(dev);
- if( write_cmd(dev, CMD_BREAK) == RT_EOK)
- {
- return RT_EOK ;
- }else
- {
- return -RT_ERROR ;
- }
- }
- /**
- * This function initializes sht3x registered device driver
- *
- * @param i2c_bus_name the name of i2c device used by SHT3x device
- * @param sht3x_addr the address of SHT3x device
- *
- * @return the pointer to sht3x device driver structure.
- */
- sht3x_device_t sht3x_init(const char *i2c_bus_name, rt_uint8_t sht3x_addr)
- {
- sht3x_device_t dev;
- RT_ASSERT(i2c_bus_name);
- dev = rt_calloc(1, sizeof(struct sht3x_device));
- if (dev == RT_NULL)
- {
- LOG_E("Can't allocate memory for sht3x device on '%s' ", i2c_bus_name);
- return RT_NULL;
- }
- if(sht3x_addr == SHT3X_ADDR_PD || sht3x_addr == SHT3X_ADDR_PU){
- dev->sht3x_addr = sht3x_addr ;
- }else{
- LOG_E("Illegal sht3x address:'%x'", sht3x_addr);
- rt_free(dev);
- return RT_NULL;
- }
-
- dev->i2c = rt_i2c_bus_device_find(i2c_bus_name);
- if (dev->i2c == RT_NULL)
- {
- LOG_E("Can't find sht3x device on '%s' ", i2c_bus_name);
- rt_free(dev);
- return RT_NULL;
- }
- dev->lock = rt_mutex_create("mutex_sht3x", RT_IPC_FLAG_FIFO);
- if (dev->lock == RT_NULL)
- {
- LOG_E("Can't create mutex for sht3x device on '%s' ", i2c_bus_name);
- rt_free(dev);
- return RT_NULL;
- }
- // I2C streching disabled, medium repeatability for default single shot readout
- dev->cmd_readout = CMD_MEAS_POLLING_M ;
- // clear the status register
- sht3x_clear_status(dev);
-
- return dev;
- }
- /**
- * This function releases memory and deletes mutex lock
- *
- * @param dev the pointer of device driver structure
- */
- void sht3x_deinit(sht3x_device_t dev)
- {
- RT_ASSERT(dev);
- rt_mutex_delete(dev->lock);
- rt_free(dev);
- }
- /**
- * This function is exported to MSH commands list
- * Usage example:
- * - sht3x probe i2c1 pu : initialize sht3x device on i2c1 bus with address pin pulled up(i2c address 0x45)
- * - sht3x probe i2c1: initialize sht3x device one i2c1 bus with address pin pulled down by default(i2c address 0x44)
- * - sht3x read: read and print temperature and humidity from previously initialized sht3x
- */
- void sht3x(int argc, char *argv[])
- {
- static sht3x_device_t dev = RT_NULL;
- rt_uint8_t sht_addr = SHT3X_ADDR_PD ;
-
- if (argc > 1)
- {
- if (!strcmp(argv[1], "probe"))
- {
- if (argc >= 3)
- {
- /* initialize the sensor when first probe */
- if (!dev || strcmp(dev->i2c->parent.parent.name, argv[2]))
- {
- /* deinit the old device */
- if(dev)
- {
- rt_kprintf("Deinit sht3x");
- sht3x_deinit(dev);
- }
- // no else needed here
- if( argc > 3)
- {
- if( !strcmp("pd", argv[3]))
- {
- sht_addr = SHT3X_ADDR_PD ;
- }
- else if( !strcmp("pu", argv[3]))
- {
- sht_addr = SHT3X_ADDR_PU ;
- }
- else
- {
- rt_kprintf("Illegal sht3x address, using 0x44 by default\n");
- sht_addr = SHT3X_ADDR_PD ; // pulled down by default: 0x44
- }
- }
- // no else needed here
- dev = sht3x_init(argv[2], sht_addr);
- if(!dev)
- {
- rt_kprintf("sht3x probe failed, check input args\n");
- }else
- {
- rt_kprintf("sht3x probed, addr:0x%x\n", sht_addr) ;
- }
- }
- }
- else
- {
- rt_kprintf("sht3x probe <i2c dev name> - probe sensor by given name\n");
- }
- }
- else if (!strcmp(argv[1], "read"))
- {
- if (dev)
- {
- /* read the sensor data */
- sht3x_read_singleshot(dev);
- rt_kprintf("sht3x humidity : %d.%d \n", (int)dev->humidity, (int)(dev->humidity * 10) % 10);
- rt_kprintf("sht3x temperature: %d.%d \n", (int)dev->temperature, (int)(dev->temperature * 10) % 10);
- }
- else
- {
- rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
- }
- }
- else if (!strcmp(argv[1], "status"))
- {
- if(dev)
- {
- if(sht3x_read_status(dev) == RT_EOK)
- {
- rt_kprintf("sht3x status:\n");
- rt_kprintf("\tchecksum:\t%d\t- 0 means checksum correct\n", dev->status.bits.checksum_ok);
- rt_kprintf("\tcommand:\t%d\t- 0 means last cmd executed OK\n", dev->status.bits.command_ok);
- rt_kprintf("\treset deteced:\t%d\n", dev->status.bits.reset_detected);
- rt_kprintf("\talert pending:\t%d\n", dev->status.bits.alert_pending);
- rt_kprintf("\tT track alert:\t%d\n", dev->status.bits.T_tracking_alert);
- rt_kprintf("\tRH track alert:\t%d\n", dev->status.bits.RH_tracking_alert);
- rt_kprintf("\theater enabled:\t%d\n", dev->status.bits.heater);
- }else
- {
- rt_kprintf("sht3x status not read\n");
- }
- }else
- {
- rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
- }
- }
- else if (!strcmp(argv[1], "reset"))
- {
- if(dev)
- {
- if(sht3x_softreset(dev) == RT_EOK)
- {
- rt_kprintf("sht3x reset cmd sent\n");
- }else
- {
- rt_kprintf("sht3x reset cmd not sent\n");
- }
- }else
- {
- rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
- }
- }
- else if (!strcmp(argv[1], "heater"))
- {
- if(dev)
- {
- if( !strcmp(argv[2], "on"))
- {
- if(sht3x_enable_heater(dev) == RT_EOK)
- {
- rt_kprintf("sht3x heater cmd sent\n");
- }else
- {
- rt_kprintf("sht3x heater cmd not sent\n");
- }
- }else if( !strcmp(argv[2], "off"))
- {
- if(sht3x_disable_heater(dev) == RT_EOK)
- {
- rt_kprintf("sht3x heater cmd sent\n");
- }else
- {
- rt_kprintf("sht3x heater cmd not sent\n");
- }
- }
- else{
- rt_kprintf("Please input correct format:sht3x heater on/off\n");
- }
- }else
- {
- rt_kprintf("Please using 'sht3x probe <i2c dev name> <pu/pd>' first\n");
- }
- }
- else
- {
- rt_kprintf("Unknown command. Enter 'sht3x' for help\n");
- }
- }
- else
- {
- rt_kprintf("Usage:\n");
- rt_kprintf("\tsht3x probe <i2c dev name> <pu/pd> -- probe sensor by i2c dev name and pull config\n");
- rt_kprintf("\tsht3x read -- read sensor sht3x data\n");
- rt_kprintf("\tsht3x status -- status register of sht3x\n");
- rt_kprintf("\tsht3x reset -- send soft reset command to sht3x\n");
- rt_kprintf("\tsht3x heater <on/off> -- turn on/off heater of sht3x\n");
- }
- }
- MSH_CMD_EXPORT(sht3x, sht3x sensor);
- #endif /* PKG_USING_SHT3X */
|