找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 11278|回复: 14
打印 上一主题 下一主题
收起左侧

一款51单片机电子钟制作(C语言)

  [复制链接]
跳转到指定楼层
楼主
本帖最后由 yinqing452 于 2019-8-27 12:18 编辑

/*一款电子钟程序,此电子钟是四位电子钟数码管组成的,功能分别有走时、响闹、走时间调整、闹钟时间调整等功能!调整部分分别由三个按键实现,一个功能键,一个+(加)键,另一个为-(减)键,其它功能键是复用功能!*/
硬键介绍:数码管个位.十位.百位.千位.小数点分别接P0.0 P0.1 P0.2 P0.3 P0.4。蜂鸣器接P3.5脚,功能按键接P3.2 加按键接P3.3 减按键接P3.4
以下是两张图片!!!


#include <reg52.h>//头文件
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
uchar shi,fen,nshi,nfen,mao,ding,ding1,ding3,yin;//变量定义
sbit ge=P0^0;//数码管个位
sbit shi4=P0^1;//数码管十位
sbit bai=P0^2;//数码管百位
sbit qian=P0^3;//数码管千位
sbit dian=P0^4;//两小数点位
sbit bbt=P3^5;//闹钟输出口
sbit key=P3^2;//功能按键定义
sbit key1=P3^3;//++按键定义
sbit key2=P3^4;//--按键定义
bit  a=0;//调时间功能时位定义
bit  b=0;//调小时位定义
bit  c=0;//调分钟位定义
bit  d=0;//调闹钟小位定义
bit  e=0;//调闹钟分钟定义
bit  g=0;//主程序位定义,它控制主程序中的显示子程序
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,
0x8e};//数组,即列表
void key11();//声时调时子程序
void delay(uint);//声明延时子程序
void disy(uchar,uchar);//声明时间显示子程序
void ndisy(uchar,uchar);//声明调时显示子程序1
void disy1(uchar);//声明调时时显示小时子程序
void disy2(uchar);//声明调时时显示分子程序
void chushi();//初始化程序
void bbbt();//闹钟子程序
//////////////主程序/////////////////
void main()//主程序开始
{
chushi();//初始化
while(1)//大循环
{
  if(g!=1)//如果g不等于1,就执行下一句,否则跳过下一句
  disy(fen,shi);//调用走时显示子程序
  key11();//调用按键子程序
  bbbt();//调用闹钟子程序
}
}
/////////////按键执行的子程序/////////////
void key11()//按键子函数
{

if(a!=0)//如果a不等于0,则执行大括号语句,否则跳过
{
  dian=0;//将中间两个小数点打开
  delay(10);//延时一会儿
  dian=1;//将点关掉
  delay(10);//延时一会儿,以上即是动态显示
  disy(fen,shi);//调用显示子程序
  delay(4000);//延时,使它闪烁
  }
if(b!=0)//如果b不等于0,则执行大括号语句
{
  disy1(shi);//调用小时显示子程序,此程序在前面声明
  delay(2000);//延时,即使它闪烁
  if(key1==0)//如果+按键有按下,则执行大括号内容
  {
   delay(10);//去抖
   if(key1==0)//再次判断
   {
    shi++;//确实按下了就将小时时间+1
    disy1(shi);//加1后调用小时显示子程序
    delay(10);//延时一会儿
    if(shi==24)//如果小时加到了24就执行下一个语句,否则跳过
    shi=0;//到了24就清0
   }   
  }
  if(key2==0)//如果-按键有按下,则执行大括号内容
  {
   delay(10);//去抖动
   if(key2==0)//再次确认
   {
    shi--;//确实按下就将小时减1
    disy1(shi);//调用显示程序
    delay(10);//延时
    if(shi==(0-1))//如果小时到了(0-1)时,就给23
    shi=23;//给23
   }   
  }
}
if(c!=0)//如果b不等于0,则执行大括号语句
{
  disy2(fen);//调用调分分显示子程序
  delay(2000);//使它闪动
  if(key1==0)//判断+按键是否有按下
  {
   delay(10);//延时
   if(key1==0)//再次确认按下情况
   {
    fen++;//将分加1
    disy2(fen);//调用显示子程序
    delay(10);//延时一会儿
    if(fen==60)//如果分到了60,则执行下一语句
    fen=00;//清0
   }
  }
  if(key2==0)//如果减按键按下了执行下一语句
  {
   delay(10);//延时一会儿
   if(key2==0)//再次判断
   {
    fen--;//将分减1
    disy2(fen);//调用显示子程序
    delay(10);//延时
    if(fen==(0-1))//如果分等于(0-1),则给59
    fen=59;//给59
   }
  
  }

}
if(d!=0)//如果b不等于0,则执行大括号语句
{
  ndisy(nshi,nfen);//调用闹钟显示程序
  delay(2000);//使它闪
  if(key1==0)//如果+按键按下了则执行括号内语句
  {
   delay(10);//去抖
   if(key1==0)//再次判断
   {
    nshi++;//将闹钟时加1
    ndisy(nshi,nfen);//调用显示子程序
    delay(10);//延时
    if(nshi==24)//如果等24就执行下一句话
    nshi=0;//到了24,清0
   }   
  }
  if(key2==0)//如果-按键按下了,则执行括号内容
  {
   delay(10);//去抖
   if(key2==0)//再次判断
   {
    nshi--;//自减1
    ndisy(nshi,nfen);//调用显示程序
    delay(10);//延时
    if(nshi==(0-1))//如果小时等于(0-1),就执行下一句
    nshi=23;//给23
   }   
  }
}
if(e!=0)//如果b不等于0,则执行大括号语句
{
  ndisy(nshi,nfen);//调用显示子程序
  delay(2000);//闪烁
  if(key1==0)//+按键按下了没?
  {
   delay(10);//去抖
   if(key1==0)//再次确认
   {
    nfen++;//将分加1
    ndisy(nshi,nfen);//调用显示子程序
    delay(10);//延时
    if(nfen==60)//到了60?
    nfen=00;//清0
   }
  }
  if(key2==0)//-按键有按下吗?
  {
   delay(10);//延时
   if(key2==0)//再次确认
   {
    nfen--;//分减1
    disy(nfen,nshi);//调用显示
    delay(10);//延时
    if(nfen==(0-1))//如果分等于(0-1),则执行下一句
    nfen=59;//给59
   }
  
  }
}   
}

