SHT11温湿度仿真,自己拿去用
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
流程图:
单片机源程序如下:
- #include<reg51.h>
- #include <intrins.h>
- #include <math.h>
- #include <stdio.h>
- #define LCD_DB P0
- sbit LCD_RS=P2^0;
- sbit LCD_RW=P2^1;
- sbit LCD_E=P2^2;
- sbit beep = P1^7;
- sbit key1 = P3^0;
- sbit key2 = P3^1;
- sbit key3 = P3^2;
- sbit key4 = P3^3;
- unsigned char Time; //用来存放定时时间
- unsigned char Second;
- unsigned char w; //标志位
- unsigned char wendumode = 0;
- unsigned char shidumode = 0;
- unsigned char wenduCB = 40;
- unsigned char shiduCB = 100;
- unsigned int wendu,shidu;
- /******定义函数****************/
- #define uchar unsigned char
- #define uint unsigned int
- void LCD_init(void); //初始化函数
- void LCD_write_command(uchar command); //写指令函数
- void LCD_write_data(uchar dat); //写数据函数
- void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)
- void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602显示字符串函数
- void delay_n10us(uint n); //延时函数
- void kcankey()
- {
- if(key1==0)
- {
- delay_n10us(1000);
- if(key1==0)
- {
- wendumode = 1;
- shidumode = 0;
- }
- }
- if(key2==0)
- {
- delay_n10us(1000);
- if(key2==0)
- {
- wendumode = 0;
- shidumode = 1;
- }
- }
- if(wendumode==1)
- {
- if(key3==0)
- {
- delay_n10us(1000);
- if(key3==0)
- {
- wenduCB++;
- }
- }
- if(key4==0)
- {
- delay_n10us(1000);
- if(key4==0)
- {
- wenduCB--;
- }
- }
- }
- if(shidumode==1)
- {
- if(key3==0)
- {
- delay_n10us(1000);
- if(key3==0)
- {
- shiduCB++;
- }
- }
- if(key4==0)
- {
- delay_n10us(1000);
- if(key4==0)
- {
- shiduCB--;
- }
- }
- }
- if(wendu>=wenduCB*10)
- {
- beep = 1;
- }
- if(shidu>=shiduCB*10)
- {
- beep = 1;
- }
- if(wendu<wenduCB*10&&shidu<shiduCB*10)
- {
- beep = 0;
- }
- }
- void LCD_init(void)
- {
- delay_n10us(10);
- LCD_write_command(0x38);//设置8位格式,2行,5x7
- delay_n10us(10); LCD_write_command(0x0c);//开显示,关光标,不闪烁
- delay_n10us(10); LCD_write_command(0x06);//设定输入方式,增量不移位
- delay_n10us(10); LCD_write_command(0x01);//清除屏幕显示
- delay_n10us(100); //延时清屏,延时函数,延时约n个10us
- }
- void LCD_write_command(uchar dat)
- {
- delay_n10us(10);
- LCD_RS=0; //指令
- LCD_RW=0; //写入
- LCD_E=1; //允许
- LCD_DB=dat; delay_n10us(10); //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
- LCD_E=0; delay_n10us(10); //实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。
- }
- void LCD_write_data(uchar dat)
- {
- delay_n10us(10);
- LCD_RS=1; //数据
- LCD_RW=0; //写入
- LCD_E=1; //允许
- LCD_DB=dat; delay_n10us(10);
- LCD_E=0; delay_n10us(10);
- }
- void LCD_disp_char(uchar x,uchar y,uchar dat)
- {
- uchar address;
- if(y==1)
- address=0x80+x;
- else
- address=0xc0+x;
- LCD_write_command(address);
- LCD_write_data(dat);
- }
- void LCD_disp_str(uchar x,uchar y,uchar *str)
- {
- uchar address;
- if(y==1)
- address=0x80+x;
- else
- address=0xc0+x;
- LCD_write_command(address);
- while(*str!='\0')
- {
- LCD_write_data(*str);
- str++;
- }
- }
- void delay_n10us(uint n) //延时n个10us@12M晶振
- {
- uint i;
- for(i=n;i>0;i--)
- {
- nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
- }
- }
- sbit SCK = P2^6; //定义通讯时钟端口
- sbit DATA = P2^7; //定义通讯数据端口
- typedef union
- { unsigned int i; //定义了两个共用体
- float f; } value;
- enum {TEMP,HUMI}; //TEMP=0,HUMI=1
- #define noACK 0 //用于判断是否结束通讯
- #define ACK 1 //结束数据传输 //adr command r/w
- #define STATUS_REG_W 0x06 //000 0011 0
- #define STATUS_REG_R 0x07 //000 0011 1
- #define MEASURE_TEMP 0x03 //000 0001 1
- #define MEASURE_HUMI 0x05 //000 0010 1
- #define RESET 0x1e //000 1111 0
- /****************定义函数****************/
- void s_transstart(void); //启动传输函数
- void s_connectionreset(void); //连接复位函数
- char s_write_byte(unsigned char value);//DHT90写函数
- char s_read_byte(unsigned char ack); //DHT90读函数
- char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);//测量
- void calc_dht90(float *p_humidity ,float *p_temperature);//温湿度补偿
- void s_transstart(void) // generates a transmission start
- {
- DATA=1; SCK=0; //Initial state
- _nop_();
- SCK=1;
- _nop_();
- DATA=0;
- _nop_();
- SCK=0;
- _nop_();_nop_();_nop_();
- SCK=1;
- _nop_();
- DATA=1;
- _nop_();
- SCK=0;
- }
- void s_connectionreset(void) // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
- {
- unsigned char i;
- DATA=1;
- SCK=0; //Initial state
- for(i=0;i<9;i++) //9 SCK cycles
- {
- SCK=1;
- SCK=0;
- }
- s_transstart(); //transmission start
- }
- char s_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) //shift bit for masking
- {
- if (i & value) DATA=1; //masking value with i , write to SENSI-BUS
- else DATA=0;
- SCK=1; //clk for SENSI-BUS
- _nop_();_nop_();_nop_(); //pulswith approx. 3 us
- SCK=0;
- }
- DATA=1; //release DATA-line
- SCK=1; //clk #9 for ack
- error=DATA; //check ack (DATA will be pulled down by DHT90),DATA在第9个上升沿将被DHT90自动下拉为低电平。
- _nop_();_nop_();_nop_();
- SCK=0;
- DATA=1; //release DATA-line
- return error; //error=1 in case of no acknowledge //返回:0成功,1失败
- }
- char s_read_byte(unsigned char ack) // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
- {
- unsigned char i,val=0;
- DATA=1; //release DATA-line
- for (i=0x80;i>0;i/=2) //shift bit for masking
- {
- SCK=1; //clk for SENSI-BUS
- if (DATA) val=(val | i); //read bit
- _nop_();_nop_();_nop_(); //pulswith approx. 3 us
- SCK=0;
- }
- if(ack==1)
- DATA=0; //in case of "ack==1" pull down DATA-Line
- else DATA=1; //如果是校验(ack==0),读取完后结束通讯
- _nop_();_nop_();_nop_(); //pulswith approx. 3 us
- SCK=1; //clk #9 for ack
- _nop_();_nop_();_nop_(); //pulswith approx. 3 us
- SCK=0;
- _nop_();_nop_();_nop_(); //pulswith approx. 3 us
- DATA=1; //release DATA-line
- return val;
- }
- 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;
- s_transstart(); //transmission start
- switch(mode){ //send command to sensor
- case TEMP : error+=s_write_byte(MEASURE_TEMP); break;
- case HUMI : error+=s_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) =s_read_byte(ACK); //read the first byte (MSB)
- *(p_value+1)=s_read_byte(ACK); //read the second byte (LSB)
- *p_checksum =s_read_byte(noACK); //read checksum
- return error;
- }
- void calc_dht90(float *p_humidity ,float *p_temperature)
- // calculates temperature [C] and humidity [%RH]
- // input : humi [Ticks] (12 bit)
- // temp [Ticks] (14 bit)
- // output: humi [%RH]
- // temp [C]
- { 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 [C]
- t_C=t*0.01 - 40; //calc. temperature from ticks to [C]
- 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 [C]
- *p_humidity=rh_true; //return humidity[%RH]
- }
-
- //*********主函数*****************
- void main(void)
- {
- value humi_val,temp_val;
- unsigned char error,checksum;
- LCD_init();
- s_connectionreset();
- beep = 0;
- LCD_disp_str(0,1,"TE CB:");
- LCD_disp_str(0,2,"RH CB:");
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
温湿度仿真.zip
(111.44 KB, 下载次数: 201)
|