⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sht11.c

📁 基于单片机AT89C52的温湿度传感器显示程序
💻 C
字号:
#include <REG52.H>
#include "intrins.h"      /*Keil library (is used for _nop()_ operation)*/ 
#include "math.h"         /*Keil library*/ 
#include "stdio.h"        /*Keil library*/
#include "absacc.h"

#define ACK 1
#define noACK 0
#define measure_temp 0x03 //测量温度命令 
#define measure_humi 0x05 //测量湿度命令 
#define RESET        0x1e //软启动 

#define     uchar    unsigned   char
#define     uint     unsigned   int
#define     ulong    unsigned   long
#define     LCD_DATA P0 //数据口  

sbit   DATA=P1^0;
sbit   SCK=P1^1;
sbit   RS = P2^0; //并行的指令/数据选择信号, H数据, L命令
sbit   RW = P2^1; //并行读写选择信号, H读, L写
sbit   E =  P2^2;  //并行使能端, H有效, L无效
sbit   LED=P3^7; 

typedef union                      /*保存所测得的温度&湿度值*/
{ uint  i;
  float f;
} value;

typedef struct __SYSTEMTIME__
{
	unsigned char gewei;
	unsigned char shiwei;
	unsigned char DateString1[5];
    unsigned char DateString2[6];
}SYSTEMTIME;

char write_byte(unsigned char value)
// writes a byte on the Sensibus and checks the acknowledge 
{ 
  unsigned char i,error=0;  
  for(i=0x80;i>0;i/=2)             /*连续向右移动8位*/
  { 
    if (i & value) DATA=1;          /*把相应的位送数据线 */
    else DATA=0;                        
    SCK=1;                          /*时序脉冲,应严格按着此标准 */
    _nop_();
    _nop_();
    _nop_();                        /*大约0.5us*/	
    SCK=0;
  }
  DATA=1;                           /*释放数据线 */
  SCK=1;                            /*第9位作为响应位*/
  error=DATA;                       /*检测响应情况,如果有响应数据线就会被SHT10拉低*/
  SCK=0;        
  return error;                     /*返回1表示没响应*/
}

char read_byte(unsigned char ack)
{ 
  unsigned char i,val=0;
  DATA=1;                           /*释放数据线 */
  for (i=0x80;i>0;i/=2)             /*连续向右移动8位*/
  { SCK=1;                          /*clk for SENSI-BUS*/
    if (DATA) val=(val | i);        /*read bit */ 
    SCK=0;  					 
  }
  DATA=!ack;                        /*当ack=1时拉低数据线*/
  SCK=1;                            /*clk #9 for ack*/
  _nop_();_nop_();_nop_();          /*pulswith approx. 5 us */
  SCK=0;						    
  DATA=1;                           /*释放数据线*/
  return val;
}

void transstart(void)
{
    DATA=1; 
    SCK=0;                   //初始状态
    _nop_();
    SCK=1;
    _nop_();
    DATA=0;
    _nop_();
    SCK=0;
    _nop_();_nop_();_nop_();
    SCK=1;
    _nop_();
    DATA=1;
	_nop_();
    SCK=0;
}

void connectionreset(void)//复位:当DATA线处于高低平时,触发SCK9次以上(含9次),此后应接发一个"传输开始"命令 
{  
  unsigned char i; 
  DATA=1; SCK=0;                    /*Initial state*/
  for(i=0;i<9;i++)                  /*9 SCK cycles*/
  { 
    SCK=1;
    SCK=0;
  }
  transstart();                   /*transmission start*/
}

char softreset(void)              //重启芯片,清除状态记录器的错误记录

/*resets the sensor by a softreset*/ 
{ 
  unsigned char error=0;  
  connectionreset();              /*reset communication*/
  error+=write_byte(RESET);       /*向传感器发送复位命令*/
  return error;                     /*error=1 in case of no response form the sensor*/
}

char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)

/*makes a measurement (humidity/temperature) with checksum*/ 
{ 
  unsigned error=0;
  unsigned int i;

  transstart();                   /*transmission start*/
  switch(mode){                     /*send command to sensor*/
    case 0	: error+=write_byte(measure_temp); break;
    case 1	: error+=write_byte(measure_humi); break;
    default     : break;	 
  }
  for (i=0;i<65535;i++) if(DATA==0) break; /*wait until sensor has finished the measurement*/
  if(DATA) error+=1;                       /*or timeout (~2 sec.) is reached*/ 
  *(p_value)  =read_byte(ACK);           /*read the first byte (MSB)*/
  *(p_value+1)=read_byte(ACK);           /*read the second byte (LSB)*/
  *p_checksum =read_byte(noACK);         /*read checksum*/
  return error;
}

//温湿度值标度变换及温度补偿
void calc_sth11(float *p_humidity ,float *p_temperature)      
{ const float C1=-4.0;              /*for 12 Bit*/ 
  const float C2=+0.0405;           /*for 12 Bit*/ 
  const float C3=-0.0000028;        /*for 12 Bit*/ 
  const float T1=+0.01;             /*for 14 Bit @ 5V*/ 
  const float T2=+0.00008;           /*for 14 Bit @ 5V*/ 	

  float rh=*p_humidity;             /*rh:      Humidity [Ticks] 12 Bit */ 
  float t=*p_temperature;           /**t:       Temperature [Ticks] 14 Bit*/ 
  float rh_lin;                     /*rh_lin:  Humidity linear*/ 
  float rh_true;                    /*rh_true: Temperature compensated humidity*/ 
  float t_C;                        /*t_C   :  Temperature [癈]*/ 

  t_C=t*0.01 - 40;                     /*calc. temperature from ticks to [癈]*/
  rh_lin=C3*rh*rh + C2*rh + C1;        /*calc. humidity from ticks to [%RH]*/
  rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;  /*calc. temperature compensated humidity [%RH]*/
  if(rh_true>100)rh_true=100;          /*cut if the value is outside of*/
  if(rh_true<0.1)rh_true=0.1;          /*the physical possible range*/

  *p_temperature=t_C;                  /*return temperature [癈]*/
  *p_humidity=rh_true;                 /*return humidity[%RH]*/
}


