OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 801|回复: 0

基于Linux I2C实现SHT20驱动程序

[复制链接]

44

主题

187

帖子

0

精华

高级会员

Rank: 4

积分
563
金钱
563
注册时间
2016-9-28
在线时间
158 小时
发表于 2024-1-18 18:29:29 | 显示全部楼层 |阅读模式
本帖最后由 mftang2016 于 2024-1-18 18:35 编辑

1 驱动程序实现
1)SHT20硬件接口图
1704466900882.png

1704466918987.png
file://G:/workspace/documents/%E6%8A%80%E6%9C%AF%E8%B5%84%E6%96%99/linux/Linux%20Study(Mini2440).assets/1704466900882.png?lastModify=1705556772
file://G:/workspace/documents/%E6%8A%80%E6%9C%AF%E8%B5%84%E6%96%99/linux/Linux%20Study(Mini2440).assets/1704466918987.png?lastModify=1705556772
2)  代码实现
在drv-sht20.c中实现驱动程序,使用系统自带I2C-0接口,编写驱动代码

  1. #include "drv-sht20.h"

  2. /******************************************************************************
  3. * LOCAL MACROS AND DEFINITIONS
  4. ******************************************************************************/
  5. #define SHT2X_ADDR           0x40
  6. #define POLY                 0x131          //P(x)=x^8+x^5+x^4+1 = 100110001

  7. #define DELAY_CNT            4500            //for , sleep time is 6.4 ms
  8. #define DEV_FILE             "/dev/i2c/0"

  9. #define QUERY_TEMP_CMD       TRIG_T_MEASUREMENT_POLL
  10. #define QUERY_HUMIDY_CMD     TRIG_RH_MEASUREMENT_POLL


  11. static int public_fd;


  12. static void msleep(unsigned int time)
  13. {
  14.     struct timespec sleeper, temp;

  15.     sleeper.tv_sec = (time_t)(time/1000);
  16.     sleeper.tv_nsec = (long)(time%1000)*1000000;
  17.     nanosleep(&sleeper, &temp);
  18. }

  19. static int sht2xdrv_CheckCrc(unsigned char data[], unsigned char nbrOfBytes, unsigned char checksum)
  20. {
  21.     int set = 0;
  22.     unsigned char crc = 0;
  23.     unsigned char byteCtr;
  24.     unsigned char bit;
  25.    
  26.     //calculates 8-Bit checksum with given polynomial
  27.     for (byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
  28.     {
  29.         crc ^= (data[byteCtr]);
  30.         for ( bit = 8; bit > 0; --bit)
  31.         {
  32.             if (crc & 0x80)
  33.             {
  34.                 crc = (crc << 1) ^ POLY;
  35.             }
  36.             else
  37.             {
  38.                 crc = (crc << 1);
  39.             }
  40.         }
  41.     }

  42.     if (crc != checksum)
  43.     {
  44.         set = -1;
  45.     }

  46.     return set;
  47. }

  48. static int sht2xdrv_CalcTemperatureC(unsigned short u16sT)
  49. {
  50.     int temperatureC;       // variable for result

  51.     u16sT &= ~0x0003;       // clear bits [1..0] (status bits)

  52.     /*
  53.     * Formula T = -46.85 + 175.72 * ST / 2^16 from data sheet 6.2,
  54.     * optimized for integer fixed point (3 digits) arithmetic
  55.     */

  56.     temperatureC = ((17572 * u16sT) >> 16) - 4685;

  57.     return temperatureC;
  58. }

  59. static int sht2xdrv_CalcRH(unsigned short u16sRH)
  60. {
  61.     int humidityRH;       // variable for result

  62.     u16sRH &= ~0x0003;          // clear bits [1..0] (status bits)

  63.     /*
  64.     * Formula RH = -6 + 125 * SRH / 2^16 from data sheet 6.1,
  65.     * optimized for integer fixed point (3 digits) arithmetic
  66.     */

  67.     humidityRH = ((12500 * u16sRH) >> 16) - 600;

  68.     return humidityRH;
  69. }

  70. static int sht2x_send_cmd_wr( unsigned cmd)
  71. {
  72.         int              ret = -1;
  73.         unsigned char    buf[2] = {0};

  74.     switch (cmd)
  75.     {
  76.         case QUERY_TEMP_CMD:
  77.             buf[0] = QUERY_TEMP_CMD;
  78.             ret = write(public_fd, buf, 1);
  79.             if( ret < 0 )
  80.             {
  81.                 printf("write temper cmd to sht2x failure.\n");
  82.                 return -1;
  83.             }
  84.             msleep(85);  //datasheet typ=66, max=85
  85.             break;

  86.         case QUERY_HUMIDY_CMD:
  87.             buf[0] = QUERY_HUMIDY_CMD;
  88.             ret = write(public_fd, buf, 1);
  89.             if( ret < 0 )
  90.             {
  91.                 printf("write humidity cmd to sht2x failure.\n");
  92.                 return -1;
  93.             }
  94.             msleep(29);  //datasheet typ=22, max=29
  95.             break;
  96.         default:
  97.             return -1;
  98.     }

  99.     return 0;
  100. }


  101. int sht2x_init(void)
  102. {
  103.         int fd = -1;
  104.        
  105.     fd = open(DEV_FILE, O_RDWR);
  106.     if( fd < 0 )
  107.     {
  108.         close( fd );
  109.         printf("%s %s i2c device open failure: %s\n", __FILE__, __FUNCTION__, strerror(errno));
  110.         return -1;
  111.     }

  112.     ioctl(fd, I2C_TENBIT, 0);
  113.     ioctl(fd, I2C_SLAVE, SHT2X_ADDR);
  114.     public_fd = fd;

  115.     return fd;
  116. }

  117. int sht2x_softreset( void )
  118. {
  119.     int           ret = -1;
  120.     unsigned char buf[2] = {0};
  121.     unsigned char cmd = SOFT_RESET;
  122.        
  123.     buf[0] = cmd;
  124.     ret = write(public_fd, buf, 1);
  125.     if( ret < 0 )
  126.     {
  127.         printf("%s %s write softrest cmd to sht2x failure \n", __FILE__, __FUNCTION__);
  128.         return -1;
  129.     }

  130.     msleep(50);

  131.     return 0;
  132. }

  133. int sht2x_get_tempeture( float *temper)
  134. {
  135.     unsigned char   buf[4] = {0}, checksum;
  136.     int             ret = -1;
  137.     int tempval;

  138.         ret = sht2x_send_cmd_wr( QUERY_TEMP_CMD);
  139.     if( ret < 0 )
  140.     {
  141.         return -1;
  142.     }

  143.     ret = read(public_fd, buf, 3);
  144.     if( ret < 0 )
  145.     {
  146.         printf("get the temper failure.\n");
  147.         return -1;
  148.     }

  149.     // match crc here
  150.     checksum = buf[2];
  151.     ret = sht2xdrv_CheckCrc(buf, 2, checksum);
  152.     if( ret < 0 )
  153.     {
  154.         printf("match check sum error.\n");
  155.         return -1;
  156.     }

  157.     tempval = (buf[0] << 8) | buf[1];
  158.     *temper = sht2xdrv_CalcTemperatureC( tempval );
  159.   
  160.     return 0;
  161. }

  162. int sht2x_get_humidy( float *humidy )
  163. {
  164.     unsigned char   buf[4] = {0}, checksum;
  165.     int             ret = -1;
  166.     int tempval;

  167.         ret = sht2x_send_cmd_wr( QUERY_HUMIDY_CMD );
  168.     if( ret < 0 )
  169.     {
  170.         return -1;
  171.     }

  172.     ret = read(public_fd, buf, 3);
  173.     if( ret < 0 )
  174.     {
  175.         printf("get the humidy failure.\n");
  176.         return -1;
  177.     }

  178.     // match crc here
  179.     checksum = buf[2];
  180.     ret = sht2xdrv_CheckCrc(buf, 2, checksum);
  181.     if( ret < 0 )
  182.     {
  183.         printf("match check sum error.\n");
  184.         return -1;
  185.     }

  186.     tempval = (buf[0] << 8) | buf[1];
  187.     *humidy = sht2xdrv_CalcRH( tempval );
  188.   
  189.     return 0;
  190. }

  191. int sht2x_open( void )
  192. {
  193.     int set;

  194.     set = sht2x_init();
  195.     if( set < 0 ){
  196.         return -1;
  197.     }

  198.     set = sht2x_softreset();
  199.     if( set < 0 ){
  200.         return -1;
  201.     }  

  202.     return 0;
  203. }


  204. int sht2x_release( void )
  205. {
  206.     close( public_fd );

  207.     return 0;
  208. }
复制代码

头文件部分定义参数和引用

  1. #ifndef __DRV_SHT20_H
  2. #define __DRV_SHT20_H

  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif

  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <linux/types.h>
  9. #include <linux/i2c-dev.h>
  10. #include <linux/i2c.h>
  11. #include <sys/ioctl.h>
  12. #include <unistd.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <fcntl.h>
  16. #include <stdlib.h>
  17. #include <linux/fs.h>
  18. #include <errno.h>
  19. #include <assert.h>
  20. #include <string.h>
  21. #include <time.h>

  22. typedef enum sht2xOptErrorCode
  23. {
  24.     SHT2x_RES_I2C_ERR = 0X01,
  25. }sht2xOptErrorCode;

  26. /******************************************************************************
  27. * EXPORTED MACROS AND DEFINITIONS
  28. ******************************************************************************/
  29. typedef enum sht2xResolution_t
  30. {
  31.   SHT2x_RES_12_14BIT       = 0x00, // RH=12bit, T=14bit
  32.   SHT2x_RES_8_12BIT        = 0x01, // RH= 8bit, T=12bit
  33.   SHT2x_RES_10_13BIT       = 0x80, // RH=10bit, T=13bit
  34.   SHT2x_RES_11_11BIT       = 0x81, // RH=11bit, T=11bit
  35.   SHT2x_RES_MASK           = 0x81  // Mask for res. bits (7,0) in user reg.
  36. } sht2xResolution_t;

  37. typedef enum sht2xStatusCode {
  38.   SHT2x_STATUS_OK                = 0x00,
  39.   SHT2x_STATUS_VALID_DATA        = 0x01,
  40.   SHT2x_STATUS_NO_CHANGE         = 0x02,
  41.   SHT2x_STATUS_ABORTED           = 0x03,
  42.   SHT2x_STATUS_BUSY              = 0x04,
  43.   SHT2x_STATUS_SUSPEND           = 0x05,
  44.   SHT2x_STATUS_ERR_IO            = 0x06,
  45.   SHT2x_STATUS_ERR_BAD_DATA      = 0x07,
  46.   SHT2x_STATUS_ERR_TIMEOUT       = 0x08
  47. }sht2xStatusCode;

  48. // sensor command
  49. typedef enum{
  50.   TRIG_T_MEASUREMENT_HM    = 0xE3, // command trig. temp meas. hold master
  51.   TRIG_RH_MEASUREMENT_HM   = 0xE5, // command trig. humidity meas. hold master
  52.   TRIG_T_MEASUREMENT_POLL  = 0xF3, // command trig. temp meas. no hold master
  53.   TRIG_RH_MEASUREMENT_POLL = 0xF5, // command trig. humidity meas. no hold master
  54.   USER_REG_W               = 0xE6, // command writing user register
  55.   USER_REG_R               = 0xE7, // command reading user register
  56.   SOFT_RESET               = 0xFE  // command soft reset
  57. }sht2xCommand_t;

  58. typedef enum {
  59.   SHT2x_EOB_ON             = 0x40, // end of battery
  60.   SHT2x_EOB_MASK           = 0x40, // Mask for EOB bit(6) in user reg.
  61. } sht2xEob_t;

  62. typedef enum {
  63.   SHT2x_HEATER_ON          = 0x04, // heater on
  64.   SHT2x_HEATER_OFF         = 0x00, // heater off
  65.   SHT2x_HEATER_MASK        = 0x04, // Mask for Heater bit(2) in user reg.
  66. } etSHT2xHeater;

  67. // measurement signal selection
  68. typedef enum{
  69.   HUMIDITY,
  70.   TEMP
  71. }etSHT2xMeasureType;

  72. typedef enum{
  73.   I2C_ADR_W                = 128,   // sensor I2C address + write bit
  74.   I2C_ADR_R                = 129    // sensor I2C address + read bit
  75. }etI2cHeader;


  76. typedef struct {
  77.     unsigned char _step;
  78.     unsigned char ret;
  79.    
  80.     unsigned char finish;     //1: finished, 0: idle
  81.     unsigned char dataValid;  //1: valid, 0: invalid
  82.    
  83.     int _tryCnt;
  84.     int _binValue;   // primordial value from sht20 register
  85.     int outValue;    // true temperature or humidity
  86. } shtdrv;

  87. typedef struct {
  88.     shtdrv st_Temp;
  89.     shtdrv st_RH;
  90.     int errorCode;
  91. }shtOpt;


  92. int sht2x_open( void );

  93. int sht2x_get_humidy( float *humidy );

  94. int sht2x_get_tempeture( float *temper);

  95. int sht2x_release( void );


  96. #ifdef __cplusplus
  97. }
  98. #endif

  99. #endif /* __DRV_SHT20_H */
