原创 51开发板学习之定时器与电子钟

2008-11-4 22:26 3521 6 11 分类: MCU/ 嵌入式

已经好久没有登陆EDN了
最后一个51例程也在2个星期之前就做完了,这个时期也算是在调整吧
加入的电子园的USB学习小组,也申请了免费PCB,并且两次跑到元器件市场


终于买到了大部分的零件,下一个阶段就准备从51进阶到USB开发的学习上来


下面是我整理出来51开发板的最后一个学习程序
用定时器,按键,1602液晶做一个电子钟程序  另外说明一下,其实这并非是最


后一个我学习的51程序,只是因为那最后一个程序是运用DS12887做一个精密


的电子钟,但是12887板上没有下载口,调试起来很麻烦,为了不插拔弄坏单片


机,所以决定暂时先不做这个程序了。好了言归正传。
首先这个电子钟主要就是对51单片机的几个学习重点进行回顾和综合运用,键


盘扫描,定时器与中断,1602液晶的显示等等,如果把这个程序做好的话,基


本上51算是入门了,当然,学习之路还是很漫长的,入门不算是精通,还有很


多要继续学习掌握。
首先,我想先说说,至于C语言编程,还是能省则省,毕竟不是汇编。比如说一


个取字符串长度的函数就可以直接加入到头文件中,这样以后就不要一个个数


字符串的长度了(就视频教程的一些不尽人意之处而发,作为教学我觉得应该要


早培养学习者尽量写简洁代码的意识)。首先是位定义,这里应该基本上都没什


么问题。之后的延时函数也很有必要,我发现在大部分的学习程序中延时函数都


是必不可少的的函数。之后就是一些1602相关的字程序,在上一篇日志中已经做


了详尽描述。接着是键盘扫描程序,我觉得本程序的关键点有两个,一个就是键


盘扫描,另外一个就是中断,基本上所有的工作都要在上述两个关键点中完成。


我们设想,当定时器每1S产生一个中断,之后在中断中要刷新液晶显示,以实现


秒分时的跳动,另外一个就是我们可以通过键盘来设置时间。这就是这个电子种


的基本功能(多说两句,用定时器做的电子钟误差很大,所以这个程序没有实用


价值,纯粹是作为学习用途而已)定时器运用就很简单了,1S产生一个中断,使


得秒自加1,当然,秒分时都要做溢出判断,这是外话,之后在1602液晶中刷新


显示即可。而按键扫描稍微复杂一点,首先要先检测主按键是否按下,在主按键


按下的情况下,要把中断暂停,进而执行余下的按键扫描程序,这样的话主按键


按下后时钟就停止跳动,并且此时,假若再按下一次主按键,那么光标就会跳动


到时位上,依此类推,再按一次主按键,光标就跳到分,直至秒为止,假若光标


跳到秒以后,并无其他按键操作的情况下再按一次主按键,则光标消失,同时时


钟恢复跳动。剩下的难点就是按键扫描工作,主要是对时间+键和时间-键的检


测,时间+ 键按下一次对应的数字+1,时间-键则正好相反,只要注意这余下的


键盘扫描必需是嵌套在主按键按下时的服务程序中就可以了,这样的话基本上整


个程序就没什么难点,相当于是一个51开发板复习的好程序。



下面把代码贴出:


#include <reg52.h>
#include <string.h>
#define uchar unsigned char
sbit lcden="P2"^1;
sbit FM="P2"^2;
sbit rs="P2"^0;
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
uchar table1[]="2008-10-20 MON";
uchar table2[]="    11:58:00";
uchar i,long1,long2,cnum=0,pnum=0;
char miao="0",shi=11,fen=58;
void delay(uchar z)          //延时函数
{
 uchar x,y;
 for(x=z;x>0;x--)
  for(y=100;y>0;y--);
}
void write_con(uchar con)   //写指令函数
{
 rs=0;
 P0=con;
 delay(5);
 lcden=1;
 delay(5);
 lcden=0;
}


void write_data(uchar dat)   //写数据函数
{
 rs=1;
 P0=dat;
 delay(5);
 lcden=1;
 delay(5);
 lcden=0;
}
void init()        


//初始化函数
{
 FM=1;
 lcden=0;
 write_con(0x38);     //开显



 write_con(0x0e);     //显示


指针,不闪烁  
 write_con(0x06);     //每写


一字符指针自动+1
 write_con(0x01);     //清屏


指针归零
 write_con(0x80);     //定义


指针位置
}


void keyscan();                        //键盘扫描