void init_uart()  //串口传输初始化 :19200 bps @ 11.059 MHz TMOD = 0x01	
{
 SCON  = 0x52;    
 TMOD  = 0x21;    
 TCON  = 0x69;	  
 TH1   = 0xfd;    
 TH0   = 0xFC;
 TL0   = 0x17;
 IE    = 0x82;
 TR0   = 1;
}
/*************************************************************************************/
//延时约2us
void delayUs()
{
    _nop_();_nop_();
}
//延时 a * 1ms
void delayMs(uint a)
{
    uint i, j;
    for(i = a; i > 0; i--)
        for(j = 100; j > 0; j--);
}

//检测LCD是否处于忙状态, 若忙返回1, 空闲返回0
bit checkBusy()
{
    bit busy;
    RS = 0;
    RW = 1;
    E = 1;
    delayUs();
    busy = (bit)(LCD_DATA&0x80);
    E = 0;
    return busy;
}

//等待LCD到空闲
void wait()
{
    while(checkBusy());
}

//写命令
void writeCmd(uchar cmd)
{
    wait();
    RS = 0;
    RW = 0;
    E = 0;
    delayUs();
    LCD_DATA = cmd;
    delayUs();
    E = 1;
    delayUs();
    E = 0;
}

//写数据
void writeData(uchar dat)
{
    wait();
    RS = 1;
    RW = 0;
    E = 0;
    delayUs();
    LCD_DATA = dat;
    delayUs();
    E = 1;
    delayUs();
    E = 0;
}

//初始化LCD
void init()
{
    //PSB = 1; //并口方式
    writeCmd(0x30); //基本指令, 扩充指令为34H
    delayMs(10);
    writeCmd(0x0c); //显示开, 关光标
    delayMs(10);
    writeCmd(0x01); //清屏
    delayMs(10);
}

void setPosition(uchar x, uchar y)
{
    uchar p;
    switch(x%4)
    {
        case 0: p = 0x80; break; //第一行开始地址
        case 1: p = 0x90; break; //第二行
        case 2: p = 0x88; break; //第三行
        case 3: p = 0x98; break; //第四行
    }
    p += y;
    writeCmd(p);
}

void DateToStr(SYSTEMTIME *Time,float datax,float datax1)
{
	uint i;
    i=(int)datax;
	Time->shiwei=i/10;
	Time->gewei =i%10;
    Time->DateString1[0] = Time->shiwei + '0';
	Time->DateString1[1] = Time->gewei + '0';
	i=(int)((datax-i)*10); 
	Time->DateString1[2] ='.';
	Time->DateString1[3] = i + '0';
	Time->DateString1[4] = '\0';

    i=(int)datax1;
	Time->shiwei=i/10;
	Time->gewei =i%10;
    Time->DateString2[0] = Time->shiwei + '0';
	Time->DateString2[1] = Time->gewei + '0';
	i=(int)((datax1-i)*10); 
	Time->DateString2[2] ='.';
	Time->DateString2[3] = i + '0';
	Time->DateString2[4] = '%';
	Time->DateString2[5] = '\0';
}

void writeString(uchar * str)
{
    uchar i = 0;
    while(str[i] != '\0')
    {
        writeData(str[i++]);
    }
}
/*********************************************************************/

void main(void)
{
   SYSTEMTIME S;
   uchar time_str1[]={"北京温度:"};
   uchar time_str2[]={"北京湿度:"};
   value humi_val,temp_val;
   unsigned char error,checksum;
   unsigned int i;
   init_uart();
   connectionreset();
   init();
   setPosition(0,0);
   writeString(time_str1);
   setPosition(2,0);
   writeString(time_str2);
   while(1)
   {
      LED=0;	  
      error=0;
      error+=s_measure((unsigned char*) &humi_val.i,&checksum,1);   /*measure humidity*/
      error+=s_measure((unsigned char*) &temp_val.i,&checksum,0);   /*measure temperature*/
      if(error!=0) 
	     connectionreset();                                /*in case of an error:connection reset*/
      else
      { 
         humi_val.f=(float)humi_val.i;                     /*converts integer to float*/
         temp_val.f=(float)temp_val.i;                     /*converts integer to float*/
         calc_sth11(&humi_val.f,&temp_val.f);              /*calculate humidity,temperature*/
         DateToStr(&S,temp_val.f,humi_val.f);		                  
         setPosition(0,5);
         writeString(S.DateString1);         
         setPosition(2,5);
         writeString(S.DateString2);
     }
     /*----------wait approx. 0.8s to avoid heating up SHT10------------------------------ */      
     for (i=0;i<10000;i++);     //(be sure that the compiler doesn't eliminate this line!)
     /*----------------------------------------------------------------------------------- */                    
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -