单片机课程设计报告-xx

《单片机技术与应用》

课程设计报告

题    目:   单片机小系统电子钟的设计   

院 (系):      信息科学与技术系      

专业班级:          通信1101          

学生姓名:               XX         

学    号:        20111181022          

指导教师:           XX              

20 13   12 09 日至2013  1220  日

华中科技大学武昌分校制

 目   录

一.设计题目………………………………………………………………………1

二.设计内容………………………………………………………………………1

三.硬件结构………………………………………………………………………1

四.软件思路………………………………………………………………………3

五.程序源代码……………………………………………………………………6

六.主要参考资料…………………………………………………………………14

             

一、设计题目

课题一:单片机小系统电子钟的设计

二、设计主要内容

设计制作要求:用80C51/52单片机编程控制显示的电子钟。

1)要有8位LED显示器,分别显示 “年号:月份:日期”/“时:分:秒”

例如“2005。10。 20”表示“20##年10月20日”/“10 52 49” 表示“10时52分49秒”

2)要有四位输入按键,功能分别是“移位”,“数字+”,“数字-”,“存储”

即“SHIFT”,“NUM+”,“NUM-”,“SAVE”

3)显示过程:实验板通电开机后,8位LED显示器显示“时:分:秒”

    按下“SHIFT”后第一位数字闪动,继续按下“SHIFT”后面数字闪动移位。再按“NUM+”数字增加,按“NUM-”数字减少,按“SAVE”储存修改结果。

三、硬件系统

1.单片机最小系统 AT89S52:它是一款非常适合单片机初学者学习的单片机,它完全兼容传统的8051,8031的指令系统,他的运行速度要比8051快最高支持达33MHz的晶体震荡器,在此系统中使用12MHz的晶振。AT89S52具有以下标准功能: 8k字节Flash,256字节RAM,32 位I/O 口线,看门狗定时器,2 个数据指针,三个16 位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89S52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。

 2、显示模块 :LED数码管是由发光二极管构成的,亦称半导体数码管。将条状发光二极管按照共阴极(负极)或共阳极(正极)的方法连接,组成“8”字,再把发光二极管另一电极作笔段电极,就构成了LED数码管。若按规定使某些笔段上的发光二极管发光,就能显示从0~9的?系列数字。同荧光数码管(VFD)、辉光数码管(NRT)相比,它具有:体积小、功耗低、耐震动、寿命长、亮度高、单色性好、发光响应的时间短,能与TTL、CMOS电路兼容等的数显器件。+、-分别表示公共阳极和公共阴极。a~g是7个笔段电极,DP为小数点。另有一种字高为7.6mm的超小型LED数码管,管脚从左右两排引出,小数点则是独立的。本系统利用4位LED数码管显示时间,共阴极结构。LED数码管由7段发光二极管组成,当要显示某个数字时只要将数字所对应的引脚送入低电平

 3.按键模块:本设计中主要有三个控制按键,按键功能为:(1)P3.2为调时间模式,长按P3.2进入调分状态:分单元闪烁,按P3.2加1,按P3.3减1.再长按P3.2进入时调整状态,时单元闪烁,加减调整同调分.按长按退出调整状态。(2)按P3.3进入设定闹时状态: 12:00: ,可进行分设定,按P3.4分加1,再按P3.2为时调整,按P3.4时加1,按P3.3调闹钟结束.在闹铃时可按P3.2停闹,不按闹铃1分钟。(3)按下P3.4进入秒表状态:再按P3.4秒表又启动,按P3.4暂停,再按P3.4秒表清零,按P3.4退出秒表回到时钟状态。

4.晶振模块:在AT89S52芯片内部有一个高增益反相放大器,其输入端为芯片引脚XTAL1,输出端为引脚XTAL2。而在芯片内部,XTAL1和XTAL2之间跨接晶体振荡器和微调电容,从而构成一个稳定的自激振荡器。时钟电路产生的振荡脉冲经过触发器进行二分频之后,才成为单片机的时钟脉冲信号。

5.80C52/51,8位LED显示器,CD4511-BCD译码器。参考电路如下所示:

四、软件思路 

 (一)程序分为四个部分

1》动态扫描显示LED电路程序

  设立8个内部RAM 显示缓冲区 ,将要显示的数据的BCD码送显示缓冲区,程序只需要将显示缓冲区的BCD码,送相应的端口即可。动态扫描显示

  例如:将40H-48H 为“时:分:秒”显示区

        将49H-4FH 为“年:月:日”显示区

