找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3551|回复: 0
打印 上一主题 下一主题
收起左侧

SHT10传感器+LCD1602显示的单片机源程序

[复制链接]
跳转到指定楼层
楼主
ID:269159 发表于 2017-12-30 13:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
几点说明:
1.主要是分以下几个模块写的:SHT10,LCD1602,主函数,头文件。
2.每支SHTxx传感器都在25℃(77 °F)和 3.3V条件下进行过标定并且完全符合精度指标.因为考虑到实际硬件5V的电压比较好操作,所以SHT10用的精度采用的为5V时的参数。其他的都采取默认值(14bit湿度 , 12bit 温度)。
3.SHT10中所以部分我都编写了。有的部分在本次程序中没用到,也可以作为参考。
4.所有程序都已经加了注释,且有仿真图。
5.个人认为还可以在此基础上添加个中断。
6.程序编写keil 4 ,仿真 protues7.5


头文件(tou.h)
  1. #ifndef __TOU_H__
  2. #define __TOU_H__

  3. #include<reg52.h>
  4. #include <intrins.h>
  5. //#include <math.h>    //Keil library

  6. #define uchar unsigned char
  7. enum {TEMP,HUMI};

  8. sbit DATA = P1^7;
  9. sbit SCK = P1^6;

  10. sbit LcdRs = P2^4;
  11. sbit LcdRw = P2^5;
  12. sbit LcdEn = P2^6;
  13. sfr DBPort = 0x80;     //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口

  14. /********     DS1602函数声明     ********/
  15. void LCD_Initial();
  16. void GotoXY(unsigned char x, unsigned chary);
  17. void Print(unsigned char *str);
  18. void LCD_Write(bit style, unsigned charinput);


  19. /********     SHT10函数声明      ********/
  20. void s_connectionreset(void);
  21. char s_measure(unsigned char *p_value,unsigned char *p_checksum, unsigned char mode);
  22. void calc_sth10(float *p_humidity ,float*p_temperature);
  23. //float calc_dewpoint(float h,float t);


  24. #endif
  25. /***********************************************************************************************************************************************************/
复制代码


