微机课程设计报告风扇控制.docx
《微机课程设计报告风扇控制.docx》由会员分享,可在线阅读,更多相关《微机课程设计报告风扇控制.docx(44页珍藏版)》请在冰豆网上搜索。
微机课程设计报告风扇控制
1、设计的题目名称及要求…………………………………2
2、实验设备…………………………………………………2
3、设计思想、实施方案和硬件电路图………………………2
4、典型程序模块及典型编程技巧分析…………………………7
5、课程设计中遇到的问题及解决方法…………………………9
6、实验程序的流程图……………………………………………10
7、程序清单及程序注释…………………………………………16
8、收获与体会……………………………………………………42
9、参考文献………………………………………………………42
一、课程设计的题目名称及要求
设计题目:
家用电扇控制实验与驱动电路设计
基本设计要求:
1.编程语言为汇编语言和C语言;
2.控制硬件电路基于80x86微机接口电路;
3.驱动电路(主回路)仅需设计;
4.控制器功能包括:
按钮三个,分别为风速、类型和停止,LED指示灯六个,指示风速强、中、弱,类型为睡眠、自然和正常。
指标如下:
1)电扇处于停转状态时,所有指示灯不亮,只有按下“风速”键时,才会响应,进入起始工作状态;电扇在任何状态,只要按停止键,则进入停转状态。
2)处于工作状态时,有:
初始状态为:
风速-“弱”,类型-“正常”
按“风速”键,其状态由“弱”“中”“强”“弱”……往复循环改变,每按一下按键改变一次;
按“类型”键,其状态由“正常”“睡眠”“自然”“正常”……往复循环改变;
3)风速的弱、中、强对应于电扇的转动由慢到快。
4)类型的不同选择,分别为:
正常电扇连续运转;自然电扇模拟自然风,即转4s,停8s;睡眠电扇慢转,产生轻柔的微风,运转8s,停转8s;
5)按照风速与类型的设置输出相应的控制信号。
附加功能扩展:
根据控制性能要求,在“睡眠”和“自然”类型下仍可选择不同的“风速”,工作时总共有“3*3”种不同的模式,而且通过按键的分时复用可在“停止”与“工作”两种状态间反复切换而不必重载程序。
二、实验设备
PC机一台(装有TDPIT软件)、唐都TD-Pit实验箱。
三、设计的思想和实施方案
由于本次课程设计控制的对象是直流电机,在上个学期学习的《电机与电力拖动》时已知直流电机可通过改变给定电压的大小调节其转速,但实际测试时风扇的转速变化不够明显,故采用了两种方案:
1、用汇编语言编写的程序通过改变电压控制直流电机的转速。
2、用C语言编写的程序采用PWM波控制直流电机的转速。
方案1较容易实施,但由于对PWM波比较陌生,方案2需要搜索了一些PWM控制方式的相关资料,所得资料如下:
PWM控制就是对脉冲的宽度进行调制的技术。
即通过对一系列脉冲的宽度进行调制来等效地获得所需要波形(含形状和幅值)。
在采样控制理论中有一条重要的结论:
冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同,冲量即窄脉冲的面积。
效果基本相同是指环节的输出响应波形基本相同。
上述原理称为面积等效原理。
简单点说,就是通过调节时间周期很小的方波的占空比就可以明显地调节直流电机的转速。
图1、TD-PIT直流电机及驱动电路单元
驱动电机的电压由DA0832提供,DA0832的输出OUT接驱动电路的A端,驱动电路的12V和A`端分别接直流电机的1端和2端。
图2、DA0832单元
解决了电机的控制问题后,课题要求有6个LED灯显示相应的风速和类型以及3个按键做相应的控制,于是本人想到了用一片8255做LED灯的驱动电路和小键盘的读取接口。
8255内部包含3个8位的输入输出端口A、B和C,端口A和端口B都可以用作一个8位的输入口或8位的输出口,端口C既可以作为一个8位的输入口或8位的输出口,又可以作为两个4位的输入输出口(C口上半部分和C口下半部分)使用,还可以配合A口和B口工作,分别用来产生A口和B口的输出控制信号和输入A口和B口的端口状态信号。
本次设计,我对8255的使用是这样的:
8255工作于方式0,A口低四位接键盘及数码管显示单元的Y4-Y1;C口接LED及开关单元的LED灯D0-D7;B口和A口高四位悬空。
选择C口做LED灯的接口是因为C口能方便地通过编程置位和复位,从而方便的点亮和熄灭相应的LED信号。
图3、8255单元
键盘及数码管显示单元的X1接地,Y1对应“风速”,Y2对应“类型”,Y3对应“停止”,X2、X3、X4悬空。
本次实验未用到数码管,故A、B、C、D、E、F、G、DP悬空。
图4、小键盘及数码管显示单元
图5、硬件电路总接线图
如上图示:
该图涉及到系统总线、可编程外围接口芯片8255、DA0832、键盘及数码管显示单元、直流电机及其驱动电路。
8255和DA0832的D0~D7依次接系统总线的XD0~XD7,DA0832的A1和A0分别接系统总线的XA3和XA2;WR和RD依次接系统总线上的XIOW和XIOR;8255的CS接系统总线的IOY0,DA0832的CS接系统总线的IOY1;DA0832的OUT接驱动电路的A端;8255的PC0-PC7接低八位LED。
四、典型程序模块及典型编程技巧分析
1、C语言与汇编语言的共同典型模块
(1)主函数(或主程序)MAIN
当程序运行时,PC机屏幕上显示提示菜单,完成硬件初始化——电机不转动且LED无显示,8255工作方式0、A口输入、C口输入,并等待小键盘的输入。
若①当小键盘有键按下且键值是“110(Y3\Y2\Y1)”时电机启动,PC机屏幕显示电机转动的风速强弱,LED显示风速和类型(低速、正常\PC0和PC4为1);
若②当小键盘有键按下且键值为“011”时,退出程序。
编程小技巧:
将读入的A口数据与07H“与”运算可屏蔽A口其他位对输入信息的影响。
(2)不带键盘检测的延时模块DELLY
用与键盘检测时防抖。
(3)小键盘检测模块KEY
当小键盘无输入时返回调用该模块的下一条指令,如果有小键盘输入则延时一定的时间(调用不带键盘检测的延时模块),若输入为“110”则改变风速,若输入为“101”则改变类型,若输入为“011”则停止风扇转动并熄灭LED指示灯。
(4)带键盘检测的延时模块DELLY2
由于希望“睡眠”和“自然”类型下风扇能实时响应小键盘的控制,所以在这两种类型中的延迟用的是带键盘检测的延时模块。
2、C语言的特别模块——风扇控制集成模块WIND_MODE
本模块将风扇的转速和类型控制集于一体,先检测风速强弱的标志FLAG,再检测类型标志FLAG2,从而对直流电机和LED灯进行相应的控制。
在电机的运行过程中实时调用小键盘检测模块以及时响应输入。
3、汇编语言的特别模块
汇编语言中的的风速和类型控制并不作为独立过程,而是用标号标示在主程序中,通过条件判断和跳转指令给DA0832相应的电压数字量和延时,用做标志的是LIGHT1和LIGHT2,即通过灯控信号识别直流电机的控制信号。
编程小技巧:
由于灯控信号是通过8255的C口输出的,而C口可通过控制字进行置位
(1)和复位(0),如果要熄灭一盏已点亮的LED灯,可将该LED对应的灯控信号(比如LIGHT1)与0EH“与”运算再输出到8255的控制字。
五、课程设计中遇到的问题及解决方法
1、直流电机的控制方式:
用哪种方式能改变直流电机的转速,使其有明显的转速变化以区分“弱”、“中”、“强”三种风速是最开始遇到的问题。
通过查找资料,并在实验室调节DA0832的输出(占空比不变时改变电压数字量、电压不变时改变占空比)观察风扇的转速变化,最终确定调节PWM波的占空比为有效的控制方式。
2、小键盘检测:
由于采用的是软件延时,小键盘的检测究竟需要多久的延时才使程序在检测到一次按键时,刚好使风速或者类型改变一次(而不是两次或以上)是个很棘手的问题。
为此曾多次调节键盘检测延时的参数,也多次由于延时不当使程序执行时造成死机。
最后终于调出了合适的延时参数。
3、自然和睡眠类型下风扇需要转一会停一会,如何在风扇停转的这段延时中使风扇能实时响应小键盘的输入,这是又一个大问题。
在多次调整程序的结构觉得毫无作用的时候,本人想到了增加一个带键盘检测的延时模块,从而轻松解决了该问题。
4、当按下小键盘的按键时X端和Y端的状态是低电平还是高电平直接关系到输入检测问题。
通过查询TD-PIT实验平台用户手册和使用数字万用表了解了X端和Y端在按键按下时的电平状态,据此可获得所要检测的数字输入信号。
5、程序编译连接没通过,尤其是C语言,提示的错误不存在,很可能是因为函数的括号没成对出现或者某个语句缺少分号结尾而产生。
或者是输入的符号用了全角或者中文输入而没注意,这些通过养成良好的编程习惯可以很大程度地避免。
6、程序在调试中没问题,可是一运行就死机,这种问题经常发生,有可能是硬件的问题,也可能是调试时不够仔细,没调试完所有功能就急着运行了。
这需要仔细耐心地把程序的所有功能都调试一遍,防止意外的执行结果产生。
六、实验程序的流程图
流程图1-1:
MAIN函数流程图
流程图1-2:
风扇运行模式
特别说明:
圆点线部分由于页面大小无法全部画出,该部分与风速标志值为“1”时只在风速上有差别(分别为‘3’对应‘强风’,‘2’对应‘中风’),未画出的两个部分和中间的部分一起构成三个分支。
流程图1-3:
小键盘检测
流程图1-4:
带键盘检测的延时模块
流程图1-5:
不带键盘检测的延时模块
特别说明:
汇编语言的程序流程和C语言的大同小异,只是标志符号有所不同。
七、程序清单及程序注释
1、C语言程序清单
//使用芯片:
0832\8255
//家用风扇控制
#include
#include
#include
#include
#include
voidkey(char*f_point,char*f2_point);
voiddelay(longinttime);//不带键盘检测的延时模块
voiddelay2(longinttime,char*f_point,char*f2_point);//带键盘检测的延时模块
voidwind_mode(char,char);
//************************根据查看配置信息修改下列符号***************
#defineIOY00xC400
#defineIOY10xC440
//*******************************************************************
#defineMY8255_AIOY1+0x00*4
#defineMY8255_BIOY1+0x01*4
#defineMY8255_CIOY1+0x02*4
#defineMY8255_MODEIOY1+0x03*4
//*******************************************************************
#defineDA0832IOY0+0x00*4
charch1,flag=1,flag2=1;
voidmain()
{charf;
outp(MY8255_MODE,0x90);
outp(DA0832,0x00);
printf("WELCOMETOUSEIT!
\nCHOOSE1TOCHANGESPEED!
I\nCHOOSE2TOCHANGETYPE!
\nCHOOSE3TOQUITE!
\n");
while
(1)
{
loop1:
f=inp(MY8255_A);
f=f&0x07;
if(f!
=0x07)
{switch(f)
{case0x06:
{wind_mode(flag,flag2);break;}
case0x03:
{outp(DA0832,0x00);flag=1;flag2=1;break;}
case0x05:
{outp(DA0832,0x00);outp(MY8255_MODE,0x90);exit(0);break;}
}
}
}
}
//*****************************风速模式******************************
voidwind_mode(charf,charf2)
{longinta,b;
char*f_point,*f2_point;
f_point=&f;
f2_point=&f2;
switch(f)
{//*******************flag=1则设置风速为弱,占空比1/3***************
case1:
{
printf("wind_weak\t");
outp(MY8255_MODE,0x01);//屏幕以及指示灯提示风速
while(f==1)
{switch(f2)
{
case1:
{outp(MY8255_MODE,0x0c);
outp(MY8255_MODE,0x09);
b=1;
for(a=0;a
{ch1=0x00;
outp(DA0832,ch1);
delay(0x200);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
}
break;
}
case2:
{outp(MY8255_MODE,0x08);
outp(MY8255_MODE,0x0b);
b=0x200000;
for(a=0;a<(b/0x28);a++)//flag2=2,自然模式
{ch1=0x00;
outp(DA0832,ch1);
delay(0x200);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
if(f2!
=2||f!
=1)
{break;}
}
if(f2!
=2||f!
=1)
{break;}
outp(DA0832,0x00);
delay2(b,f_point,f2_point);
break;
}
case3:
{outp(MY8255_MODE,0x0a);
outp(MY8255_MODE,0x0d);
b=0x400000;
for(a=0;a<(b/0x50);a++)//flag2=3,睡眠模式
{ch1=0x00;
outp(DA0832,ch1);
delay(0x100);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
if(f2!
=3)//小键盘有输入,跳出FOR循环
{f2=1;break;}
if(f!
=1)
{break;}
}
if(f2!
=3||f!
=1)
{break;}
outp(DA0832,0x00);
delay2(b,f_point,f2_point);
if(f2!
=3)
{f2=1;}
break;
}
}
}
outp(MY8255_MODE,0x00);
flag=f;
flag2=f2;
break;
}
//******************************************************************
//*********************flag=2则风速为中,占空比1/2******************
case2:
{printf("wind_medium\t");//屏幕以及指示灯提示风速
outp(MY8255_MODE,0x03);
while(f==2)
{switch(f2)
{
case1:
{outp(MY8255_MODE,0x0c);
outp(MY8255_MODE,0x09);
b=1;
for(a=0;a
{ch1=0x00;
outp(DA0832,ch1);
delay(0x100);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
}
break;
}
case2:
{outp(MY8255_MODE,0x08);
outp(MY8255_MODE,0x0b);
b=0x200000;
for(a=0;a<(b/0x28);a++)//flag2=2,自然模式
{ch1=0x00;
outp(DA0832,ch1);
delay(0x100);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
if(f2!
=2||f!
=2)
{break;}
}
if(f2!
=2||f!
=2)
{break;}
outp(DA0832,0x00);
delay2(b,f_point,f2_point);
break;
}
case3:
{outp(MY8255_MODE,0x0a);
outp(MY8255_MODE,0x0d);
b=0x400000;
for(a=0;a<(b/0x50);a++)//flag2=3,睡眠模式
{ch1=0x00;
outp(DA0832,ch1);
delay(0x100);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
if(f2!
=3)//小键盘有输入,跳出FOR循环
{f2=1;break;}
if(f!
=2)
{break;}
}
if(f2!
=3||f!
=2)
{break;}
outp(DA0832,0x00);
delay2(b,f_point,f2_point);
if(f2!
=3)
{f2=1;}
break;
}
}
}
outp(MY8255_MODE,0x02);
flag=f;
flag2=f2;
break;
}
//*******************************************************************
//******************flag=3则风速为强,占空比2/3**********************
case3:
{
printf("wind_strong\t");//屏幕以及指示灯提示风速
outp(MY8255_MODE,0x05);
while(f==3)
{switch(f2)
{
case1:
{outp(MY8255_MODE,0x0c);
outp(MY8255_MODE,0x09);
b=1;
for(a=0;a
{ch1=0x00;
outp(DA0832,ch1);
delay(0x50);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
}
break;
}
case2:
{outp(MY8255_MODE,0x08);
outp(MY8255_MODE,0x0b);
b=0x200000;
for(a=0;a<(b/0x28);a++)//flag2=2,自然模式
{ch1=0x00;
outp(DA0832,ch1);
delay(0x50);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
if(f2!
=2||f!
=3)
{break;}
}
if(f2!
=2||f!
=3)
{break;}
outp(DA0832,0x00);
delay2(b,f_point,f2_point);
break;
}
case3:
{outp(MY8255_MODE,0x0a);
outp(MY8255_MODE,0x0d);
b=0x400000;
for(a=0;a<(b/0x50);a++)//flag2=3,睡眠模式
{ch1=0x00;
outp(DA0832,ch1);
delay(0x50);
ch1=0xff;
outp(DA0832,ch1);
delay(0x100);
key(f_point,f2_point);
if(f2!
=3)
{f2=1;break;}
if(f!
=3)
{break;}
}
if(f2!
=3||f!
=3)
{break;}
outp(DA0832,0x00);
delay2(b,f_point,f2_point);
if(f2!
=3)
{f2=1;break;}
if(f!
=3)
{break;}
break;
}
}
}
outp(MY8255_MODE,0x04);
flag=1;
flag2=f2;
break;
}
//******************************************************************
}
return;
}
//****************************小键盘检测*****************************
voidkey(char*f_point,char*f2_point)
{charC;