复制代码

2 测试代码实现
实现功能,读取温度和湿度数据,并通过调试终端打印数据
1) 测试代码
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <linux/types.h>
  4. #include <linux/i2c-dev.h>
  5. #include <linux/i2c.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <fcntl.h>
  10. #include <stdlib.h>
  11. #include <linux/fs.h>
  12. #include <sys/ioctl.h>
  13. #include <errno.h>
  14. #include <assert.h>
  15. #include <string.h>
  16. #include <time.h>
  17. #include "drv-sht20.h"

  18. int main(void)
  19. {
  20.     float temper, rh;
  21.     int count_run = 100;
  22.     int set;

  23.     set = sht2x_open();
  24.     if( set < 0){
  25.         printf("initial sht20 failure.\n");
  26.         return -1;
  27.     }

  28.     while( count_run > 0){
  29.                                 set = sht2x_get_tempeture( &temper );
  30.                                 if(set > -1)
  31.                                 {
  32.                                                 printf( "TM(C):  %.2f ", temper*0.01);
  33.                                 }

  34.                                 set = sht2x_get_humidy( &rh );
  35.                                 if(set > -1)
  36.                                 {
  37.                                           printf("HM(\%): %.2f \r\n", rh*0.01);
  38.                                 }
  39.                                 count_run--;
  40.     }

  41.         sht2x_release();

  42.     return 0;
  43. }
复制代码
2)Makefile文件
  1. CFLAGS= -Wall -O2
  2. CC=arm-linux-gcc


  3. test-sht20: test-sht20.o drv-sht20.o
  4.         $(CC) $(CFLAGS) -o test-sht20 test-sht20.o drv-sht20.o
  5.         arm-linux-strip -s test-sht20

  6. clean:
  7.         rm -f test-sht20 test-sht20.o drv-sht20.o
复制代码

3 测试实验编译代码,通过NFS传送到开发板上




1704784505972.png


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 12:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表