/////////////闹钟子子程序/////////////
void bbbt()//闹钟子程序
{
  if(ding1==2)//如果计数器ding1到了2次中断?就执行括号内容
{
  ding1=0;//清0计数器
  if(shi==nshi)//走时小时时间与闹钟小时时间相等吗?
  {
   if(fen==nfen)//走时分钟时间与闹钟分钟时间相等吗?
   {
   bbt=~bbt;//将蜂呜器取反,使它发声
   }
  }
   
}
else
bbt=1;//否则将蜂呜器关掉
}

/////////////初始化子程序/////////////
void chushi()//初始化子函数
{
TMOD=0x11;//两个定时器工作在方式1方式下
EA=1;//开总中断
ET0=1;//开定时器0中断允许
ET1=1;//开定时器1中断允许
TR0=1;//开定时器0
TR1=1;//开定时器0
TH0=(65536-50000)/256;//定时器0高位赋值
TL0=(65536-50000)%256;//定时器0低位赋值
TH1=(65536-10000)/256;//定时器1高位赋值
TL1=(65536-10000)%256;//定时器1低位赋值
shi=23;//开机小时显示23
fen=59;//开机分钟显示59
nshi=12;//开机闹钟小时显示12
nfen=00;//开机闹钟分钟显示00
}

/////////////走时显示子程序/////////////
void disy(uchar shi,uchar fen)//走时显示子程序
{
P1=table[shi%10];//小时个位赋值
ge=0;//开个位位选
delay(5);//延时
ge=1;//关个位位选
P1=table[shi/10];//小时十位赋值
shi4=0;//开小时位选端
delay(5);//延时
shi4=1;//关小时位选端
P1=table[fen%10];//分钟个位赋值
bai=0;//将百位打开
delay(5);//延时
bai=1; //将百位关闭
P1=table[fen/10];//分钟十位赋值
qian=0;//打开千位位选
delay(5);//延时
qian=1; //关闭千位
}
/////////////调时显示子程序/////////////
void ndisy(uchar nshi,uchar nfen)//调时显示子程序
{
P1=table[nshi%10&0x7f];//赋值给小时个位
bai=0;//开位选
delay(30);//延时
bai=1;//关位选
P1=table[nshi/10];//赋值给小时十位
qian=0;//开位选
delay(30);//延时
qian=1;//关位选
P1=table[nfen%10];//赋值分十位
ge=0;//开位选
delay(30);//延时
ge=1; //关位选
P1=table[nfen/10];//送分个位
shi4=0;//开位选
delay(30);//延时
shi4=1; //关位选
dian=0;//小数点打开
delay(10);//延时
dian=1;//关闭
}

/////////////调时小时显示子函数/////////////
void disy1(uchar fen)//调时小时显示子函数
{
P1=table[shi%10];//送小时个位
bai=0;//打开小时个位位选
delay(40);//延时
bai=1;//关闭位选
P1=table[shi/10];//关十位代码
qian=0;//打开十位位选
delay(40);//延时
qian=1;//关闭千位
shi4=1; //关闭十位数码管
ge=1; //关闭个位数码管
}