SHT10程序(SHT10.c):

  1. #include<tou.h>
  2. #define noACK 0                         //继续传输数据,用于判断是否结束通讯
  3. #define ACK   1            //结束数据传输;
  4.                                                  //地址 命令  读/写
  5. #define STATUS_REG_W 0x06   //000  0011    0
  6. #define STATUS_REG_R 0x07   //000  0011    1
  7. #define MEASURE_TEMP 0x03   //000  0001    1
  8. #define MEASURE_HUMI 0x05   //000  0010    1
  9. #define RESET        0x1e  //000   1111    0



  10. //写字节程序
  11. char s_write_byte(unsigned char value)   
  12. {
  13.        unsignedchar i,error=0;
  14.        for(i=0x80;i>0;i>>=1)            //高位为1,循环右移
  15.        {
  16.               if(i&value) DATA=1;          //和要发送的数相与,结果为发送的位
  17.            else DATA=0;                        
  18.            SCK=1;                          
  19.            _nop_();_nop_();_nop_();        //延时3us
  20.            SCK=0;
  21.        }
  22.        DATA=1;                           //释放数据线
  23.        SCK=1;                           
  24.        error=DATA;                       //检查应答信号,确认通讯正常
  25.        _nop_();_nop_();_nop_();
  26.        SCK=0;        
  27.        DATA=1;
  28.        returnerror;                     //error=1 通讯错误
  29. }

  30. //读字节程序
  31. char s_read_byte(unsigned char ack)
  32. //----------------------------------------------------------------------------------
  33. {
  34.        unsignedchar i,val=0;
  35.        DATA=1;                           //释放数据线
  36.        for(i=0x80;i>0;i>>=1)             //高位为1,循环右移
  37.        {
  38.               SCK=1;                        
  39.            if(DATA) val=(val|i);        //读一位数据线的值
  40.            SCK=0;      
  41.        }
  42.        DATA=!ack;                        //如果是校验,读取完后结束通讯;
  43.        SCK=1;                           
  44.        _nop_();_nop_();_nop_();          //延时3us
  45.        SCK=0;   
  46.        _nop_();_nop_();_nop_();      
  47.        DATA=1;                           //释放数据线
  48.        returnval;
  49. }

  50. //启动传输
  51. void s_transstart(void)
  52. // generates a transmission start
  53. //      _____         ________
  54. // DATA:      |_______|
  55. //          ___     ___
  56. // SCK : ___|   |___|  |______
  57. {
  58.      DATA=1; SCK=0;                   //准备
  59.      _nop_();
  60.       SCK=1;
  61.      _nop_();
  62.      DATA=0;
  63.      _nop_();
  64.       SCK=0;
  65.        _nop_();_nop_();_nop_();
  66.      SCK=1;
  67.      _nop_();
  68.       DATA=1;   
  69.       _nop_();
  70.      SCK=0;   
  71. }


  72. //连接复位
  73. void s_connectionreset(void)
  74. // communication reset: DATA-line=1 and atleast 9 SCK cycles followed by transstart
  75. //      _____________________________________________________         ________
  76. // DATA:                                                     |_______|
  77. //         _    _    _   _    _    _   _    _    _       ___     ___
  78. // SCK : __| |__| |__| |__| |__| |__| |__||__| |__| |______|   |___|   |______
  79. {
  80.        unsignedchar i;
  81.        DATA=1;SCK=0;                    //准备
  82.        for(i=0;i<9;i++)                  //DATA保持高,SCK时钟触发9次,发送启动传输,通迅即复位
  83.        {
  84.               SCK=1;
  85.            SCK=0;
  86.        }
  87.        s_transstart();                   //启动传输
  88. }


  89. //软复位程序
  90. char s_softreset(void)
  91. // resets the sensor by a softreset
  92. {
  93.        unsignedchar error=0;
  94.        s_connectionreset();              //启动连接复位
  95.        error+=s_write_byte(RESET);       //发送复位命令
  96.        returnerror;                     //error=1 通讯错误
  97. }


  98. /*读状态寄存器
  99. char s_read_statusreg(unsigned char*p_value, unsigned char *p_checksum)
  100. //----------------------------------------------------------------------------------
  101. // reads the status register with checksum(8-bit)
  102. {
  103.        unsignedchar error=0;
  104.        s_transstart();                   //transmission start
  105.        error=s_write_byte(STATUS_REG_R);//send command to sensor
  106.        *p_value=s_read_byte(ACK);        //read status register (8-bit)
  107.        *p_checksum=s_read_byte(noACK);   //read checksum (8-bit)
  108.        returnerror;                     //error=1 in case of no response form the sensor
  109. }

  110. //写状态寄存器
  111. char s_write_statusreg(unsigned char*p_value)
  112. // writes the status register with checksum(8-bit)
  113. {
  114.        unsignedchar error=0;
  115.        s_transstart();                   //transmission start
  116.        error+=s_write_byte(STATUS_REG_W);//sendcommand to sensor
  117.        error+=s_write_byte(*p_value);    //send value of status register
  118.        returnerror;                     //error>=1 in case of no response form the sensor
  119. }                                                                                                                               */

  120. //温湿度测量
  121. char s_measure(unsigned char *p_value,unsigned char *p_checksum, unsigned char mode)
  122. // 进行温度或者湿度转换,由参数mode决定转换内容;
  123. {
  124. //     enum{TEMP,HUMI};           //已经在头文件中定义
  125.        unsignederror=0;
  126.        unsignedint i;

  127.        s_transstart();                   //启动传输
  128.        switch(mode)                     //选择发送命令
  129.     {     
  130.               caseTEMP : error+=s_write_byte(MEASURE_TEMP); break;             //测量温度
  131.            case HUMI :error+=s_write_byte(MEASURE_HUMI); break;              //测量湿度
  132.            default     : break;
  133.        }
  134.        for(i=0;i<65535;i++) if(DATA==0) break; //等待测量结束
  135.        if(DATA)error+=1;                // 如果长时间数据线没有拉低,说明测量错误
  136.        *(p_value)=s_read_byte(ACK);    //读第一个字节,高字节 (MSB)
  137.        *(p_value+1)=s_read_byte(ACK);    //读第二个字节,低字节 (LSB)
  138.        *p_checksum=s_read_byte(noACK); //read CRC校验码
  139.        returnerror;                                 //error=1 通讯错误
  140. }

  141. //温湿度值标度变换及温度补偿
  142. void calc_sth10(float *p_humidity ,float*p_temperature)
  143. {
  144.        constfloat C1=-4.0;              // 12位湿度精度 修正公式
  145.        constfloat C2=+0.0405;           // 12位湿度精度 修正公式
  146.        constfloat C3=-0.0000028;        // 12位湿度精度 修正公式
  147.        constfloat T1=+0.01;             // 14位温度精度 5V条件 修正公式
  148.        constfloat T2=+0.00008;          // 14位温度精度 5V条件 修正公式

  149.        floatrh=*p_humidity;             // rh:      12位湿度
  150.        floatt=*p_temperature;           // t:       14位温度
  151.        floatrh_lin;                     // rh_lin: 湿度 linear值
  152.        floatrh_true;                    // rh_true: 湿度 ture值
  153.        floatt_C;                        // t_C   : 温度℃

  154.        t_C=t*0.01- 40;                  //补偿温度
  155.        rh_lin=C3*rh*rh+ C2*rh + C1;     //相对湿度非线性补偿
  156.        rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;   //相对湿度对于温度依赖性补偿
  157.        if(rh_true>100)rh_true=100;       //湿度最大修正
  158.        if(rh_true<0.1)rh_true=0.1;       //湿度最小修正

  159.        *p_temperature=t_C;               //返回温度结果
  160.        *p_humidity=rh_true;              //返回湿度结果
  161. }

  162. //从相对温度和湿度计算露点
  163. /*float calc_dewpoint(float h,float t)
  164. {
  165.        floatlogEx,dew_point;
  166.        logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2);
  167.        dew_point= (logEx - 0.66077)*237.3/(0.66077+7.5-logEx);
  168.        returndew_point;
  169. }                                                                         */

  170. /***********************************************************************************************************************************************************/
