秒表计时器设计报告

1、实训任务目的

1.   根据单片机课程所学内容,结合其他相关课程知识,设计电子秒表,以加深对单片机知识的理解,锻炼实践动手能力,为以后的毕业设计和工作打下坚实基础;

2.   熟悉汇编语言或C语言的程序设计方法,熟悉51系列单片机的使用;

3.   掌握单片机的内部功能模块的应用,如定时器/计数器、中断、I/O口、串行口通讯等功能;

4.   掌握单片机应用系统的软硬件设计过程、方法及实现。

2、 设计方案

  2.1系统总体设计方案

使用STC89C52单片机作为核心控制部件,采用12M晶体振荡器及30PF微小电容构成振荡电路;用1个四位一体共阴极数码显示管作为显示部分,构成数字式秒表的主体结构,配合独立式键盘和复位电路完成此秒表的计时、清零、停止、增减初始时间等各项功能。

  2.2 系统总体整体框图

 


图2.2 系统设计框图

3、 电路设计

  3.1 硬件部分系统设计

     3.1.1电路原理图

图3.1.秒表计时器电路图

1. 时钟电路 

在XTAL1、XTAL2 的引脚上外接定时元件(一个石英晶体和两个电容),内部振荡器便能产生自激振荡。在本设计中采用的12M 的石英晶振。和晶振并联的两个电容的大小对振荡频率有微小影响,可以起到频率微调作用。当采用石英晶振时,电容可以在20 ~ 40pF 之间选择。 

2.  复位电路 

复位操作通常有两种基本形式:上电自动复位和开关复位。上电瞬间,电容两端电压不能突变,此时电容的负极和RESET 相连,电压全部加在了电阻上, RESET 的输入为高,芯片被复位。随之+5V电源给电容充电,电阻上的电压逐渐减小,最后约等于0,芯片正常工作。并联在电容的两端为复位按键,当复位按键没有被按下的时候电路实现上电复位,在芯片正常工作后,通过按下按键使RST管脚出现高电平达到手动复位的效果。

3.  EA/VPP(31 脚)的功能和接法 

51 单片机的EA/VPP(31 脚)是内部和外部程序存储器的选择管脚。当EA 保持高电平时,单片机访问内部程序存储器;对于现今的绝大部分单片机来说,其内部的程序存储器(一般为flash)容量都很大,因此基本上不需要外接程序存储器,而是直接使用内部的存储器。 

4. P0 口外接上拉电阻 

51 单片机的P0 端口为开漏输出,内部无上拉电阻。所以在当做普通I/O 输出数据时,由于V2 截止,输出级是漏极开路电路,要使“1”信号(即高电平)正常输出,必须外接上拉电阻。

   3.1.2 数码管显示模块设计

显示部分采用动态显示。数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的共阴极增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的位选通端,就使各个数码管轮流受控显示,这就是动态驱动。动态显示是利用人眼视觉暂留特性来实现显示的。事实上,显示器上任何时刻只有一个数码管有显示。由于各数码管轮流显示的时间间隔短、节奏快,人的眼睛反应不过来,因此看到的是连续显示的现象。为防止闪烁延时的时间在1ms左右,不能太长,也不能太短。

3.1.3 焊接过程的问题和解决办法

     因为对焊接技术的不熟练,所以在焊接的过程中也出现了一些问题。例如出现虚焊的问题。所谓虚焊,是指焊点处只有少量锡焊住,造成接触不良,时通时断。焊接时,应保证每个焊点焊接牢固、接触良好,锡点应光亮、圆滑无毛刺,锡量适中。锡和被焊物熔合牢固,不应有虚焊。为避免虚焊,应注意以下几点:

(1)保证金属表面清洁:若焊件和焊点表面带有锈渍、污垢或氧化物,应在焊接之前用刀刮或砂纸磨,直至露出光亮金属,才能给焊件或焊点表面镀上锡。

(2)掌握温度:为了使温度适当,应根据元器件大小选用功率合适的电烙铁,并注意掌握加热时间。若用功率小的电烙铁去焊接大型元器件或在金属底板上焊接地线,易形成虚焊。

(3)上锡适量:根据所需焊点的大小来决定烙铁蘸取的锡量,使焊锡足够包裹住被焊物,形成一个大小合适且圆滑的焊点。若一次上锡不够,可再补上,但须待前次上的锡一同被熔化后再移开电烙铁。

