原创 电子时钟设计报告

2009-5-14 22:27 7039 9 9 分类: MCU/ 嵌入式

声明:本博客内容全部原创,若要转载,请注明出处,谢谢合作!


插图的完整程序在附件中,有兴趣者下载!https://static.assets-stash.eet-china.com/album/old-resources/2009/5/13/a02e6e67-eea8-4397-b11a-0802c4beff7a.rar


目录


1 实验环境 1
1.1采用 Proteus6_9_SP5实现单片机及外围器件的仿真 1
1.2使用Keil uVision3编写本时钟程序(C语言) 1
2 原理图 2
3 程序分析及代码 3
3.1程序分析 3
3.2源代码 4
4 效果图 15
4.1正常显示效果 15
4.2闹钟设置效果 15
4.3功能选择模式效果 16
4.4调时效果 17


 


 


 



1 实验环境
1.1采用 Proteus6_9_SP5实现单片机及外围器件的仿真
如图:
 
1.2使用Keil uVision3编写本时钟程序(C语言)
如图:
 
2 原理图
 
各部分功能实现:
? 通过AT89C52的P2口控制数码管的段选,决定显示的数值;
? 通过AT89C52的P1口及38译码器控制数码管的位选,决定显示哪一位数码管;
? 通过AT89C52的P0口与1*4矩阵键盘连接执行相应功能;
? led发光二极管在闹钟定的时间到达时点亮;
? 因为P0口没有上拉电阻,所以与排阻相连。


3 程序分析及代码
3.1程序分析
3.1.1程序的优点
    首次在程序中使用了数组、指针及函数,指针做了函数的参数,大大减少了代码的编写量;
3.1.2程序的缺点
    在调试和设置闹钟时可能会出现时钟暂停的情况;设置闹钟函数不够简洁;闪烁不够稳定。
3.1.3总结
    此实验是我们学习单片机以来写的第一个较正式的程序,难免存在不足之处。


 


 


 



3.2源代码
E-clock.c程序文件:
#include "E-clock.h"
/*************以下是主函数**************/
void main()
{   
 iniTimer(); //首先初始化定时计数器
 while(1)
 { 
  display(); //调用显示函数
  keyScan(); //扫描键盘
  bellClock(); //扫描闹钟是否到点
 }
}


E-clock.h程序文件:
/*************以下是宏定义**************/
#include <reg52.h>
#define uchar unsigned char    //将unsigned char用uchar表示
#define uint unsigned int



/*************以下是功能函数声明**************/
void iniTimer();       // 定时计数器初始化函数
void display();          // 显示模式变换函数
void normalDisplay(uchar *tmp);     // 正常显示函数
void oneWeiDisplay(uchar num,uchar wei);// 一位数码管显示函数
void numCount();         // 时间进位函数
void flash(uchar num,uchar wei);   // 单位数码管闪动函数
void keyScan();           // 键盘扫描函数
void numadd(uchar *tmp);         // 数字加一函数
void bellClock();           // 闹钟定时函数
void delay();               // 延时函数
/*************以下是变量声明**************/


uchar code numTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,
0x7d, 0x07,0x7f,0x6f,0x40};  //数字字符编码表
uchar code weiTable[]={0x00,0x01,0x02,0x03,0x04,0x05,
0x06,0x07};  // 数码管位编码表
uchar numTmp[6]={0};   // 正常显示的时分秒数据存储数组
uchar bellTmp[6]={0};     // 存储闹钟时间的数据存储数组
sbit Led="P3"^0;      // 小灯的位定义
uchar time,flsh,enter,ok,value=1,move;  // 各个变量的定义


/*************以下是功能函数定义**************/
void iniTimer()
{
 EA=1; //开中断总开关
 ET1=1;  //允许T1中断
 TMOD=0x10; //T1工作于定时方式1
 TH1=(65536-50000)/256;  //送定时初值高八位
 TL1=(65536-50000)%256;  //送定时初值低八位
 TR1=1;  //启动T1工作
}
void display()

 numCount();
 if(enter==1&&ok!=1)  //当按下“进入/退出”键后,且没有//按下“确认”键时,进入功能模式,显示1
  oneWeiDisplay(value,0);
 else if(value==1)     //当显示“1”时按下“确认”键,进入//调时模式
  normalDisplay(numTmp);
 else if(value==2)     //当显示“2”时按下“确认”键,