复制代码


DS1602程序(1602.c):

  1. #include<tou.h>

  2. //内部等待函数**************************************************************
  3. unsigned char LCD_Wait(void)
  4. {
  5.    LcdRs=0;
  6.    LcdRw=1;    _nop_();
  7.    LcdEn=1;    _nop_();           
  8.    LcdEn=0;
  9.    return DBPort;  
  10. }
  11. //向LCD写入命令或数据********************************************************
  12. #define LCD_COMMAND         0     // Command
  13. #define LCD_DATA            1      // Data
  14. #define LCD_CLEAR_SCREEN    0x01     // 清屏
  15. #define LCD_HOMING          0x02      // 光标返回原点
  16. void LCD_Write(bit style, unsigned charinput)
  17. {
  18.    LcdEn=0;
  19.    LcdRs=style;
  20.    LcdRw=0;        _nop_();
  21.    DBPort=input;   _nop_();//注意顺序
  22.    LcdEn=1;        _nop_();//注意顺序
  23.    LcdEn=0;        _nop_();
  24.    LCD_Wait();
  25. }

  26. //设置显示模式************************************************************
  27. #define LCD_SHOW            0x04    //显示开
  28. #define LCD_HIDE            0x00    //显示关

  29. #define LCD_CURSOR          0x02    //显示光标
  30. #define LCD_NO_CURSOR       0x00   //无光标        

  31. #define LCD_FLASH           0x01    //光标闪动
  32. #define LCD_NO_FLASH        0x00   //光标不闪动

  33. void LCD_SetDisplay(unsigned charDisplayMode)
  34. {
  35.    LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
  36. }

  37. //设置输入模式************************************************************
  38. #define LCD_AC_UP       0x02
  39. #define LCD_AC_DOWN         0x00      // default

  40. #define LCD_MOVE            0x01      // 画面可平移
  41. #define LCD_NO_MOVE         0x00      //default

  42. void LCD_SetInput(unsigned char InputMode)
  43. {
  44.    LCD_Write(LCD_COMMAND, 0x04|InputMode);
  45. }

  46. //初始化LCD************************************************************
  47. void LCD_Initial()
  48. {
  49.    LcdEn=0;
  50.    LCD_Write(LCD_COMMAND,0x38);          //8位数据端口,2行显示,5*7点阵
  51.    LCD_Write(LCD_COMMAND,0x38);
  52.    LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);    //开启显示, 无光标
  53.    LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏
  54.    LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);       //AC递增, 画面不动
  55. }

  56. //液晶字符输入的位置************************
  57. void GotoXY(unsigned char x, unsigned chary)
  58. {
  59.    if(y==0)
  60.        LCD_Write(LCD_COMMAND,0x80|x);
  61.    if(y==1)
  62.        LCD_Write(LCD_COMMAND,0x80|(x-0x40));
  63. }

  64. //将字符输出到液晶显示
  65. void Print(unsigned char *str)
  66. {
  67.    while(*str!='\0')
  68.     {
  69.        LCD_Write(LCD_DATA,*str);
  70.        str++;
  71.     }
  72. }

  73. /***********************************************************************************************************************************************************/