(4)选用合适的助焊剂:助焊剂的作用是提高焊料的流动性,防止焊接面氧化,起到助焊和保护作用。焊接电子元器件时,应尽量避免使用焊锡膏。比较好的助焊剂是松香酒精溶液,焊接时,在被焊处滴上一点即可。

3.2  软件部分控制系统设计

由P1口作为独立摁键信号的输入端控制时钟的加1s、减1s、复位60.0s等操作。用外部中断0作为秒表计时器的开启和暂停的操作。且所有摁键均为低电平有效。其中部分摁键为单刀双掷开关用于控制增计时或减计时以及限60.0s计时和60.0s外计时。

3.2.1 程序流程图

图3.2

 3.2.2 程序设计

秒表程序:

#include <reg52.h>

//#include "I2C_AT24C02.h"                                     

#define uchar unsigned char

#define uint unsigned int

#define N 50000

sbit keyInc = P3^2;   //按键 +

sbit keyDec = P3^3;   //按键 -

sbit keyClear = P3^4; //按键 清零

sbit keyPause = P3^5; //按键 自增

uchar Tab1[ ]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};  //段码表

uchar Tab2[ ]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};    //个位段码表

uchar cntDeci;           //cntDeci为中断计数值

uint deciSec;        //deciSec=10*秒数值,显示的数值

//=======函数声明=======

void delay1ms(uint);

void Timer_Init();

void Display(uint);

void KeyScan();

//=======主函数=======

void main()

{    

       Timer_Init();

       deciSec=0;

       cntDeci=0;

       TR0=1;                    //开启定时器0

       while(1)

       {    

       Display(deciSec);

       KeyScan();

       }

}

/***************************延时1ms基准******************************************/

void delay1ms(uint i)

{

 uint a,b,c;

 while(i--)

 {

 for(c=0;c<1;c++)        //1ms基准延时程序 12MHZ晶振

  for(b=0;b<142;b++)

 for(a=0;a<2;a++)

{

;

 }

 }

}

/********************************************************************************

******************数码管显示程序 ***********************************************/

void Display(uint x)

{       

    P0=Tab1[x%1000/100];   //显示十位

       P2=0xfd;        //P2.1引脚输出低电平,1111 1101

        delay1ms(1);

       P2=0xff;      

    P0=Tab2[x%100/10];   //显示个位

       P2=0xfb;        //P2.2引脚输出低电平,1111 1011

        delay1ms(1);

      P2=0xff;

    P0=Tab1[x%10];  //显示0.1位

    P2=0xf7;      //P2.3引脚输出低电平,1111 0111

     delay1ms(1);

       P2=0xff;

 }

//=======定时器初始化函数=======

void Timer_Init()

{

       TMOD=0x01;                //设置定时器0为工作方式1 0000

       TH0=(65536-N)/256;        //装初值 50ms一次中断

       TL0=(65536-N)%256;

       EA=1;                     //开总中断

       ET0=1;                    //开定时器0中断

       TF0=0;             //溢出标志位清零

       TR0=0;                    //先不开启定时器0

}

//=======定时器中断服务函数=======

void Timer_Serv() interrupt 1

{

       TH0=(65536-N)/256; //50ms中断一次

       TL0=(65536-N)%256;

       cntDeci++;

        if(cntDeci==2)

        {    

         cntDeci=0; 

         deciSec=deciSec+1;                      //秒表加0.1s     

         if(deciSec==599)

         {

          deciSec=0;

         }

        }

         TF0=0;

}

//=======键盘扫描函数=======

void KeyScan()

{                         

       if(keyInc==0&TR0==0)

       {

              delay1ms(1);

              if(keyInc==0)

              {

                     deciSec+=10;

                     if(deciSec>599)             //当到60s时重新归0

                            deciSec=0;

                     while(!keyInc);         //等待按键释放

              }

       }

       if(keyDec==0&TR0==0)

       {

              delay1ms(1);

              if(keyDec==0)

              {

                     deciSec-=10;

                     if(deciSec<0)             //当到0时重新归60s

                            deciSec=599;

                     while(!keyDec);

              }

       }

       if(keyClear==0&TR0==0)

       {

              delay1ms(1);

              if(keyClear==0)

              {

                     deciSec=0;                 //清0

                     while(!keyClear);

              }

       }

       if(keyPause==0)

       {

              delay1ms(1);

              if(keyPause==0)

              {

                     TR0=~TR0;           //启动或停止定时器0

                     while(!keyPause);

              }

       }

}

