0-全部停机,I-1台风机工作,II-2台风机工作,III-3台风机工作。
但为了防止风机频繁切换,所以当温度从一个界限降到另一个界限时并不立即关掉一台风机,而是要降到下一个界限减一度的时候才关掉一台风机。
2、控制系统设计
2.1系统硬件电路设计
2.1.1电路图、各部分的作用说明
按键电路由四个按键组成用于温度的设定、温控系统的开关。
显示电路由六个数码管组成用于各种数据及状态的显示。
而测温电路主要由DS18B20组成。
2.1.2元件、器件介绍
本电路的单片机采用Atmel公司的AT89S52单片机。
最小系统该单片机、按键和显示组成。
而温度传感器采用的是DS18B20。
DS18B20采用数字化技术,能以数字形式直接输出被测温度值,具有测温误差小、分辨力高、抗干扰能力强、能够远程传输数据、用户可设定温度上、下限、有越限自动报警功能、自带串行总线接口等优点,适配各种微控制器(MCU),含微处理器(uP)和单片机(uC),是研制和开发具有高性价比的新一代温度测控系统所必不可少的核心器件。
2.2系统软件设计
2.2.1流程图
1、总流程图
2、温控程序流程图
3、读键程序流程图
4、按键判断流程图
5、选择键处理流程图
6、加键处理流程图
7、减键处理流程图
8、温控控制键处理流程图
9、Time0中断服务程序流程图
2.2.2说明
系统开机首先要进行初始化,包括个变量的初始化和中断程序的初始化,最后开系统中断开始工作。
本系统的中断服务程序的主要工作是更新各个时间标志和调用显示程序。
根据设定是每1毫秒发生一次中断。
本系统的测温间隔由DEF_CHECK_INTERVAL这个预定义设定。
具体时间间隔是DEF_CHECK_INTERVAL*250毫秒。
如果测温时间间隔已到相应的标志位flag_check_interval就要置位以便进入测温程序。
而检测按键的间隔则由flag_50ms这个为变量来控制。
每当这个标志置1便可以进入检测按键程序。
检测按键程序采用了软件去抖动,就是第一次检测到有按键被按下后就保存该键值并开始计时50毫秒,50毫秒已到就再次检测按键,如果这次检测到的按键与已保存的键值相等就确定该键值是用户按下产生的。
然后在把这个键值和上次有效键值比较,如果相等就是说这个是重复键。
为了预防用户按下按键不放参数变化过快的现象,我们还要判断100毫秒标志位有没有置位,如果100毫秒标志为1则把这个键值传送个按键判断程序,如果为0则当无效键处理。
如果新建值和上次有效键键值不相等,就是说这个键是新键,马上把这个键值传送个按键判断程序。
按键判断程序接收到键值就根据该键值调用相应的按键处理程序。
温控程序则是以温度和现在开动风机的数量来控制三台风机的状态。
显示程序负责人机对话。
前三个数管在非设定状态时显示三台风机的运行状态,第三个数码管在设定状态时用来指示现在修改的参数。
后三个数码管显示测量温度值并在设定状态期间显示上、中、下三个不同的温度设定值。
3、系统调试
在确定硬件能正常工作后系统调试工作主要就是软件的调试了。
我们首先调试显示程序。
从最简单的单个数码管的显示开始,然后逐步向前。
而不是把整个显示程序写好在调试。
这样可能会有很多错误,一下子就被吓得没信心了。
显示程序调试成功后我们接着就可以进行按键程序的编写及调试了。
也是从最简单的工作做起,就是直接检测有没有按键,成功后再加软件去抖动,然后再加重复键和新键的处理程序。
一步一步,最后一个较完美的按键程序就完成了。
做完按键我们就分开两路一些同学搞DS18B20的程序,另外一些同学则负责温度控制程序。
但是还没有测出温度是没有温度值的,所以温控程序的开发就用读随机的方法模拟“可变的温度值”。
在两部分工作都搞完后我们就联合调试了,大家都很高兴的看到显示结果但是显示会随机出现一些莫名其妙的数值。
这个问题困扰了我们很久。
因为分析程序都没发现什么错误会出现这种情况。
最后我们决定逐步调试,先是去掉测温程序发现显示正常,按键也正常。
我们就怀疑是不是按键和测温会有相撞。
于是我们就加入测温程序,撤去按键程序。
发现显示还是有问题。
我们就确定是测温的问题,但是无论怎样分析都是发现测温程序之正确无误的。
无奈!
一些同学便乱试碰碰运气。
最后发现把测温程序移到中断程序便不会发生错误。
惘然大悟。
原来是中断的问题。
因为如果在测温的过程中如果发生中断,那就会破坏测温程序。
因为测温程序对时间的连续性要求非常严格。
最后我们在进入测温前禁止全局中断,测温完成后再开中断就解决了最大的问题。
4、总结
通过这次课程设计,在老师的指导下,我基本上学会用C语言开发单片机程序,发现用C语言编写单片机程序很容易实现自己的想法,不用太顾及寄存器的使用、中断向量的编写及免去了一些琐碎的跳转指令,而且C语言调试程序相当方便。
不过这些都需要有扎实的汇编基础,不然在写短延时的时候就会束手无策。
通过这次课程设计我进一步学习了一个系统开发的步骤,首先要把整个系统的硬件系统搞出来,然后按照要求开始做软件的流程图。
在这之后就一步一步地按照流程图编写程序。
最后就是体会到了用模块化编程的好处。
用模块化编程可以把大问题细分成一个个小问题。
各个模块各司其职,然后合并成一个完整的程序。
5、参考
6、附录(程序清单)
//Cautions:
//temp:
temperature
//sel:
select
//whc:
which
//con:
content
//disp:
display
#include
#include
#include
#defineled_dataXBYTE[0xE000]
#defineled_selXBYTE[0xC000]
#definekey_addXBYTE[0xA000]
#definedisp_start_pos3//valuefrom0to3arewelcomed
#defineDEF_CHECK_INTERVAL4
#defineMAX_TEMP_MAX250
#defineMAX_TEMP_MIN200
#defineMIN_TEMP_MAX150
#defineMIN_TEMP_MIN100
sbitDQ=P1^0;
unsignedcharcodedot_temp[16]={0,0,1,1,2,3,3,4,5,5,6,6,7,8,8,9};
//data_disp:
leddisplayarray
unsignedchardatadata_disp[6]={0x00,0x00,0x00,0x00,0x00,0x00};
unsignedintdatasetting[3]={0x64,0x96,0x0C8};
unsignedintcur_temp=200;
unsignedchardatacount_50ms=0;
unsignedchardatacount_100ms=0;
unsignedchardatacount_250ms=0;
unsignedchardatacount_check_interval=0;
unsignedchardataold_key_val=0;
unsignedchardataworking_fans=0;
//cur_pos:
currentdisplayingled
unsignedchardatacur_pos=0;
//flash_cur_pos:
justforflashingled
unsignedchardataflash_cur_pos=0;
//cur_var:
currentmodifyingsetting
unsignedchardatacur_var=0;
//sys_statue:
flagsofthesystem
unsignedcharbdatasys_statue=0;
//2msreached
sbitflag_1ms=sys_statue^0;
//50msreached
sbitflag_50ms=sys_statue^1;
//100msreached
sbitflag_100ms=sys_statue^2;
//500msreached
sbitflag_250ms=sys_statue^3;
//keypressed,systemparameterisbeingmodifying
sbitflag_modifying=sys_statue^4;
//forcommonuse
sbitflag_temp=sys_statue^5;
//fortemperaturecheckinterval
sbitflag_check_interval=sys_statue^6;
//coolingsystempenabledornot
sbitflag_sys_enabled=sys_statue^7;
voiddivide_con(unsignedintcon_disp)
{
unsignedcharcodetab[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsignedinttemp=0;
//138/100=1
temp=con_disp/100;
data_disp[disp_start_pos]=tab[temp];
//138-100*1=38
con_disp=con_disp-100*temp;
//38/10=3;
temp=con_disp/10;
temp=tab[temp];
//displayradixpoint
data_disp[disp_start_pos+1]=temp|0x80;
//38%10=8
temp=con_disp%10;
data_disp[disp_start_pos+2]=tab[temp];
}
voiddisp(void)
{
//flashing
led_data=0x00;
led_sel=0xff;
led_data=data_disp[cur_pos];
led_sel=~(1<if(cur_pos<6)
{
++cur_pos;
}
else
{
cur_pos=0;
}
}
/*
unsignedcharupdate_disp(unsignedcharwhc_segment)
{
}
*/
/*
unsignedintread_temp(void)
{
cur_temp+=20;
if(cur_temp>600)
{
cur_temp=200;
}
return(cur_temp);
}
*/
unsignedcharkey_press(void)
{
unsignedchardatawhc_key=0;
led_data=0x00;
led_sel=0xFE;
whc_key=key_add;
whc_key=~whc_key;
return(whc_key);
}
voidkey2_process(void)
{
if(cur_var==1)
{
if(setting[0]{
setting[cur_var-1]=setting[cur_var-1]+10;
divide_con(setting[cur_var-1]);
}
}
elseif(cur_var==3)
{
if(setting[2]{
setting[cur_var-1]=setting[cur_var-1]+10;
divide_con(setting[cur_var-1]);
}
}
setting[1]=setting[0]+setting[2];
setting[1]=setting[1]>>1;//div2
}
voidkey3_process(void)
{
if(cur_var==1)
{
if(setting[cur_var-1]>MIN_TEMP_MIN)
{
setting[cur_var-1]=setting[cur_var-1]-10;
divide_con(setting[cur_var-1]);
}
}
elseif(cur_var==3)
{
if(setting[cur_var-1]>MAX_TEMP_MIN)
{
setting[cur_var-1]=setting[cur_var-1]-10;
divide_con(setting[cur_var-1]);
}
}
setting[1]=setting[0]+setting[2];
setting[1]=setting[1]>>1;//div2
}
voidkey4_process(void)
{
flag_sys_enabled=~flag_sys_enabled;
if(~flag_sys_enabled)
{
data_disp[0]=0x3F;
data_disp[1]=0x3F;
data_disp[2]=0x3F;
}
}
voidkey_process(unsignedcharkey_kpval)
{
//waituntilrelease
//key1pressdandnowrelease
//timescur_var_beforecur_var_after
//101
//212
//323
//434
if(key_kpval==1)
{
data_disp[0]=0x00;
data_disp[1]=0x00;
data_disp[2]=0x00;
flag_modifying=1;
if(cur_var==0)
{
data_disp[2]=0x08;
}
elseif(cur_var==1)
{
data_disp[2]=0x40;
}
elseif(cur_var==2)
{
data_disp[2]=0x01;
}
else
{
data_disp[2]=0x00;
}
divide_con(setting[cur_var]);
++cur_var;
if(cur_var==4)
{
flag_modifying=0;
cur_var=0;
}
return;
}
elseif(key_kpval==8)
{
key4_process();
return;
}
//key2pressdandnowrelease
if(flag_modifying)
{
if(key_kpval==2)
{
key2_process();
}
//key3pressdandnowrelease
if(key_kpval==4)
{
key3_process();
}
}
}
unsignedcharread_key(void)
{
unsignedchardatakey_val=0;
key_val=key_press();
if(key_val)
{
//delay100ms
flag_50ms=0;
count_50ms=0;
while(!
flag_50ms);
flag_50ms=0;
if(key_val==key_press()&&key_val==old_key_val)//
{
if(flag_100ms==1)
{
flag_100ms=0;
return(key_val);
}
else
{
return(0);
}
}
elseif(key_val==key_press())
{
old_key_val=key_val;
flag_100ms=0;
count_100ms=0;
return(key_val);
}
else
{
return(0);
}
}
}
/*
voidcooling_control(unsignedintcur_temp_b)
{
unsignedchartemp_logic=0;
temp_logic=cur_temp>=setting[0]-10&&working_fans==1;
if(cur_temp_b>=setting[0]||temp_logic)
{
working_fans=1;
temp_logic=cur_temp>=setting[1]-10&&working_fans==2;
if(cur_temp_b>=setting[1]||temp_logic)
{
working_fans=2;
temp_logic=cur_temp>=setting[0]-10&&working_fans==3;
if(cur_temp_b>=setting[2]||temp_logic)
{
working_fans=3;
}
}
}
else
{
working_fans=0;
}
}*/
voidcooling_control(unsignedintT)
{
if(T{
if(T{
working_fans=0;
}
}
elseif(T>=setting[0]&&T{
if(T{
working_fans=1;
}