//进入闹钟设置模式
  normalDisplay(bellTmp);
}
void normalDisplay(uchar *tmp)
{
 if(enter==1&&ok==1&&move==5)//如果进入了模式且按下了//“确认”键且选中最右边数码管
  {flash(tmp[0],7);}    //那么该位数码管闪动,此时若
//按下“加一”键可以实现加1操作
 else oneWeiDisplay(tmp[0],7);//如果没有按键,则正常显示
 if(enter==1&&ok==1&&move==4)
  {flash(tmp[1],6);}
 else oneWeiDisplay(tmp[1],6);
 oneWeiDisplay(10,5);   //秒与分中间的 “-”
 if(enter==1&&ok==1&&move==3)
  {flash(tmp[2],4);}
 else oneWeiDisplay(tmp[2],4);
 if(enter==1&&ok==1&&move==2)
  {flash(tmp[3],3);}
 else oneWeiDisplay(tmp[3],3);
 oneWeiDisplay(10,2);   //分与时之间的“-”
 if(enter==1&&ok==1&&move==1)
  {flash(tmp[4],1);}
 else oneWeiDisplay(tmp[4],1);
 if(enter==1&&ok==1&&move==0)
  {flash(tmp[5],0);}
 else oneWeiDisplay(tmp[5],0); 
}
void oneWeiDisplay(uchar num,uchar wei)
{
  P2=numTable[num];
  P1=weiTable[wei];
  delay();
  P2=0; //让数码管熄灭一下,起到消影的效果
}
void numCount() //实现秒到分,分到时的进位
{
 if(time==20)//定时计数器计数20次后 ,达到1秒,time标志//重新置为0
 {
  time=0;
  numTmp[0]++; //秒位加1
 }  
 if(numTmp[0]>9)
 {
  numTmp[0]=0;
  numTmp[1]++;
 }
if(numTmp[1]>5)
 {
  numTmp[1]=0;
  numTmp[2]++;
 }
 if(numTmp[2]>9)
 {
  numTmp[2]=0;
  numTmp[3]++;
 }
 if(numTmp[3]>5)
 {
  numTmp[3]=0;
  numTmp[4]++;
 }
 if(numTmp[4]>9)
 {
  numTmp[4]=0;
  numTmp[5]++;
 }
 if(numTmp[5]==2&&numTmp[4]==4) //到24整点时,从0点//开始重新显示
 {
  numTmp[4]=0;
  numTmp[5]=0;
 } 
}
void flash(uchar num,uchar wei)
{
 flsh++;  //让该位数码管灭6次亮一次 ,达到闪烁效果
 P2=0;
 P1=weiTable[wei];
 delay();
 if(flsh==6)
 {
  oneWeiDisplay(num,wei); 
  flsh=0;
 }
}
void keyScan()
{
 P0=0x7f;
 if(P0!=0x7f)
 {
  delay();     //键盘延时去抖 
  if(P0!=0x7f)
  {
   switch(P0)
   {
    case 0x7e:    // “进入/退出”键
    {
     enter++;   //首次按下该键后,enter标志为1,//进入功能选择模式,数码管显示一
     if(enter==2){enter=0;ok=0;value=1; }//进入功
//能模式后,再次按下“进入/退出”键
     break;      //退出到正常显示状态
    }
    case 0x7d:   // “加一”键
    { 
     if(enter==1&&ok!=1) //当按下“进入/退出”键//后,且没有按下“确认”键时,实现1和2的选择
     {
      value++;
      if(value>2)
        value=1;
     }
     if(enter==1&&ok==1)//当按下“进入/退出”键后,//且按下“确认”键后实现时间的各位加1功能
     {
      if(value==1) numadd(numTmp);//调时模式时
      if(value==2) numadd(bellTmp); //闹钟模式时
     }   
     break;
    }    
    case 0x7b:     //“移位”键
    {
     move++;   //实现数码管位的移动
     if(move>5) move="0";
     break;
    }
    case 0x77:    //“确认”键
    {
     ok=1;    //按下该键,ok标志置1
     Led=1;  //当小灯亮时,按下该键,小灯熄灭
     break;
    }
   }
   while(P0!=0x7f);  //如果按键没有松开,则一直等待
  }  
 }
}
void numadd(uchar *tmp)

 switch(move)//按照时分秒的情况,限制加数的范围
 {
    case 0: tmp[5]++;if(tmp[5]>2) tmp[5]=0; break;
case 1:tmp[4]++;if(tmp[5]==2&&tmp[4]>3)
tmp[4]=0;if(tmp[4]>9) tmp[4]=0; break;
  case 2: tmp[3]++;if(tmp[3]>6) tmp[3]=0; break;
  case 3: tmp[2]++;if(tmp[2]>9) tmp[2]=0; break;
  case 4: tmp[1]++;if(tmp[1]>6) tmp[1]=0; break;
  case 5: tmp[0]++;if(tmp[0]>9) tmp[0]=0; break;
 }
}
void bellClock()//将实际时间与设好的闹钟时间比较,如果相等,//则小灯亮

 if(bellTmp[0]==0&&bellTmp[1]==0&&bellTmp[2]==0&&bellTmp[3]==0&&bellTmp[4]==0&&bellTmp[5]==0)
  Led=1;  //因闹钟与实际时间初始值均是00-00-00,为了//程序初始时不让小灯亮,将此值屏蔽
 else if(numTmp[0]==bellTmp[0]&&numTmp[1]==bellTmp[1]&&numTmp[2]==bellTmp[2]&&numTmp[3]==bellTmp[3]&&numTmp[4]==bellTmp[4]&&numTmp[5]==bellTmp[5])       Led="0";
}
void delay() //实现短暂时间的延时
{
 uchar tmp;
 for(tmp=0;tmp<200;tmp++);
}
//以下为定时器中断函数,实现50ms的计时
void time1() interrupt 3 using 1

 TH1=(65536-50000)/256; //重新送初值
   TL1=(65536-50000)%256;
 time++;
}
4 效果图
4.1正常显示效果
 
4.2闹钟设置效果
(首次进入闹钟设置时默认为零点)
4.3功能选择模式效果
(注:1为调时)
 
(注:2为闹钟设置)
 


4.4调时效果
(注:通过按“加一”键,实现闪烁位的加一由于该位闪烁,所以截图时未显示出数字)
 


 
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
9
关闭 站长推荐上一条 /3 下一条