60秒倒计时

#include <reg52.h>

//#include "I2C_AT24C02.h"                                     

#define uchar unsigned char

#define uint unsigned int

#define N 5000

sbit keyInc = P3^2;   //按键 +

sbit keyDec = P3^3;   //按键 -

sbit keyClear = P3^4; //按键 清零

sbit keyPause = P3^5; //按键 自增

uchar Tab1[ ]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};  //段码表

uchar Tab2[ ]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};    //个位段码表

uchar cntDeci;           //cntDeci为中断计数值

uint deciSec;        //deciSec=10*秒数值,显示的数值

//=======函数声明=======

void delay1ms(uint);

void Timer_Init();

void Display(uint);

void KeyScan();

//=======主函数=======

void main()

{    

       Timer_Init();

       deciSec=6000;

       cntDeci=0;

       TR0=1;                    //开启定时器0

       while(1)

       {    

       Display(deciSec);

       KeyScan();

       }

}

/***************************延时1ms基准******************************************/

void delay1ms(uint i)

{

 uint a,b,c;

 while(i--)

 {

 for(c=0;c<1;c++)        //1ms基准延时程序 12MHZ晶振

  for(b=0;b<142;b++)

 for(a=0;a<2;a++)

{

;

 }

 }

}

/********************************************************************************

******************数码管显示程序 ***********************************************/

void Display(uint x)

{   

       P0=Tab1[x%10000/1000];   //显示十位

       P2=0xfe;        //P2.1引脚输出低电平,1111 1101

        delay1ms(1);

       P2=0xff;

    P0=Tab2[x%1000/100];   //显示十位

       P2=0xfd;        //P2.1引脚输出低电平,1111 1101

        delay1ms(1);

       P2=0xff;      

    P0=Tab1[x%100/10];   //显示个位

       P2=0xfb;        //P2.2引脚输出低电平,1111 1011

        delay1ms(1);

      P2=0xff;

    P0=Tab1[x%10];  //显示0.1位

    P2=0xf7;      //P2.3引脚输出低电平,1111 0111

     delay1ms(1);

       P2=0xff;

 }

//=======定时器初始化函数=======

void Timer_Init()

{

       TMOD=0x01;                //设置定时器0为工作方式1 0000

       TH0=(65536-N)/256;        //装初值 50ms一次中断

       TL0=(65536-N)%256;

       EA=1;                     //开总中断

       ET0=1;                    //开定时器0中断

       TF0=0;             //溢出标志位清零

       TR0=0;                    //先不开启定时器0

}

//=======定时器中断服务函数=======

void Timer_Serv() interrupt 1

{

       TH0=(65536-N)/256; //50ms中断一次

       TL0=(65536-N)%256;

       cntDeci++;

        if(cntDeci==2)

        {    

         cntDeci=0; 

         deciSec=deciSec-1;                       //秒表加0.1s     

         if(deciSec==0)

         {

          deciSec=6000;

         }

        }

         TF0=0;

}

//=======键盘扫描函数=======

void KeyScan()

{                         

       if(keyInc==0&TR0==0)

       {

              delay1ms(1);

              if(keyInc==0)

              {

                     deciSec+=100;

                     if(deciSec>6000)             //当到60s时重新归0

                            deciSec=6000;

                     while(!keyInc);         //等待按键释放

              }

       }

       if(keyDec==0&TR0==0)

       {

              delay1ms(1);

              if(keyDec==0)

              {

                     deciSec-=100;

                     if(deciSec<0)             //当到0时重新归60s

                            deciSec=0;

                     while(!keyDec);

              }

       }

       if(keyClear==0&TR0==0)

       {

              delay1ms(1);

              if(keyClear==0)

              {

                     deciSec=6000;                 //清0

                     while(!keyClear);

              }

       }

       if(keyPause==0)

       {

              delay1ms(1);

              if(keyPause==0)

              {

                     TR0=~TR0;           //启动或停止定时器0

                     while(!keyPause);

              }

       }

}

4、制作及调试过程

  4.1 电路的制作

(1) 分析各单元电路图,并分析其各部分的功能;