2》动态扫描键盘程序:

       循环扫描有无按键,有:判断是何按键,转入相应子程序处理。

                      无:返回主程序执行。

    3》定时器设置与时间处理的程序:

     此段为该程序段的关键所在,它决定时间的准确性,和进位的正确性。

    定时器计数可用中断方式,也可以用软件查询方式进行。定时器中断定时方式的     精确度高。采用软件延时方式要注意每条指令的机器周期的精确计算,否则会造成时间的不准。

    4》各项功能键的子程序模块:

      ⑴移位子程序:按下“SHIFT”后左边第一位数字闪动,继续按下“SHIFT”后面数字闪动移位。程序中可设置第二显示缓冲区,将移到要闪动的数字位设为不显示(黑)“0FFH/00H”,程序只需要将两组显示缓冲区的BCD码,分时间间隔发送出去,就会产生数字闪动效果。

      ⑵数字+/-:将要显示的数据缓冲区的内容取出加一/减一,注意每个位都有自己的位限制,如“时”的位最大数23,“分、秒”最大数59,“月”最大数 12,“日” 最大数 31。两位数一起调整比较方便。还要注意的是计数后二/十进制之间的转换问题。

⑶“存储”:即将修改好的数值存储到显示缓冲区,并返回,进入主程序运行。

五.总结及体会

    通过这次的设计使我认识到本人对单片机方面的知识知道的太少了,对于书本上的很多知识还不能灵活运用,尤其是对程序设计语句的理解和运用,不能够充分理解每个语句的具体含义,导致编程的程序过于复杂,使得需要的存储空间增大。损耗了过多的内存资源。 

本次的设计使我从中学到了一些很重要的东西,那就是如何从理论到实践的转化,怎样将我所学到的知识运用到我以后的工作中去。在大学的课堂的学习只是在给我们灌输专业知识,而我们应把所学的用到我们现实的生活中去,此次的电子时钟设计给我奠定了一个实践基础,我会在以后的学习、生活中磨练自己,使自己适应于以后的竞争,同时在查找资料的过程中我也学到了许多新的知识,在和同学协作过程中增进同学间的友谊,使我对团队精神的积极性和重要性有了更加充分的理解。

通过本次设计,我们系统的了解了实时时钟的设计流程,尤其是硬、软件的设计方法,掌握了键盘显示电路的基本功能及编程方法,掌握了键盘电路和显示电路的一般原理,也进一步掌握了89S52定时器的使用和中断处理器程序的编程方法。开拓了思路,锻炼了实践动手能力,提高了分工协作能力和分析问题,解决问题的能力,达到了本次课程设计的目的。在调试电路的过程中也积累了一些宝贵的经验,比如说,在I/O口要保证标准的高电平”1”的产生,一般要上拉电阻5.1k,在一些需要高电平的地方,不能用悬空来模拟,必须严格的按照“+5v”来连接,特别是调试过程中的分部分进行很重要。

设计过程,好比是我们人类成长的历程,常有一些不如意,但毕竟这是第一次做,难免会遇到各种各样的问题。在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。我们通过查阅大量有关资料,并在小组中互相讨论,交流经验和自学,若遇到实在搞不明白的问题就会及时请教老师,使自己学到了不少知识,也经历了不少艰辛,但收获同样巨大。 在整个设计中我懂得了许多东西,也培养了我独立工作的能力,树立了对自己工作能力的信心,相信会对今后的学习工作生活有非常重要的影响。而且大大提高了动手的能力,使我充分体会到了在创造过程中探索的艰难和成功时的喜悦。虽然这个设计做的也不太好,但是在设计过程中所学到的东西是这次课程设计的最大收获和财富  

我知道,今后我的路还是很长,我要学的东西也有很多。通过这次实习,我深刻的认识到计算机专业的路的不平坦,但我会以一种良好的态度去迎接每一个挫折和挑战。

六、参考资料

[1] 陈青.单片计算机原理课程设计指导书.华中科技大学武昌分校2011.10.

[2] 姜志海.单片微机原理及应用.北京:电子工业出版社.2005.

[3] 李群芳.肖看.单片机原理、接口及应用.北京:清华大学出版社.2005.

[4] 郭天祥.新概念51单片机C语言教程.入门、提高、开发.电子工业出版社.2009

七、程序清单

#include <AT89X52.H>

unsigned char code SEG7[11]={0x3f,/*0*/

                                0x06,/*1*/

                            0x5b,/*2*/

                             0x4f,/*3*/

                             0x66,/*4*/

                             0x6d,/*5*/

                             0x7d,/*6*/

                             0x07,/*7*/

                             0x7f,/*8*/

                             0x6f,/*9*/

                             0x40,/*-*/

                             };

unsigned char key_scan[]={0xef,0xdf,0xbf,0x7f};

unsigned short int tcount;

struct time

{

    unsigned char second;

    unsigned char minute;

    unsigned char hour;

    unsigned char day;

    unsigned char month;

    unsigned char year1;

    unsigned char year2;

}time1;

void delay(k)

unsigned int k;         //延时子程序

{

    unsigned char j;

    while((k--)!=0)

    for(j=0;j<125;j++);

}

void display(DisSecondH,DisSecondL,DisMinutH,DisMinutL,DisHourH,DisHourL)