/////////////调时分钟显示子函数/////////////
void disy2(uchar fen)//调时分钟显示子函数
{
P1=table[fen%10];//送分钟个位
ge=0;//打开分个位位选
delay(30);//关闭位选
ge=1;//关十位代码
P1=table[fen/10];//送个位代码
shi4=0;//打开位选
delay(30);//延时
shi4=1;//关闭位选
bai=1;//关闭百位数码管
qian=1; //关闭千位数码管
}

/////////////延时程序/////////////
void delay(uint z)//延时子函数
{
uint x,y;//定义局部变量
for(x=10;x>0;x--)//第一循環
for(y=z;y>0;y--);//内循环
}

/////////////T0中断服务程序/////////////
void zhong() interrupt 1//T0中断服务程序
{
TH0=(65536-50000)/256;//赋值给高位
TL0=(65536-50000)%256;//赋值给低位
ding++; //将走时计数器加1
ding1++;//将响闹计数器加1

/////////////走时程序/////////////
if(ding==10)//走时计数器到了10次中断0.5秒吗?
{
  ding=0;//清0
  dian=~dian;//将小数点取反一次
  mao++;//将秒变量加1
  if(mao==120)//如果秒变量mao到了120次中断(即1分钟),就执行下语句
  {
   mao=0;//将秒mao变量清0
   fen++;//将分变量加1
  }
  if(fen==60)//判断分变量是否到了60
  {
   fen=0;//到了就清0   
   shi++;//将小时加1
   if(shi==24)//如果小到了24就清0
   shi=0;//清0
  }     
}
  
}
/////////////T1中断服务程序/////////////
void zhong1() interrupt 3//T1中断服务程序
{
TH1=(65536-10000)/256;//赋值给高位
TL1=(65536-10000)%256;//赋值给低位
ding3++;//将按键计数器加1
/////////////一键多功能控制程序/////////////
P1=0xff;//先置P1口为高位
switch(yin)//执行一键多功能程序
{
  case 0:if(key==0)//如果0与yin比较相等,则执行break前的所有内容
  {
   delay(10);//延时
   if(ding3==3)//定时器时间到了?作用是实现长按按键才有作用的功能
   {
    ding3=0;//清0
    if(key==0)//再次确认是否有按下
    {
     yin++;//将变量加1,此句很重要,作用是以使下次按下时好执行下一开关语句
     a=1;//将a变为1,即打开按键程序中的第一段程序
     g=1;//将g变1,关闭主程序中的显示,只要按键按下的显示
     bbt=0;//将蜂呜开
     delay(100);//延时
      bbt=1;//关蜂呜器
     TR0=0;//关时间定时器,让时间停止运行,进入调整模式
     disy(fen,shi);//调用调时显示子函数
     while(!key);//按键放开了吗?
    }
   }
  }
  break;//退出开关语句
  case 1: if(key==0)//如果1与yin比较相等,则执行大括号内容
  {
   delay(10);//延时
   if(ding3==3)//定时器时间到了?作用是实现长按按键才有作用的功能
   {
    ding3=0;//清0
    if(key==0)//再次确认是否有按下
    {
     yin++;//将变量加1,此句很重要,作用是以使下次按下时好执行下一开关语句
     b=1;//将b变为1,即打开按键程序中的第二段程序
     a=0;//将a变为1,即关闭按键程序中的第一段程序
     TR0=0;//关时间定时器,让时间停止运行
     bbt=0;//将蜂呜开
     delay(100);//延时
      bbt=1;//关蜂呜器
     while(!key);//按键放开了吗?
    }
   }
  }
  break;//退出开关语句
  case 2: if(key==0)//如果2与yin比较相等,则执行大括号内容
  {
   delay(10);//延时
   if(ding3==3)//定时器时间到了?作用是实现长按按键才有作用
   {
    if(key==0)//再次确认是否有按下
    {
     yin++;//将变量加1,此句很重要,作用是以使下次按下时好执行下一开关语句
     b=0;//将b变为0,即关闭上一次功能
     a=0;//关闭上前面的功能
     c=1;//打开第三次功能
     TR0=0;//关闭定时器0
     bbt=0;//开蜂呜器
     delay(100);//延时
      bbt=1;//关蜂呜器
     while(!key);//按键放开了吗?
    }
   }
  }
  break;//退出开关语句
  case 3: if(key==0)//如果3与yin比较相等,则执行大括号内容
  {
   delay(10);//延时
   if(ding3==3)//定时器时间到了?
   {
    if(key==0)//再次确认是否有按下
    {
     yin++;//将变量加1,以便执行第五次功能
     b=0;//关闭上次功能
     a=0;//关闭上次功能
     c=0;//关闭上次功能
     d=1;//打开第四次功能
     TR0=0;////关闭定时器
     bbt=0;//开响声
     delay(100);//延时
      bbt=1;//关响
     while(!key);//按键放开了吗?
    }
   }
  }
  break;//退出开关语句
  case 4: if(key==0)//如果4与yin比较相等,则执行大括号内容
  {
   delay(10);//延时
   if(ding3==3)//定时器时间到了?
   {
    if(key==0)//再次确认是否有按下
    {
     yin++;//将变量加1,以便执行第五次功能
     b=0;//关闭上次功能
     a=0;//关闭上次功能
     c=0;//关闭上次功能
     d=0;//关闭上次功能
     e=1;//打开第五次功能
     TR0=0;////关闭定时器
     bbt=0;//开响声
     delay(100);//延时
      bbt=1;//关响
     while(!key);//按键放开了吗?
    }
   }
  }
  break;//退出开关语句
  case 5: if(key==0)//如果5与yin比较相等,则执行大括号内容
  {
   delay(10);//延时
   if(key==0)//定时器时间到了?
   {
    yin=0;//将变量清0,以复位按键功能
    a=0;//关闭上次功能
    b=0;//关闭上次功能
    c=0;//关闭上次功能
    g=0;//关闭上次功能
    d=0;//关闭上次功能
    e=0;//关闭上次功能
    TR0=1;//开定时器0,使时间走
    bbt=0;//开响声
    delay(100);//延时
     bbt=1;//关响
    while(!key);//按键放开了吗?
   }
  }
  break;//退出开关语句
}

}