复制代码


主函数(main.c):

  1. #include<tou.h>

  2. typedef union                             //定义共用同类型
  3. {     
  4.        unsignedint i;
  5.        floatf;
  6. } value;

  7. //延时函数
  8. void delay(int z)            //z为毫秒数
  9. {
  10.        intx,y;
  11.        for(x=z;x>0;x--)
  12.               for(y=125;y>0;y--);
  13. }


  14. void main()
  15. {
  16.        unsignedint temp,humi;
  17.        valuehumi_val,temp_val;             //定义两个共同体,一个用于湿度,一个用于温度
  18. //     floatdew_point;                       //用于记录露点值
  19.        unsignedchar error;                 //用于检验是否出现错误
  20.        unsignedchar checksum;                    //CRC                    
  21.        ucharwendu[6];                               //用于记录温度
  22.        ucharshidu[6];                                 //用于记录湿度


  23.        LCD_Initial();                                //初始化液晶            
  24.      GotoXY(0,0);                                //选择温度显示位置
  25.      Print("TEMP:     %C");                      //5格空格
  26.    GotoXY(0,1);                                //选择湿度显示位置
  27.      Print("HUMI:     %RH");                     //5格空格
  28.        s_connectionreset();                       //启动连接复位
  29.        while(1)
  30.        {
  31.               error=0;                                 //初始化error=0,即没有错误
  32.               error+=s_measure((unsignedchar*)&temp_val.i,&checksum,TEMP); //温度测量
  33.               error+=s_measure((unsignedchar*)&humi_val.i,&checksum,HUMI); //湿度测量
  34.            if(error!=0) s_connectionreset();                 ////如果发生错误,系统复位
  35.            else
  36.            {
  37.                      humi_val.f=(float)humi_val.i;                   //转换为浮点数
  38.                  temp_val.f=(float)temp_val.i;                   //转换为浮点数
  39.                  calc_sth10(&humi_val.f,&temp_val.f);            //修正相对湿度及温度
  40. //                 dew_point=calc_dewpoint(humi_val.f,temp_val.f);//计算e dew_point
  41.                    temp=temp_val.f*10;
  42.                  humi=humi_val.f*10;
  43.                  GotoXY(5,0);                                    //设置温度显示位置
  44.                 wendu[0]=temp/1000+'0';               //温度百位
  45.                 wendu[1]=temp%1000/100+'0';       //温度十位     
  46.                    wendu[2]=temp%100/10+'0';                     //温度个位
  47.                 wendu[3]=0x2E;                                       //小数点
  48.                    wendu[4]=temp%10+'0';                            //温度小数点后第一位         
  49.                      Print(wendu);                                    //输出温度            
  50.                   GotoXY(5,1);                                    //设置湿度显示位置                                 
  51.                      shidu[0]=humi/1000+'0';                 //湿度百位
  52.                 shidu[1]=humi%1000/100+'0';         //湿度十位     
  53.                    shidu[2]=humi%100/10+'0';                //湿度个位
  54.                 shidu[3]=0x2E;                                         //小数点
  55.                    shidu[4]=humi%10+'0';                       //湿度小数点后第一位  
  56.                      Print(shidu);                                      //输出湿度        
  57.            }  
  58.               delay(800);                             //等待足够长的时间,以现行下一次转换                    
  59.        }
  60. }

  61. /***********************************************************************************************************************************************************/
复制代码


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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