(2) 用仿真软件仿真电路的功能,并检查是否有错,无误后进行下步工作;

(3) 查找有关文献了解各元件的功能及引脚和有关的资料;

(4) 分别焊接单片机最小系统、数码管显示电路和摁键控制电路,与此同时检查各元器件是否可用,并分辨其引脚;

(5) 对照事先设计好的原理图仔细检查在实物中是否有接错的地方(主要检查集成电路的引脚与导线是否出错接错和是否出现了短路),若发现有,就立即改正。以防给实物通电之后,出现意外。然后,用数字万用表检测实物中是否有不导通的地方,若有,应立即修正。以防通电后不能工作,而怀疑其他地方出错。

(6) 给实物通电,并进行调试。看电路工作是否正常。若有误,则检查并思考错误原因,然后进行修改直至电路工作正常为止。

  4.2 电路的调试

     虽然选择了用万用板来制作秒表计时器,但在制作的过程中我也遇到了许多问题。问题以及解决办法如下:

(1)问题1:由于在焊电子元件及芯片时没有注意到元件的排布以及芯片的引脚问题,使得电路板上的跳线很密,这给查线带来了很大的困难,使得最后电路错线、搭线太多。

      解决办法:我把元件以及跳线重新都焊了下来,认真反复的研究原理图的每个芯片的引脚,先用油性笔在电路板上把元件画好,然后在进行焊接。

(2)问题2:芯片引脚分布的比较紧密,所以在焊接时出现焊锡把相邻引脚连接在一起的情况。

     解决办法:吸焊器取掉部分焊锡,或用小刀划开芯片引脚的分界。

(3)问题3:倒计时不能够正常的工作,且减计时混乱。

     解决办法:重新检查程序,检查电路是否搭线。

5、 结果分析和总结

单片机课程设计,是对单片机知识的验证,可以帮助我们理解巩固所学知识,激发我们对单片机课程的兴趣,更锻炼了我们独立思考、开拓创新的能力。通过这次课程设计我也发现了自身存在的不足之处,虽然感觉理论上已经掌握,但在运用到实践的过程中仍有意想不到的困惑,经过一番努力才得以解决。这也激发了我今后努力学习的兴趣,我想这将对我以后的学习产生积极的影响。 其次,这次课程设计让我充分认识到合作的重要性,只有合作才能保证整个项目的有条不絮。在设计过程中,非常感谢老师的指导和同学们的帮助,才使设计进展的比较顺利。 在课程设计的过程中,当我们碰到不明白的问题时,指导老师总是耐心的讲解,给我的设计以极大的帮助,使我获益匪浅。因此非常感谢林金燕老师的教导。 通过这次设计,我懂得了学习的重要性,了解到理论知识与实践相结合的重要意义,学会了坚持、耐心和努力,这将为自己今后的学习和工作做出了最好的榜样。

6致谢

    在这次的实训中老师给了我很大的帮助.老师为我们指点迷津,帮助我开拓设计思路,精心点拨、鼓励。在设计过程中,不管我遇到任何问题都热心的帮我们解决。在此,感谢老师。 

总的来说,通过此次实训,完成了实训任务书规定的各项要求。 

1、通过这次实训使我学习了工程设计的一般设计理念和思路以及工程资料和文查阅、检索方法等,为今后从事电子工程设计打下良好基础。 

2、通过这次实训使我在学习单片机AT89C51、接口电路7085和Prote2004等内容的基础上,进一步学习并实践了电路制作、电路图的绘制、WORD的熟练使用、电子元器件的选择和使用方法等多种实用技术,成功设计出了基于单片机的数字式电子秒表电路。 

3、通过这次实训使我学习了不少新的知识和技术,又亲身体验方案设计、电路绘制,个人觉得收获颇丰。

参考文献 

1]李敏强, 寇纪凇, 林丹. 遗传算法的基本理论与应用[C]. 北京: 科学出版社, 2002, 370-373.

[2]王昌长, 李福祺, 高胜友. 电力设备的在线监测与故障诊断. 北京: 清华大学出版社, 2009, 370-373.      

[3]李全利,迟荣强.单片机原理及接口技术.北京:高等教育出版社,2004,125-130 

[4]杨西明,朱骐.单片机编程与应用入门.北京:机械工业出版社,2004,110-115              

附录a  元件清单

相关推荐