unsigned char DisSecondH,DisSecondL,DisMinutH,DisMinutL,DisHourH,DisHourL;         //显示子程序

    P0=SEG7[DisSecondH]; //显示秒钟的位

    P3=0xef;

    delay(2);

    P0=SEG7[DisSecondL]; //显示分钟的位

    P3=0xdf;

    delay(2);

    P0=0x40;                 //显示-

    P3=0xbf;

    delay(2);

   

    P0=SEG7[DisMinutH];      //显示秒钟的位

    P3=0x7f;

    delay(2);

    P0=SEG7[DisMinutL];      //显示秒钟位

    P3=0xfe;

    delay(2);

   

    P0=0x40;               //显示-

    P3=0xfd;

    delay(2);

   

    P0=SEG7[DisHourH];       //显示小时的位

    P3=0xfb;

    delay(2);

    if(DisHourL==0)

    P0=0x00;

    else

    P0=SEG7[DisHourL];       //显示小时的位

    P3=0xf7;

    delay(2);

}

void display1(DisdayH,DisdayL,DismonthH,DismonthL,Disyear1,Disyear2,Disyear3,Disyear4)

unsigned char DisdayH,DisdayL,DismonthH,DismonthL,Disyear1,Disyear2,Disyear3,Disyear4;    //显示子程序

    P0=SEG7[DisdayH];

    P3=0xef;

    delay(2);

    P0=SEG7[DisdayL];

    P3=0xdf;

    delay(2);

    P0=SEG7[DismonthH];                

    P3=0xbf;

    delay(2);

   

    P0=SEG7[DismonthL];     

    P3=0x7f;

    delay(2);

    P0=SEG7[Disyear1];      

    P3=0xfe;

    delay(2);

   

    P0=SEG7[Disyear2];              

    P3=0xfd;

    delay(2);

   

    P0=SEG7[Disyear3];      

    P3=0xfb;

    delay(2);

    P0=SEG7[Disyear4];  

    P3=0xf7;

    delay(2);

}

TimeUpDown(n,x,y)     //时钟调整子程序

unsigned  char n,x,y;

{

    if(P1_2==0)

    {

            delay(50);

            if(P1_2==0)

                    {

                        n++;

                        if(n==x)

                        n=0;

                        while(P1_2==0);

                    }  

    }

   if(P1_1==0)

    {

            delay(50);

            if(P1_1==0)

                    {

                        if(n==0)

                        n=y;

                        else

                        n--;                      

                        while(P1_1==0);

                        }

    }

    return n;

}

main()

{

    unsigned char Flag;

    TMOD = 0x01;

    TH0 = (65536-50000)/256; 

    TL0 = (65536-50000)%256;

    ET0 = 1;

    EA = 1;

P1=key_scan[1];

    while(1)

    {  

        if(P1_0==0)                     //设置标志位 Flag

        {

            delay(50);

            if(P1_0==0)

            {

                TR0 = 0;

                Flag++;

                if(Flag > 8)

                Flag = 0;

            }

            while(P1_0==0);  

        }

        switch(Flag)

        {

            case 0:

                TR0=1;

                display(time1.second%10,time1.second/10,time1.minute%10,time1.minute/10,time1.hour%10,time1.hour/10);

                break;

            case 1:                                    //时钟小时调整

                TR0=0;            

                time1.hour=TimeUpDown(time1.hour,24,23);

                display(10,10,10,10,time1.hour%10,time1.hour/10);

                break;

            case 2:                                    //时钟分钟调整

                time1.minute=TimeUpDown(time1.minute,60,59);

                display(10,10,time1.minute%10,time1.minute/10,10,10);                  

                break;

            case 3:                                    //时钟秒调整

                time1.second=TimeUpDown(time1.second,60,59);

                display(time1.second%10,time1.second/10,10,10,10,10);  

                break;

            case 4:

                time1.day=TimeUpDown(time1.day,31,30);

        display1(time1.day%10,time1.day/10,10,10,10,10,10,10);

            break;

                case 5:

                time1.month=TimeUpDown(time1.month,12,11);

        display1(10,10,time1.month%10,time1.month/10,10,10,10,10);

                break;

                    case 6:

                time1.year1=TimeUpDown(time1.year1,99,98);

        display1(10,10,10,10,time1.year1%10,time1.year1/10,10,10);

                    break;

                    case 7:

                time1.year2=TimeUpDown(time1.year2,99,98);

        display1(10,10,10,10,10,10,time1.year2%10,time1.year2/10);

                    break;

                    case 8:

        display1(time1.day%10,time1.day/10,time1.month%10,time1.month/10,time1.year1%10,time1.year1/10,time1.year2%10,time1.year2/10);

                    break;

            default:

                break;

        }

    }

}

   

       

  void t0(void) interrupt 1 using 0  

{

   

    tcount++;

    if(tcount==20)

    {

        tcount=0;

        time1.second++;

    }

    if (time1.second>=60)

   {

         time1.second=0;

         time1.minute++;

    }

    if (time1.minute>=60)

    {

        time1.minute=0;

        time1.hour++;

    }

    if(time1.hour>=24)

        time1.hour=0;

    TH0=(65536-50000)/256;

    TL0=(65536-50000)%256;

}  

   

                    课程设计成绩评定表

相关推荐