/******************************************************************************************
作 者:微风
修改日期:2012-10-10
版 本:V3.1
核心器件:STC89C51@11.0592MHz
外围器件:DS18B20,继电器,数码管、按键
说 明:1.Conf_tny.A51中定义了每个任务的最大循环周期约5ms(晶振11.0592MHz)
INT_CLOCK EQU 1000 ; default is 10000 cycles
; Define Round-Robin Timeout in Hardware-Timer ticks.
TIMESHARING EQU 5 ; default is 5 Hardware-Timer ticks.
; 0 disables Round-Robin Task Switching
2.RTX51_Tiny操作系统使用了定时器T0,并且EA=1,所以串口初始化没必要再开总中断
*******************************************************************************************/
#include"config.h"
//程序从任务0开始运行
//任务0初始化系统,创建其他任务并删除自身
void System_Init() _task_ 0 //注意_task_与0之间有空格
{
Relay=1; //关闭继电器
LED1=LED2=LED3=0;
Uart_Init(); //串口中断初始化
//DS18B20_Init(); //温度传感器初始化
Delay_ms(1000);
//串口发送成功标志
//Uart_SendString("系统初始化成功!");
//创建3个任务:括号中可以自己起一个名字,但要与后面的任务名对应
os_create_task(1);
os_create_task(2);
os_create_task(3);
//删除自身
os_delete_task(0);
}
//每个任务都是一个while(1)循环
//任务1主要处理按键
void key() _task_ 1 //此处_task_后的名称要与os_create_task()中的名称相对应
{ //不一定非要命名成1,2,3……
uchar t=0,tt=0; //存储按键的值
uint x=0; //用于设定温度时的频繁计数
while(1)
{
t=Key_Scan();
if(t!=0)Auto=0;
if(t!=1)
{
os_send_signal(2); //给任务2发送一个控制信号,使得任务2可以继续执行
}
else //按下了Set键
{
Auto=0; //关闭自动模式
LED1=LED2=LED3=0;
os_wait (K_IVL, 800, 0); /* wait interval: 2 second */
//Delay_ms(2000); //连续按下Set键2s
if(t==Key_Scan())
{
t=0;
while(Key1!=0||Key3!=0) //按住Set不放再按 - 键退出设置
{
x++;
if(x<3) //闪烁:表明处于设置状态
{
BW=10; //显示---
SW=10;
GW=10;
}
else if(x>=3&&x<12)
{
BW=Tem_Set/100;
if(Tem_Set==0)P0=0x00;
else
SW=(Tem_Set%100)/10;
GW=Tem_Set%10;
}
else
x=0;
tt=Key_Scan();
if(tt==2)Tem_Set++;
if(tt==3)Tem_Set--;
if(Tem_Set<=2)Tem_Set=98; //温度限制在0~95之间
if(Tem_Set>=98)Tem_Set=2;
//Uart_SendString("设置成功,设置温度为:");
//Uart_SendChar(Tem_Set);
os_wait (K_IVL,100, 0); /* wait interval: 200ms */
//Delay_ms(100);
}
}
}
os_wait2(K_TMO,1);
}
}
//任务2用于在Set键未按下的情况下检测温度传感器的温度
void temperature() _task_ 2
{
static uchar Tem_Ago1=0,Tem_Last1=0,Tem_Ago2=0,Tem_Last2=0,Tem_Ago3=0,Tem_Last3=0; //用于滤波
static uchar s[3];//用于排序
uchar tltemp; //负温度标志 和临时暂存变量
uchar t;//排序时的中间变量
uint sw1;
static uint x=0;
while(1)
{
x++;
if(x==20)
{
ReadyReadTemp1(); //读温度准备
T1L=ReadOneChar1(); //先读的是温度值低位
T1H=ReadOneChar1(); //接着读的是温度值高位
if((T1H&0xf8)!=0x00)//判断高五位 得到温度正负标志
{
T1L=~T1L; //取反
T1H=~T1H; //取反
tltemp=T1L+1; //低位加1
T1L=tltemp;
if(tltemp>255) T1H++; //如果低8位大于255,向高8位进1
TN1=T1H*16+T1L/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
//这样得出的是温度的整数部分,小数部分被丢弃了
TD1=(T1L%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整,
}
TN1=(T1H*16+T1L/16); //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
//这样得出的是温度的整数部分,小数部分被丢弃了
TD1=((T1L%16)*10/16); //计算温度的小数部分,将余数乘以10再除以16取整,
//这样得到的是温度小数部分的第一位数字(保留1位小数)
if(TN1>60||TN1<0)TN1=Tem_Last1;
if(Tem_Last1>75)TN1=75;
Tem_Ago1=Tem_Last1;
Tem_Last1=TN1;
//总是取三者中的中间值
t=(Tem_Last1>Tem_Ago1)?Tem_Last1:Tem_Ago1;
s[0]=(t>TN1)?t:TN1;//存储最大值
t=(Tem_Last1>Tem_Ago1)?Tem_Ago1:Tem_Last1;
s[2]=(t>TN1)?TN1:t;//存储最小值
s[1]=Tem_Ago1+Tem_Last1-s[0]+TN1-s[2]; //写s[3]竟不报错!
TN1=s[1];
LED3=LED2=0;
LED1=1;
TN=TN1;
TD=TD1;
TH=T1H;
TL=T1L;
}
if(x==40)
{
ReadyReadTemp2(); //读温度准备
T2L=ReadOneChar2(); //先读的是温度值低位
T2H=ReadOneChar2(); //接着读的是温度值高位
if((T2H&0xf8)!=0x00)//判断高五位 得到温度正负标志
{
T2L=~T2L; //取反
T2H=~T2H; //取反
tltemp=T2L+1; //低位加1
T2L=tltemp;
if(tltemp>255) T2H++; //如果低8位大于255,向高8位进1
TN2=T2H*16+T2L/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
//这样得出的是温度的整数部分,小数部分被丢弃了
TD2=(T2L%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整,
}
TN2=(T2H*16+T2L/16); //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
//这样得出的是温度的整数部分,小数部分被丢弃了
TD2=((T2L%16)*10/16); //计算温度的小数部分,将余数乘以10再除以16取整,
//这样得到的是温度小数部分的第一位数字(保留1位小数)
if(TN2>60||TN2<0)TN2=Tem_Last2;
if(Tem_Last2>75)TN2=75;
Tem_Ago2=Tem_Last2;
Tem_Last2=TN2;
//总是取三者中的中间值
t=(Tem_Last2>Tem_Ago2)?Tem_Last2:Tem_Ago2;
s[0]=(t>TN2)?t:TN2;//存储最大值
t=(Tem_Last2>Tem_Ago2)?Tem_Ago2:Tem_Last2;
s[2]=(t>TN2)?TN2:t;//存储最小值
s[1]=Tem_Ago2+Tem_Last2-s[0]+TN2-s[2]; //写s[3]竟不报错!
TN2=s[1];
LED1=LED3=0;
LED2=1;
TN=TN2;
TD=TD2;
TH=T2H;
TL=T2L;
}
if(x==60)
{
ReadyReadTemp3(); //读温度准备
T3L=ReadOneChar3(); //先读的是温度值低位
T3H=ReadOneChar3(); //接着读的是温度值高位
if((T3H&0xf8)!=0x00)//判断高五位 得到温度正负标志
{
T3L=~T3L; //取反
T3H=~T3H; //取反
tltemp=T3L+1; //低位加1
T3L=tltemp;
if(tltemp>255) T3H++; //如果低8位大于255,向高8位进1
TN3=T3H*16+T3L/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
//这样得出的是温度的整数部分,小数部分被丢弃了
TD3=(T3L%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整,
}
TN3=(T3H*16+T3L/16); //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
//这样得出的是温度的整数部分,小数部分被丢弃了
TD3=((T3L%16)*10/16); //计算温度的小数部分,将余数乘以10再除以16取整,
//这样得到的是温度小数部分的第一位数字(保留1位小数)
if(TN3>60||TN3<0)TN3=Tem_Last3;
if(Tem_Last3>75)TN3=75;
Tem_Ago3=Tem_Last3;
Tem_Last3=TN3;
//总是取三者中的中间值
t=(Tem_Last3>Tem_Ago3)?Tem_Last3:Tem_Ago3;
s[0]=(t>TN3)?t:TN3; //存储最大值
t=(Tem_Last3>Tem_Ago3)?Tem_Ago3:Tem_Last3;
s[2]=(t>TN3)?TN3:t; //存储最小值
s[1]=Tem_Ago3+Tem_Last3-s[0]+TN3-s[2]; //写s[3]竟不报错!
TN3=s[1];
LED1=LED2=0;
LED3=1;
TN=TN3;
TD=TD3;
TH=T3H;
TL=T3L;
}
if(x>60)x=0;
if((TH&0xf8)!=0x00)BW=10; //温度为负值时,百位显示 - ,即DIS_SEG[10]
else
BW=TN/100;
if(BW==0&&((TH&0xf8)!=0x00)) SW=10;
else
SW=(TN%100)/10;
if(SW>=5)SW=sw1;
sw1=SW;
GW=TN%10;
//Delay_ms(200);
if(Auto==1) //自动模式
{
if(TN3<23||TN3==23)Relay=0; //不工作
if(TN3>23&&TN3<26)
{
if(TN1>17) Relay=1;
if(TN1<16) Relay=0;
}
if(TN3>=26) //TN1:水温;TN2:室外温度;TN3:室温
{
if(TN1<(TN2-10))Relay=0;//比室外温度TN2-10度还小时,不工作
if(TN1>(TN2-9)) Relay=1;
}
}
//这个有点像施密特触发器了!
//if(TN>=(Tem_Set+1))Relay=1;//大于设定温度一度,继电器闭合
//if(TN<=(Tem_Set-1))Relay=0;//温度降到设定温度一度,继电器断开
if(Auto!=1) //手动模式
{
if(TN1>=(Tem_Set+1))Relay=1;//大于设定温度一度,继电器闭合
if(TN1<=(Tem_