一、基础功能
利用SHT11测量温湿度,具体代码如下:
//温湿度测量
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
{
unsigned error=0;
unsigned int i;
s_transstart();
switch(mode)
{
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;
if(DATA) error+=1;
*(p_value) =s_read_byte(ACK);
*(p_value+1)=s_read_byte(ACK);
*p_checksum =s_read_byte(noACK);
return error;
}
//温湿度标度值变换及温度补偿
void calc_sth10(float *p_humidity ,float *p_temperature)
{
const float C1=-4.0;
const float C2=+0.0405;
const float C3=-0.0000028;
const float T1=+0.01;
const float T2=+0.00008;
float rh=*p_humidity;
float t=*p_temperature;
float rh_lin;
float rh_true;
float t_C;
t_C=t*0.01 - 40;
rh_lin=C3*rh*rh + C2*rh + C1;
rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;
if(rh_true>100)rh_true=100;
if(rh_true<0.1)rh_true=0.1;
*p_temperature=t_C;
*p_humidity=rh_true;
}
测量后需在LCD上显示具体读数,具体代码如下:
//向LCD写入数据或命令
#define LCD_COMMAND 0
#define LCD_DATA 1
#define LCD_CLEAR_SCREEN 0x01
#define LCD_HOMING 0x02
void LCD_Write(bit style, unsigned char input)
{
E=0;
RS=style;
RW=0; _nop_();
DBPort=input; _nop_();
E=1; _nop_();
E=0; _nop_();
LCD_Wait();
}
//设置显示模式
#define LCD_SHOW 0x04
#define LCD_HIDE 0x00
#define LCD_CURSOR 0x02
#define LCD_NO_CURSOR 0x00
#define LCD_FLASH 0x01
#define LCD_NO_FLASH 0x00
void LCD_SetDisplay(unsigned char DisplayMode)
{
LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
}
//设置输入模式
#define LCD_AC_UP 0x02
#define LCD_AC_DOWN 0x00
#define LCD_MOVE 0x01
#define LCD_NO_MOVE 0x00
void LCD_SetInput(unsigned char InputMode)
{
LCD_Write(LCD_COMMAND, 0x04|InputMode);
}
//初始化LCD
void LCD_Initial()
{
E=0;
LCD_Write(LCD_COMMAND,0x38);
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);
}
//液晶字符输入位置
void GotoXY(unsigned char x, unsigned char y)
{
if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}
//将字符输出到液晶显示
void Print(unsigned char *str)
{
while(*str!='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
温湿度输出代码:
//输出温度
TEMP1[0]=temp/1000+'0'; //温度百分位
if (TEMP1[0]==0x30) TEMP1[0]=0x20;
TEMP1[1]=temp%1000/100+'0'; //十位
if (TEMP1[1]==0x30 && TEMP1[0]!=0x30) TEMP1[1]=0x20;
TEMP1[2]=temp%100/10+'0'; //个位
TEMP1[5]=0xdf; //温度符号
Print(TEMP1);
//输出湿度
HUMI1[0]=humi/1000+'0'; //湿度百位
if (HUMI1[0]==0x30) HUMI1[0]=0x20;
HUMI1[1]=humi%1000/100+'0'; //湿度十位
if (HUMI1[1]==0x30 && HUMI1[0]!=0x30) HUMI1[1]=0X20;
HUMI1[2]=humi%100/10+'0'; //湿度个位
Print(HUMI1);
二、改进
在实际生活中我们对温湿度的要求往往不局限于个位,我们往往需要更为准确的读数,例如精确到小数点以后一位,基于此我们对程序进行改进。代码如下:
//主函数
void main()
{
unsigned int temp,humi;
value humi_val,temp_val;
// float dew_point;用于记录露点值
unsigned char error;
unsigned char checksum;
uchar TEMP1[7];
uchar HUMI1[6];
LCD_Initial();
GotoXY(0,0);
Print("Temp: C");
GotoXY(0,1);
Print("Humi: %RH");
s_connectionreset();
while(1)
{
error=0;
error+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP);
error+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI);
if(error!=0) s_connectionreset();
else
{
humi_val.f=(float)humi_val.i;
temp_val.f=(float)temp_val.i;
calc_sth10(&humi_val.f,&temp_val.f);
temp=temp_val.f*10;
humi=humi_val.f*10;
GotoXY(5,0);
TEMP1[0]=temp/1000+'0';
if (TEMP1[0]==0x30) TEMP1[0]=0x20;
TEMP1[1]=temp%1000/100+'0';
if (TEMP1[1]==0x30 && TEMP1[0]!=0x30) TEMP1[1]=0x20;
TEMP1[2]=temp%100/10+'0';
TEMP1[3]=0x2e; //小数点
TEMP1[4]=temp%10+'0'; //小数点后一位
TEMP1[5]=0xdf;
Print(TEMP1);
GotoXY(5,1);
HUMI1[0]=humi/1000+'0';
if (HUMI1[0]==0x30) HUMI1[0]=0x20;
HUMI1[1]=humi%1000/100+'0';
if (HUMI1[1]==0x30 && HUMI1[0]!=0x30) HUMI1[1]=0X20;
HUMI1[2]=humi%100/10+'0';
HUMI1[3]=0x2E; //小数点
HUMI1[4]=humi%10+'0'; //小数点后一位
Print(HUMI1);
}
delay(800);
}
}
在使用较久之后,设备可能会出现时飘现象对此通过按钮状态进行手动调节,代码如下
if (P1_2 == 0) {
delay(10);
while (P1_2 == 0) {
delay(10);
++;
}
}
if (P1_3 == 0) {
delay(10);
while (P1_3 == 0) {
delay(10);
temp--;
}
}
if (P1_4 == 0) {
delay(10);
while (P1_4 == 0) {
delay(10);
humi++;
}
}
if (P1_5 == 0) {
delay(10);
while (P1_5 == 0) {
delay(10);
humi--;
}
}
三、仿真如下
手动调节后如下