|
这是我做的温湿度控制系统资料。采用sht71温湿度传感器作为检测元件。
包含proteus仿真资料。
源代码。
程序如下:
- /*注意:子函数多层调用时,要记住:写子函数以及子函数声明用形参;而调用子函数用实参*/
- /*头文件*/
- #include<reg52.h>
- #include<intrins.h>
- #include<math.h>
- #include<hc595.h>
- #include<delay.h>
- #include<actuator.h>
- #include<ini.h>
- #include<sht71.h>
- /*全局变量定义 */
- uchar code duan[21]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
- 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,
- 0x40}; //CC码表:数字0~9 带小数点数字0~9 负号
- uchar code wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//从LED0-7
- uchar high8=0,low8=0;//传感器16位数据高低8位
- uchar temphigh8=0,templow8=0;//温度高低8位
- uchar humihigh8=0,humilow8=0;//湿度高低8位
- long SO_RH=0;//湿度10进制数据
- long SO_T=0;//温度10进制数据
- char temp; //实际温度值,温度分正负
- char temp_2;//因为湿度值计算时会用到温度值,防止对temp数学处理过程引起的值变化影响湿度的计算,故将temp赋给temp_2保存以用于湿度计算
- char humi_relative;//相对湿度值,湿度只有正值
- char humi; //实际湿度值
- uchar a1,b1,c1,d1;//正负位、十位、个位、小数位
- uchar a2,b2,c2,d2;//正负位、十位、个位、小数位
- uchar error_command;//通讯检查信号 0正常 1错误
- uchar temp_max,temp_min;//温度上下极限值
- uchar p[16];
- /**********************温湿度测量子函数***********************/
- void sht_measurement(uchar measure)
- {
- measurement_start();
- command_send(measure);
- measurement_wait();
- mcu_receive_date();
- }
- /************************启动测量子函数***********************/
- void measurement_start()
- {
- SCK=0;//赋予时钟线初始电平
- DATE=1;//赋予数据线初始电平
-
- SCK=1;
- _nop_();
- _nop_();
- DATE=0;
- _nop_();
- _nop_();
- SCK=0;
- _nop_();
- _nop_();//时钟线低电平保持
- SCK=1;
- _nop_();
- _nop_();
- DATE=1;
- _nop_();
- _nop_();
- SCK=0;
- }
- /*********************发送测量命令子函数*********************/
- char command_send(uchar command) //写时序:上升沿-高电平保持-下降沿
- { //注意:要先给DATE,再给写时序(SCK)
- uchar value=0x80,i=0;
- SCK=0;//写时序初始低电平
- for(i=0;i<8;i++)
- {
- if(command&value)
- DATE=1;
- else DATE=0;
- SCK=1;
- _nop_();
- SCK=0;
- value=value>>1;
- }
- SCK=1;
- if(DATE==0)
- error_command=0;
- SCK=0; //第9脉冲,即ACK脉冲,同时也是一个读脉冲
- if(error_command==1)
- sht_reset();//如果通讯错误,则传感器软件复位
-
- return error_command; //error=1通讯错误
- }
- /***********************测量等待子函数*********************/
- void measurement_wait()
- {
- delay(40000);//测量等待390ms(20/80/320ms对应8、12、14位)
- }
- /***********************读数据子函数**********************/
- void mcu_receive_date()
- {
- high8=mcu_receive_byte();
-
- DATE=0;//写时序:上升沿-高电平保持-下降沿
- SCK=1;_nop_();_nop_();
- SCK=0;_nop_();_nop_();//接收完高字节数据后,手动拉低数据线(写0),表示接收结束
- DATE=1;
-
- low8=mcu_receive_byte();
- DATE=1;//写时序:上升沿-高电平保持-下降沿
- SCK=1;_nop_();_nop_();
- SCK=0;_nop_();_nop_();//接收完高字节校数据后,手动拉高数据线,传感器不经校验,直接休眠
- }
- /***********************读字节子函数***********************/
- uchar mcu_receive_byte()
- {
- uchar value=0x80,dat=0,i=0;
- SCK=0;//读时序初始低电平
- for(i=0;i<8;i++) //读时序:低电平保持-上升沿-高电平保持
- {
- SCK=1;_nop_();
- if(DATE)
- dat=dat|value;
- SCK=0;_nop_();
- value=value>>1;
- }
- return dat;
- }
- /******************取实际温度子函数********************/
- void temperature_calculate()
- {
- float d1_5V=-40.1;//定义温度计算公式参数
- float d2_14bit=0.01;//定义温度计算公式参数
- temphigh8=high8;
- templow8=low8;
- SO_T=temphigh8;//先赋值给低8位
- SO_T=((SO_T<<8)&0xff00)|templow8;//将两个8位合成一个16位。与0xff00与运算,目的在于清低八位,避免不稳定错误
- SO_T=SO_T&0x3fff;//sht温度精度默认为最高14位,即temp16的高2位为0,这里人为将高2位清零,避免不稳定错误。0011 1111 1111 1111=0x3fff
- temp=d1_5V+d2_14bit*SO_T;
- compensation_temp();//正温度修正
- temp_2=temp;
- }
- /******************分离温度值子函数********************/
- void temperature_seperate()
- {
- uchar i=0;//正负数标志位
- i=0x80&temp;//取符号位,判断正负
- if(i)
- {
- temp=temp-1; //由补码取原码
- temp=~temp;
- a1=20;
- b1=(temp*10)/100;
- c1=((temp*10)%100)/10;
- d1=((temp*10)%100)%10;
- temp=~temp; //还原补码,防止下次显示将负数扫描成正数
- temp=temp+1;
- /*负温度范围补偿代码 统一上浮1度,使得精度保证在+-1度以内
- -12度以内,显示误差为0;-12以下,显示误差为-1度*/
- if(c1==9)
- {
- c1=0;
- b1+=1;
- }
- else
- {
- c1+=1;
- }
- c1+=10; //+10表示附带小数点
- p[0]=a1;
- p[1]=b1;
- p[2]=c1;
- p[3]=d1;
- }
- else
- {
- a1=0;
- b1=(temp*10)/100;
- c1=((temp*10)%100)/10;
- d1=((temp*10)%100)%10;
- c1+=10; //+10表示附带小数点
- p[0]=a1;
- p[1]=b1;
- p[2]=c1;
- p[3]=d1;
- }
- }
- /*****************温度极限值分离子函数*********************/
- void temperature_limit_seperate()
- {
- uchar min1,min2,max1,max2;//温度下限十位、温度下限个位、温度上限十位、温度上限个位
- temp_min=10;temp_max=50;
-
- min1=temp_min/10;
- min2=temp_min%10;
- max1=temp_max/10;
- max2=temp_max%10;
-
- p[8]=min1;
- p[9]=min2;
- p[10]=max1;
- p[11]=max2;
- p[12]=8;
- p[13]=8;
- p[14]=8;
- p[15]=8;
- }
- /*****************温湿度显示子函数*********************/
- void display()
- {
- uchar m=0;
- for(m=0;m<16;m++)
- {
- if(m<8) //扫描显示前8位数码管,屏蔽后8位数码管(因为数据线共用)
- {
- InputData(0xff); //给第三片595送屏蔽位选,LED8~15
- InputData(wei[m]); //给第二片595送位选,LED0~7
- InputData(duan[p[m]]);
- OutputData();
- delay(100);
- }
- else //扫描显示后8位数码管,屏蔽前8位数码管(因为数据线共用)
- {
- InputData(wei[m-8]); //给第三片595送位选,LED8~15
- InputData(0xff); //给第三片595送屏蔽位选,LED0~7
- InputData(duan[p[m]]);
- OutputData();
- delay(100);
- }
- }
- }
- /****************取实际湿度子函数**********************/
- void humidity_calculate()
- {
- float c1_12bit=-2.0468,c2_12bit=0.0367,c3_12bit=-0.0000015955;//定义湿度计算公式参数
- float t1_12bit=0.01;//定义湿度计算温补公式参数
- float t2_12bit=0.00008;//定义湿度计算温补公式参数
- humihigh8=high8;
- humilow8=low8;
- SO_RH=humihigh8; //先赋值给低8位
- SO_RH=((SO_RH<<8)&0xff00)|humilow8;//将两个8位合成一个16位。
- SO_RH=SO_RH&0x0fff;//湿度精度默认12位。0000 1111 1111 1111=0x0fff
- humi_relative=c1_12bit+c2_12bit*SO_RH+c3_12bit*SO_RH*SO_RH;
- // humi=(temp_2-25)*(t1_12bit+t2_12bit*SO_RH)+humi_relative; //温度补偿
- humi=humi_relative;
- compensation_humi();//湿度误差修正
- }
- /******************分离湿度值子函数********************/
- void humidity_seperate()
- {
- a2=0;
- b2=(humi*10)/100;
- c2=((humi*10)%100)/10;
- d2=((humi*10)%100)%10;
-
- c2+=10; //+10表示附带小数点
- p[4]=a2;
- p[5]=b2;
- p[6]=c2;
- p[7]=d2;
- }
- /*******************湿度补偿子函数******************/
- void compensation_humi()
- {
- if(humi<=12) //0~7%
- {
- humi-=5;
- }
- else
- {
- if(humi<=20) //8~16%
- {
- humi-=4;
- }
- else
- {
- if(humi<=33) //17~30%
- {
- humi-=3;
- }
- else
- {
- if(humi<=93) //31~91%
- {
- humi-=2;
- }
- else
- {
- if(humi<=103) //92~100%
- {
- humi-=3;
- }
- }
- }
- }
- }
- }
- /************************软复位子函数******************/
- void sht_reset()
- {
- uchar i;
- while(DATE==1)
- {
- SCK=0;
- for(i=0;i<12;i++) //数据线高电平的情况下,给时钟线至少9个脉冲
- {
- SCK=1;
- _nop_ ();
- SCK=0;
- _nop_ ();
- }
- }
- }
- /************************温度补偿子函数******************/
- void compensation_temp()
- {
- if(temp>=20)
- {
- temp+=1;
- }
- if(temp>=53)
- {
- temp+=1;
- }
- if(temp>=86)
- {
- temp+=1;
- }
- }
复制代码
全部资料请下载附件:
|
评分
-
查看全部评分
|