单片机课程设计文档格式.docx
《单片机课程设计文档格式.docx》由会员分享,可在线阅读,更多相关《单片机课程设计文档格式.docx(31页珍藏版)》请在冰豆网上搜索。
1.1外部脉冲自动计数,自动显示。
1.1.1设计一个255计数器:
0-255计数,计满后自动清0,重新计数(在数码管中显示)。
1.1.2设计一个99999计数器:
0-999999计数,计满后自动清0,重新计数(在数码管中显示)。
1.2设计一个出租车计费系统:
起步价为5元(2km以内),2km后,0.8元/0.5km;
要求每500m刷新计费一次,在8位数码管中,前三位显示数码管显示里程数,后三位数码管显示价钱(角,元,十元)
2任务分析
2.1设计一个255计数器
该设计计数范围为255,在51单片机里刚好一个字节足以,所以比较简单,脉冲计数方法可用单片机内部定时器的计数功能来实现,同样也可用外部中断的边沿触发方式实现。
但采用外部中断更耗费CPU资源,且计数最高频率比用定时器低,所以在这里我们采用定时器1的计数功能来实现。
单片机内部定时器为16位的,而这里只有用到8位,如果只按照任务要求功能来实现的话非常的简单,可以采用定时器1的工作方式1的计数方式来实现,因为当TL1中数据计到255时再来一个脉冲TL1则向TH1进位同时TL1清零,现在我们只看TL1中的变化就是从0-255不断的循环计数,这我们只需将TL1中数据译码后送入数码管显示就可了。
由于两个任务都是计满自动清零,在这里我们决定将第一个任务做成计数到255后停止计数,且数码管闪烁显示,再设置一个清零启动按键以方便控制。
在这里我们还是采用定时器1的工作方式1来实现,在主程序中可以设置一判断语句,当TL1中数据达到255时则停止计数,但是这样的话当外部脉冲频率过高时,可能会导致当TL1中数据超过255还没有来得及停止,因此我们在这里再加一层保障,启用中断来实现,需要说明的是采用中断计数也是要计到256才会产生中断的,就此会多计一个脉冲,在这里我们决定处理一下,即使是计到256我们也将它还原成255显示。
2.2设计一个99999计数器
该设计与第一个设计基本上一样,只是999999已经超出了16位,因此只有加上相应的处理才能满足要求了,但还是有很多种方法实现的,由于我采用的编程语言为C51,因此常见的方法有这两种,一是采用一个长整型变量来进行脉冲计数,二是采用六个字节计数,逢十进一的方法。
如果采用第一种方法编程稍容易,但其编译后的代码量和执行速度没第二种方法好,因此在这里我们采用第二种方法。
采用定时器1的工作方式2进行计数,设置成每来一个脉冲产生一个中断,在中断服务程序里面进行加计数。
在这里为方便控制我们还是设置一个按键,用来控制启动、停止、清零计数,当启动的
时候按下按键停止计数,当停止计数的时候按下按键启动计数,当按下按键超过1S时清零计数。
2.3设计一个出租车计费系统
该设计其实和前面两个任务差不多,只是有几个要考滤的地方,一就是车轮转一圈会产生几个脉冲,车轮的周长又为多少。
在任务中要求显示里程数和费用,根据要求我们又能找里程数和费用的关系为一个分段函数,在这里我们采用定时器1的工作方式2来对脉冲进行计数,设置定时器的初始值使之每行走一米产生一个中断,里程数在这里我们的分辨率设成0.1Km,因此要每产生一百次中断里程数加1,在数据里面加1而显示中实则为0.1Km,这是为了避免出现小数而这样计算的。
当每载完一个顾客后要对里程数进行清零或关闭系统,在这里我们设置一个按键,当按下该按键时会清零并重新计费,当按下按键超过1S关闭系统。
3硬件设计
由于三个任务在硬件功能上大体相同,因此完全可以采用同一个硬件来实现,且硬件比较简单,在这里就不单独对各个模块进行分析了。
下面就列出整体的原理图。
4软件设计
4.1255计数器
4.1.1流程图
⑴主程序流程图
⑵按键扫描函数流程图
⑶数据转换函数流程图
⑷显示函数流程图
⑸定时器0中断函数流程图
⑹定时器1中断函数流程图
4.1.2源程序
/********************************************************************
******文件名:
0-255外部脉冲计数
******功能:
对外部脉冲信号进行计数并显示脉冲范围0-255
******编写人:
电信083刘广
******版本:
******说明:
本程序以AT89S51为处理器,晶振为12MHZ编写。
采用proteus仿真
******实现,电路采用共阳极数码管,采用573和138分别做段码和位码的驱动。
******脉冲信号在实际中可能采用555构成多谐振荡器产生,在这里我们采用
******proteus自带的脉冲产生器来产生,仿真时注意脉冲信号频率不能高于
******0.5MHz,在这里为方便操作,采用一个控制按键进行控制,用来进行启动
******清零控制,当按下按键时会进行计数清零并重新开始计数,当计数达到
******255时停止计数,同时数码管闪烁显示。
*********************************************************************/
#include<
reg51.h>
//#include<
intrins.h>
absacc.h>
#defineucharunsignedchar
#defineuintunsignedint
**************************硬件声明区*********************************
********************************************************************/
#defineDispBitP2
#defineDispSegP0
#defineDispNum3
sbitKeyControl=P1^0;
**************************全局变量区*********************************
ucharcodeTAB[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
ucharDisplayBuff[DispNum],TimeCount;
bitHelpBit;
***************************函数声明区********************************
voidMCUInit();
voidDelayMs(uintDat);
voidDataConvert();
voidDisplayScan();
voidKeyScan();
**************************主程序*********************************
voidmain()
{
MCUInit();
while
(1)
{
KeyScan();
DataConvert();
DisplayScan();
}
}
*****函数名:
MCUInit()
*****输入参数:
无
*****输出参数:
*****功能:
对单片机内部资源进行初始化
voidMCUInit()
HelpBit=1;
TL1=0;
TH1=0xff;
TH0=(65536-50000)/256;
//定时
TL0=(65536-50000)%256;
TimeCount=0;
TMOD=0x51;
IE=0x8a;
DelayMs(uintDat)
Dat
延时函数,延时时间Dat*ms。
用在按键防抖和显示扫描部分。
voidDelayMs(uintDat)
uintx,y;
for(x=Dat;
x>
0;
x--)
for(y=111;
y>
y--);
DataConvert()
TL1
DisplayBuff[]
将TL1中的二进制数译成共阳极七段码给DisplayBuff数组。
voidDataConvert()
if(TL1==255)//如果计数满255则停止计数,同时置标志位
TR1=0;
TR0=1;
}
DisplayBuff[0]=TAB[TL1%10];
//分离个位并译成七段码
DisplayBuff[1]=TAB[((TL1%100)/10)];
//分离十位
DisplayBuff[2]=TAB[(TL1/100)];
//分离百位
DisplayScan()
DisplayBuff
将DisplayBuff中的数码放入数码管进行显示,动态扫描显示。
voidDisplayScan()
uchari;
if((TR0==0)||((TR0==1)&
&
(HelpBit==1)))//如果计数不满255正常显示
{//否则闪烁显示
for(i=0;
i<
DispNum;
i++)
{
DispSeg=0xff;
DispBit=i;
DispSeg=DisplayBuff[i];
DelayMs
(1);
}
P0=0xff;
P2=0xff;
KeyScan()
进行脉冲计数清零和重新启动
voidKeyScan()
if(KeyControl==0)
DelayMs(10);
//按键防抖
if(KeyControl==0)
TR0=0;
TR1=1;
HelpBit=1;
TimeCount=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TL1=0;
TH1=0xff;
while(KeyControl==0)//等待按键释放,如果按键放下则停止计数,并显示当前值
{
DataConvert();
DisplayScan();
}
}
Time0()
定时器0中断函数,用数控制数码管闪烁。
voidTime0()interrupt1
TimeCount++;
if(TimeCount==10)
HelpBit=~HelpBit;
TimeCount=0;
Time1()
定时器1中断函数,当脉冲频率过快时,由于动态扫描占用了程序
*****单次执行时间的绝大部分,且时间相对较长,有可能出现脉冲计数到255
*****无法及时停止计数,这里设立中断用当出现这种情况时进行计数器的停止
*****定时器工作方式采用方式1.
voidTime1()interrupt3
TR1=0;
TR0=1;
TL1=0xff;
4.1.3仿真截图
4.2999999计数器
4.2.1流程图
由于该设计与上一个设计大体相同,所以其流程图也大体相同,在这里只列出不同的部分。
⑴按键扫描函数流程图
⑵定时器0中断服务函数流程图
4.2.2源程序
0-99999999外部脉冲计数
对外部脉冲信号进行计数并显示脉冲范围0-99999999
******3K。
在这里为方便操作,采用一个控制按键进行控制,用来进行启动
******停止控制,当停止时按下按键启动,当启动时按下按键停止,当计数达到
******99999999自动清零。
重新计数.当按键按下超过1S清零并停止计数。
#defineDispNum8
ucharDisplayBuff[DispNum],TimeCount,CountBuff[DispNum];
//bitHelpBit;
//HelpBit=1;
//定时50ms
TMOD=0x61;
//设定T1为计数方式2工作,设定T0为定时方式1工作
//开定时器1和定时器2的中断
voidDelayMs(ui