void main()
{
 init();
 long1=strlen(table1);                  //取table1长度
 long2=strlen(table2);       //取talbe2长度
 for(i=0;i<long1;i++)     
 {
  write_data(table1);
  delay(30);
 }
 write_con(0x80+0x40);
 for(i=0;i<long2;i++)
 {
  write_data(table2);
  delay(30);
 }


 


 EA=1;       


  //开总中断
 ET0=1;       


  //打开定时器0
 TMOD=0x01;      


  //设置定时器工作方式为方式1
 TH0=(65536-50000)/256;     
 TL0=(65536-50000)%256;
 TR0=1; 
 while(1)
 {
  keyscan();
  if(cnum==20)
  {
   cnum=0;
   miao++;
   if(miao==60)
   {
    miao=0;
    fen++;
    if(fen==60)
    { 
     fen=0;
     shi++;
     if(shi==24)
     {
      shi=0;
      
     }
     write_con(0x80+0x44);
     write_data(0x30+shi/10);
     write_data(0x30+shi%10); 


   
    }
    write_con(0x80+0x47);
    write_data(0x30+fen/10);
    write_data(0x30+fen%10);


   }
   write_con(0x80+0x4a);
      write_data(0x30+miao/10);
      write_data(0x30+miao%10);
  }
  
 } 



 



void intertimer0() interrupt 1
{
 TH0=(65536-50000)/256;
 TL0=(65536-50000)%256;
 cnum++;
}



void keyscan()        //键盘


扫描程序
{
 if(s1==0)
 {
  delay(10);
  if(s1==0)
  {
   while(!s1);
   delay(10);
   while(!s1);
   pnum++;
   TR0=0;
   if(pnum==4)
   { 
    write_con(0x80+0x4c);
    pnum=0;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    TR0=1;
   }
  }  
 }
 if(pnum!=0)
 {
  if(pnum==1)
  {
   write_con(0x80+0x45);
   if(s2==0)
   { 
    delay(20);
    if(s2==0)
    {
     while(!s2);
     delay(20);
     while(!s2);
     shi++;
     if(shi==24)
      shi=0;
     write_con(0x80+0x44);
     write_data(0x30+shi/10);
     write_data(0x30+shi%10);
     write_con(0x80+0x45);
    }
   }
   if(s3==0)
   { 
    delay(20);
    if(s3==0)
    {
     while(!s3);
     delay(20);
     while(!s3);
     shi--;
     if(shi==-1)
      shi=23;
     write_con(0x80+0x44);
     write_data(0x30+shi/10);
     write_data(0x30+shi%10);
     write_con(0x80+0x45);
    }
   }
  }
  
  else if(pnum==2)
  {
   write_con(0x80+0x48);
   if(s2==0)
   { 
    delay(20);
    if(s2==0)
    {
     while(!s2);
     delay(20);
     while(!s2);
     fen++;
     if(fen==60)
      fen=0;
     write_con(0x80+0x47);
     write_data(0x30+fen/10);
     write_data(0x30+fen%10);
     write_con(0x80+0x48);
    }
   }
   if(s3==0)
   { 
    delay(20);
    if(s3==0)
    {
     while(!s3);
     delay(20);
     while(!s3);
     fen--;
     if(fen==-1)
      fen=59;
     write_con(0x80+0x47);
     write_data(0x30+fen/10);
     write_data(0x30+fen%10);
     write_con(0x80+0x48);
    }
   }
  }
 
  else
  {
   write_con(0x80+0x4b);
   if(s2==0)
   { 
    delay(20);
    if(s2==0)
    {
     while(!s2);
     delay(10);
     while(!s2);
     miao++;
     if(miao==60)
      miao=0;
     write_con(0x80+0x4a);
     write_data(0x30+miao/10);
     write_data(0x30+miao%10);
     write_con(0x80+0x4b);
    }
   }
   if(s3==0)
   { 
    delay(20);
    if(s3==0)
    {
     while(!s3);
     delay(20);
     while(!s3);
     miao--;
     if(miao==-1)
      miao=59;
     write_con(0x80+0x4a);
     write_data(0x30+miao/10);
     write_data(0x30+miao%10);
     write_con(0x80+0x4b);
    }
   }
  }
 }    
}                             


后记:学些51有两个月了,其实我觉得真正要入门的话,半个月够了,只是这


中间进度拖拖拉拉,并不是一直继续的而已。另外,这两个月我在学习51板的


同时也自己仿照做了一块51开发板,目前原理图和PCB图的绘制已经完毕,正


在修改错误,并在适当的时机送厂家试试自己的第一块PCB板 
 呵呵  我争取在下一篇日志中把上述的开发板原理图和PCB图都贴出来晒晒
一起学习共同进步

PARTNER CONTENT

文章评论5条评论)

登录后参与讨论

用户1480039 2008-11-11 16:43

写的不错

用户153164 2008-11-6 22:31

改了几个错别字,精华就没了~~呵呵

ilove314_323192455 2008-11-5 20:28

老赖的第一篇精华……

ilove314_323192455 2008-11-5 20:27

期待哈哈

用户1612104 2008-11-5 15:17

不错,咱们的学习进度差不多,希望以后多交流指教
相关推荐阅读
用户153164 2009-02-18 14:29
DS12887
用DS12887+1602液晶搞时钟出了问题uchar ds12887read(uchar addr){ uchar temp; CS=0; AS=0; DS=1; RW=1; AS=1; P0=ad...
用户153164 2009-02-07 14:33
继续学习51-搞个简单的方波
开年回来后,就折腾了这个小东西有人需要一个可调方波,很简单的花了2个晚上搭出来个用51单片机IO口输出的占空比和频率可调的方波 至于以后的完善当然是最好用单片机控制波形发生器芯片咯废话少说先看prot...
用户153164 2008-12-08 15:10
关于ifndef
千万不要忽略了头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明...
用户153164 2008-09-30 19:53
1602液晶初学试用
今日无事,就把1602液晶试着跟这教程走了一遍边抄边自己写  写了一点代码 感觉目前按模块来学习51还是蛮轻松的,这种学习效率也挺高的。不说了,先从原理图和1602的datasheet开始了本人的开发...
用户153164 2008-09-28 10:53
开博了
从今日开始技术类blog在Edn开博啦 我是个51单片机初学者  目前也刚进公司  什么都处于学习阶段请各位高手多多指点!...
EE直播间
更多
我要评论
5
6
关闭 站长推荐上一条 /3 下一条