d.png (12.02 KB, 下载次数: 46)

d.png

51整机--原理图--带点阵的.jpg (1.28 MB, 下载次数: 92)

51整机--原理图--带点阵的.jpg
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏8 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:405102 发表于 2019-8-26 23:31 | 只看该作者
楼主能否将电路图传上来学习学习。
回复

使用道具 举报

板凳
ID:471636 发表于 2019-8-27 08:38 | 只看该作者
这是我见到的注释最全的程度!支持一下   加油!
回复

使用道具 举报

地板
ID:156220 发表于 2019-8-27 09:12 | 只看该作者
本帖最后由 紫色的云 于 2019-8-27 09:52 编辑

注释的蛮详细的,谢谢楼主
回复

使用道具 举报

5#
ID:370644 发表于 2019-8-27 11:11 | 只看该作者
liuhiong 发表于 2019-8-26 23:31
楼主能否将电路图传上来学习学习。

可以的,我马上上传一下!
回复

使用道具 举报

6#
ID:370644 发表于 2019-8-27 11:11 | 只看该作者
liuhiong 发表于 2019-8-26 23:31
楼主能否将电路图传上来学习学习。

已上传!请查收!
回复

使用道具 举报

7#
ID:370644 发表于 2019-8-27 11:15 | 只看该作者
uvw 发表于 2019-8-27 08:38
这是我见到的注释最全的程度!支持一下   加油!

因为基础不好,所以怕以后看不懂,也为了和大家分享!
回复

使用道具 举报

8#
ID:370644 发表于 2019-8-27 11:15 | 只看该作者
紫色的云 发表于 2019-8-27 09:12
注释的蛮详细的,谢谢楼主

谢谢您的赞扬!
回复

使用道具 举报

9#
ID:61950 发表于 2019-9-1 07:47 来自手机 | 只看该作者
这是见过注释写的最全的一贴,自己学习这时也样
回复

使用道具 举报

10#
ID:619901 发表于 2019-10-26 21:15 | 只看该作者
为楼主点赞!
回复

使用道具 举报

11#
ID:619788 发表于 2019-11-5 00:17 | 只看该作者
感谢楼主的分享
回复

使用道具 举报

12#
ID:724101 发表于 2020-4-7 15:36 | 只看该作者
想要请教一下,求联系方式
回复

使用道具 举报

13#
ID:515926 发表于 2020-6-28 13:59 | 只看该作者
楼主大爱!!!

资料全面详细,为我们这样的初学者提供了很好的帮助,也坚定了学习单片机的信心。


愿您好运常在!
回复

使用道具 举报

14#
ID:853544 发表于 2020-12-17 10:03 | 只看该作者
楼主啊。。。有没有可以在Proteus 的图,和在上运行的程序
回复

使用道具 举报

15#
ID:143767 发表于 2020-12-17 15:37 | 只看该作者
上传的原理图在哪里?没有找到
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表