操作演示视频

51单片机制作智能时钟闹钟


文章目录

  • 操作演示视频
  • 课设的基本要求
  • 一、硬件框图
  • 二、功能描述
    • 2.1.基本功能
    • 2.2.设计要求
    • 2.3(1)时钟显示功能
    • (2)闹钟显示界面
    • 2.4按键功能
    • 2.5串口功能
    • 2.6初始状态说明
  • 三、评分标准
  • 四、 程序编写
    • 独立按键程序的编写
    • 初始化程序的编写
    • 时间程序编写
    • 串口通信程序
    • 全部代码汇总
  • 总结

课设的基本要求

1)按键灵敏,做好消抖准备;
2)数码管显示正常,无残影;
3)在任意界面,时钟走时准确,无暂停;


一、硬件框图

二、功能描述

2.1.基本功能

1) 用数码管显示时钟和闹钟两个功能界面;
2) 通过独立按键实现界面切换、参数设置等功能;
3) 通过串口接收来自单片机的信息;

2.2.设计要求

1) 显示界面切换时间:≤0.3 秒
2) 按键反应时间:≤0.2秒

2.3(1)时钟显示功能

S 8 8 20 8 22
提示符 熄灭 熄灭 20分 熄灭 22秒

(2)闹钟显示界面

P 8 8 20 8 22
提示符 熄灭 熄灭 20分 熄灭 22秒

2.4按键功能

1)按键1:定义为“界面切换”,按下按键1,切换选择时钟和闹钟界面;
2)按键2:按下2号键时,第一下为时间暂停,接着按为分钟、秒之间的选择。
3)按键3:实现数据累加功能,有界限回滚;
4)按键4:实现数据递减功能,有界限回滚;

2.5串口功能

当闹钟的时间到了,单片机给电脑发送字符串“TIME IS UP”;

2.6初始状态说明

初始状态上电默认为处于时钟显示界面,默认显示数据11分11秒

S 8 8 11 8 11
提示符 熄灭 熄灭 11分 熄灭 11秒

三、评分标准

1).上电初始化界面显示正常——10分;
2) 按键1功能正常——5分;
3) 按键2功能正常——5分;
4) 按键3功能正常——5分;
5) 按键4功能正常——5分;
6) 时钟界面显示正常——20分;
7) 闹钟界面显示正常——20分;
8) 串口功能实现——20分;
9) 代码编写整洁、清晰——10分;

四、 程序编写

独立按键程序的编写

定义三个局部变量, k1_flag, k4_flag,k5_flag,进行数据存储。
详细注释,看代码,我有标注。

void KeyScan()//按键扫描
{if(k1==0){delay(1000);//按键消抖if(k1==0)   {  k1_flag=~k1_flag;//变量取反,判断按键1按下次数if(k1_flag==0){ET0=1;} //开启定时器中断}while(k1==0);//再次判断}if(k2==0){delay(1000);if(k2==0)  {ET0=0;//关闭定时器中断if(k1_flag==0)//时钟的移位操作{k4_flag++; //数码管移位if(k4_flag==4){ET0=1;k4_flag=0;}//开启中断;重新计数操作}if(k1_flag==1)//闹钟的移位操作{k5_flag++;//闹钟数码管移位if(k5_flag==4)//数据累积到4{k5_flag=0;}//清零操作}     }while(k2==0);}if(k3==0)/*对时钟、闹钟进行加法滚动*/{delay(1000);//按键消抖if(k3==0){if(k4_flag==2)//按第一下为暂停,第二下开始对分钟开始加法运算{minute++;if(minute==60){minute=0;}}if(k4_flag==3)//第三下开始对秒进行加法运算{second++;if(second==60){second=0;}}if(k5_flag==2)//对闹钟的分中进行加法运算{minute1++;if(minute1==60){minute1=0;}}if(k5_flag==3)//对闹钟的秒进行加法运算{second1++;if(second1==60){second1=0;}}} while(k3==0);}if(k4==0) /*对时钟、闹钟进行减法滚动*/{delay(1000);if(k4==0){if(k4_flag==2)//第一下暂停,第二下对时钟的分钟进行减法运算{minute--;if(minute==-1){minute=59;}}if(k4_flag==3)//第三下对时钟的秒进行减法运算{second--;if(second==-1){second=59;}}if(k5_flag==2)//第二下对闹钟的分钟进行减法运算{minute1--;if(minute1==-1){minute1=59;}}if(k5_flag==3)//第三下对闹钟的秒进行减法运算{second1--;if(second1==-1){second1=59;}}} while(k4==0);}
}

初始化程序的编写

我是把时钟初始化程序和闹钟初始化程序分别建立了两个函数。
直接对minute和second进行编写即可改变初值。

时钟初始化;

void clock_init()
{TempData[0]=0x6d;TempData[1]=0x00;TempData[2]=0x00;TempData[3]=dofly_DuanMa[minute/10];TempData[4]=dofly_DuanMa[minute%10];TempData[5]=0x00;TempData[6]=dofly_DuanMa[second/10];TempData[7]=dofly_DuanMa[second%10];
}

闹钟初始化:

void alarm_init()
{TempData[0]=0x73;TempData[1]=0x00;TempData[2]=0x00;TempData[3]=dofly_DuanMa[minute1/10];TempData[4]=dofly_DuanMa[minute1%10];TempData[5]=0x00;TempData[6]=dofly_DuanMa[second1/10];TempData[7]=dofly_DuanMa[second1%10];
}

时间程序编写

这里我是使用定时器进实现的时间流逝,定时器的好处就是对秒的计算比较准确,而且比死循环延时函数更加稳定。
代码如下所示:

void Init_Timer0(void)//开启定时器 0
{TMOD|=0x01;TH0=(65536-2000)/256;//给初值。TL0=(65536-2000)%256;EA=1;//总中断ET0=1;//定时器中断TR0=1;//定时器开关
}
/*中断*/
void Timer0_isr(void) interrupt 1
{static unsigned int num;TH0=(65536-2000)/256;//给初值。TL0=(65536-2000)%256;num++;if(num==500) //50ms{num=0;second++;if(second==60){second=0;minute++;if(minute==60){minute=0;}}}if((minute==minute1)&&(second==second1))//相等判断条件{BEEP=!BEEP;delay(800);UART_init();UART_send_string(Buf);delay(2000);
//          TR1=0;}elseBEEP=0;
}

细心的朋友就会发现,我这里不止包括了一个定时器,还有一个定时器UART_init();它是用来实现当闹钟响起时,对电脑发送字符串的。下面我们就来讲一下它。

串口通信程序

得先说一下串口相关寄存器的基本知识(参考普中开发攻略):
(1)串口控制寄存器 SCO

SM0 和 SM1 为工作方式选择:

SM2(暂时咱们用不到):多机通信控制位,主要用于方式 2 和方式 3。当 SM2=1 时可以利用收到
的 RB8 来控制是否激活 RI(RB8=0 时不激活 RI,收到的信息丢弃;RB8=1 时收
到的数据进入 SBUF,并激活 RI,进而在中断服务中将数据从 SBUF 读走)。当
SM2=0 时,不论收到的 RB8 为 0 和 1,均可以使收到的数据进入 SBUF,并激活 RI
(即此时 RB8 不具有控制 RI 激活的功能)。通过控制 SM2,可以实现多机通信)
REN:允许串行接收位。由软件置 REN=1,则启动串行口接收数据;若软件置
REN=0,则禁止接收。
TB8:在方式 2 或方式 3 中,是发送数据的第 9 位,可以用软件规定其作用。
可以用作数据的奇偶校验位,或在多机通信中,作为地址帧/数据帧的标志位。
在方式 0 和方式 1 中,该位未用到。
RB8:在方式 2 或方式 3 中,是接收到数据的第 9 位,作为奇偶校验位或地
址帧/数据帧的标志位。在方式 1 时,若 SM2=0,则 RB8 是接收到的停止位。
TI:发送中断标志位。在方式 0 时,当串行发送第 8 位数据结束时,或在其
它方式,串行发送停止位的开始时,由内部硬件使 TI 置 1,向 CPU 发中断申请。
在中断服务程序中,必须用软件将其清 0,取消此中断申请。
RI:接收中断标志位。在方式 0 时,当串行接收第 8 位数据结束时,或在其
它方式,串行接收停止位的中间时,由内部硬件使 RI 置 1,向 CPU 发中断申请。
也必须在中断服务程序中,用软件将其清 0,取消此中断申请。
如何单片机单方面向PC端发送字符串:
参考以下代码:

u8 Buf[]="TIME IS UP!\n";//串口发送的字符串。/*开启定时器1*/
void UART_init(void)
{SCON = 0x50; //串口方式1TMOD|= 0x20; // 定时器使用方式2自动重载TH1 = 0xFD; //9600波特率对应的预设数,定时器方式2下,TH1=TL1TL1 = 0xFD;TR1 = 1;//开启定时器,开始产生波特率
}void UART_send_byte(u8 dat) //仅是发送一个字符
{SBUF = dat;       //把数据放到SBUF中while (TI == 0);//未发送完毕就等待TI=0;    //发送完毕后,要把TI重新置0
}void UART_send_string(u8 *buf)//发送一个字符串
{while (*buf != '\0'){UART_send_byte(*buf++);}
}

全部代码汇总

/*课题:用51单片机制作时钟闹钟独立按键k1为切换时钟和闹钟界面k2为通过移位对时钟闹钟是分钟还是秒进行选择k3为对分钟进行有界限的增加、k4为对秒进行有界限的减少时钟和闹钟时间相等时,蜂鸣器开始报警,串口发送“TIME IS UP!”给PC*/
#include <REGX52.H>
#define DatPort P0//数码管数据端口宏定义。
#define KeyPort P3//独立按键端口宏定义。
#define u16 unsigned int
#define u8 unsigned charunsigned char TempData[8];
bit k1_flag=0;//对位进行定义。
u8 k4_flag=0,k5_flag=0;
unsigned char minute,second,minute1,second1;//定义分、秒u8 minute=11,second=11;//时钟初始化;
u8 minute1=20,second1=22;//闹钟初始化;unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
u8 code smgduan[17]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X77,0X7C,0X39,0X5E,0X79,0X71};//数码管时钟初始化;bit UpdateTimeFlag;//读时间标志;sbit BEEP=P2^5;sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
/*各工作函数*/
void DigDisplay();
void KeyScan();
void Init_Timer0(void);
void Timer1_display(void);
void clock_init();
void alarm_init();u8 Buf[]="TIME IS UP!\n";//串口发送的字符串。void delay(u16 i)
{while(i--);
}
/*开启定时器1*/
void UART_init(void)
{SCON = 0x50; //串口方式1TMOD|= 0x20; // 定时器使用方式2自动重载TH1 = 0xFD; //9600波特率对应的预设数,定时器方式2下,TH1=TL1TL1 = 0xFD;TR1 = 1;//开启定时器,开始产生波特率
}void UART_send_byte(u8 dat) //仅是发送一个字符
{SBUF = dat;       //把数据放到SBUF中while (TI == 0);//未发送完毕就等待TI=0;    //发送完毕后,要把TI重新置0
}void UART_send_string(u8 *buf)//发送一个字符串
{while (*buf != '\0'){UART_send_byte(*buf++);}
}
/*时钟界面*/
void clock_init()
{TempData[0]=0x6d;TempData[1]=0x00;TempData[2]=0x00;TempData[3]=dofly_DuanMa[minute/10];TempData[4]=dofly_DuanMa[minute%10];TempData[5]=0x00;TempData[6]=dofly_DuanMa[second/10];TempData[7]=dofly_DuanMa[second%10];
}
/*闹钟界面*/
void alarm_init()
{TempData[0]=0x73;TempData[1]=0x00;TempData[2]=0x00;TempData[3]=dofly_DuanMa[minute1/10];TempData[4]=dofly_DuanMa[minute1%10];TempData[5]=0x00;TempData[6]=dofly_DuanMa[second1/10];TempData[7]=dofly_DuanMa[second1%10];
}
/*开启定时器0*/
void Init_Timer0(void)
{TMOD|=0x01;TH0=(65536-2000)/256;//给初值。TL0=(65536-2000)%256;EA=1;//总中断ET0=1;//定时器中断TR0=1;//定时器开关
}void main(void)
{Init_Timer0();while(1){if(k1_flag==0){clock_init();}else if(k1_flag==1){alarm_init();}KeyScan();DigDisplay();}
}void Timer0_isr(void) interrupt 1
{static unsigned int num;TH0=(65536-2000)/256;//给初值。TL0=(65536-2000)%256;num++;if(num==500) //50ms{num=0;second++;if(second==60){second=0;minute++;if(minute==60){minute=0;}}}if((minute==minute1)&&(second==second1))//相等判断条件{BEEP=!BEEP;delay(800);UART_init();UART_send_string(Buf);delay(2000);
//          TR1=0;}elseBEEP=0;
}void DigDisplay()
{u8 i=0;for(i;i<8;i++){switch(i){case(7):LSA=0;LSB=0;LSC=0;break;//0case(6):LSA=1;LSB=0;LSC=0;break;//1case(5):LSA=0;LSB=1;LSC=0;break;//2case(4):LSA=1;LSB=1;LSC=0;break;//3case(3):LSA=0;LSB=0;LSC=1;break;//4case(2):LSA=1;LSB=0;LSC=1;break;//5case(1):LSA=0;LSB=1;LSC=1;break;//6case(0):LSA=1;LSB=1;LSC=1;break;//7}P0=TempData[i];//传送段选数据;delay(100);P0=0x00;//消隐}
}void KeyScan()//按键扫描
{if(k1==0){delay(1000);if(k1==0)   {  k1_flag=~k1_flag;//取反判断按键1按下次数if(k1_flag==0){ET0=1;} //开启定时器中断}while(k1==0);}if(k2==0){delay(1000);if(k2==0)  {ET0=0;//关闭定时器中断if(k1_flag==0){k4_flag++; //数码管移位if(k4_flag==4){ET0=1;k4_flag=0;}}if(k1_flag==1){k5_flag++;if(k5_flag==4){k5_flag=0;}  }        }while(k2==0);}if(k3==0)/*对时钟、闹钟进行加法滚动*/{delay(1000);if(k3==0){if(k4_flag==2){minute++;if(minute==60){minute=0;}}if(k4_flag==3){second++;if(second==60){second=0;}}if(k5_flag==2){minute1++;if(minute1==60){minute1=0;}}if(k5_flag==3){second1++;if(second1==60){second1=0;}}} while(k3==0);}if(k4==0) /*对时钟、闹钟进行减法滚动*/{delay(1000);if(k4==0){if(k4_flag==2){minute--;if(minute==-1){minute=59;}}if(k4_flag==3){second--;if(second==-1){second=59;}}if(k5_flag==2){minute1--;if(minute1==-1){minute1=59;}}if(k5_flag==3){second1--;if(second1==-1){second1=59;}}} while(k4==0);}
}

总结

用51单片机制作智能时钟闹钟对初学者来说算是一个高级实验例程了,对编写程序的人要求细心,比如我在编写串口通信时,就发生了串口和定时器冲突,刚开始秒很正常,可是当闹钟铃声过去,串口发送完字符串后,秒数频率变得非常快,我检查了好久,最后发现TMOD没有写上与‘|’运算符!改变了在该定时器预存的值,后面的定时器配置会覆盖前一个定时器TMOD的状态值。
这就是细心问题,还有串口使用的定时器不要和时钟定时器用的一样,不然会发生冲突,导致数据读写出现问题,

课设系列:51单片机制作智能时钟闹钟相关推荐

  1. 51单片机可调时钟/闹钟(源程序+原理图+PCB+详细报告)

    51单片机可调时钟/闹钟 经过实验验证,切实可行!!配备详细代码注释!!! 功能介绍 时钟设置显示功能  这个仿真提供年份日期星期24小时格式时间显示,初始化后可以设置时间,选择模式一后可设置,通过对 ...

  2. 单片机课设基于51单片机的波形发生器(公开资源)(四种波形)(同时输出两种波形)

    单片机课设-波形发生器 前言 一.课设任务是什么? 二.如何解决这几个任务? 三.仿真原理图 四.代码 4.1 LCD1602代码 4.2 波形输出以及8*8点阵显示代码 4.3 波形选择 五.仿真源 ...

  3. C语言课设项目-51单片机-定时器和计数器

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 一.定时器的原理 1.CPU时序的有关知识 2.在学习定时器之前需要明白的 3.定时/计数器的工作原理 ...

  4. 初学51单片机制作智能小车心得

    因为以下个别错误对于刚开始接触51智能车的我来说,浪费了不少时间在这些上面,有时候人都快崩溃了

  5. 【优秀课设】51单片机LCD1602显示的温度控制系统设计 包括时间显示 校时、设置最值温度报警功能

    1.将DS18B20温度传感器的温度读出来,并在LCD1602上显示出来. 2.在LCD上分别切换显示,软件设计时钟(时.分.秒),和当前温度值,和温度上下控制值.并可以通过按键进行修改设置,温度高于 ...

  6. C语言课设项目-51单片机-数码管

    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 静态数码管 1.数码管是如何显示出字符 显示器及其接口 共阴数码管码表 开发板数码管电路图 2.数码管 ...

  7. 【资料分享】基于51单片机的智能指纹考勤系统设计-原理图-PCB-程序-报告、基于51单片机和MAX1898的智能手机充电器设计

    1661[毕设课设]基于51单片机的智能指纹考勤系统设计-原理图-PCB-程序-报告 摘 要 随着科学技术的不断发展带动着电子行业的地位越来越重,现在电子产品几乎在社会的各个领域都可以见到.这些技术的 ...

  8. 基于51单片机的自动浇花系统设计/基于51单片机的智能抽奖系统控制设计/基于51单片机的数字时钟与日历显示控制设计 毕业设计

    1147基于51单片机的自动浇花系统设计 设计思路:通湿度传感器实时监测湿度,通过LCD显示出实时的湿度采集值,可以通过按键设定目标界限,当达到这个界限值时,浇花系统的电机装置运行. 电路包含:LCD ...

  9. 智能窗帘研究制作_基于51单片机的智能窗帘的研究与设计.doc

    基于51单片机的智能窗帘的研究与设计 第 PAGE \* Arabic \* MERGEFORMAT 24 页第 PAGE \* Arabic \* MERGEFORMAT 24 页 目录 TOC \ ...

最新文章

  1. socket接收的消息怎么更新到页面_spring boot 集成 websocket 实现消息主动
  2. ZieglerNicholas PID GUI控制设计
  3. c语言程序会使cpu变高,用 C 语言写个程序,运行时,cpu占用率一直保持50%
  4. “烟花”来势汹汹!用数据可视化告诉你:台风最爱在哪登陆?
  5. SAP License:谈对财务人的解惑
  6. js值发送给php,将JSON数据从Javascript发送到PHP?
  7. 代码管理学:代码分堆
  8. python curl invalid syntax_将CURL Post转换为Python请求失败
  9. java制作数字彩虹雨的代码,canvas+gif.js打造自己的数字雨头像的示例代码
  10. CommandName属性和CommandArgument属性
  11. Windows操作技巧0001--Windows 10 修改用户名文件夹名称
  12. hive根据出生日期算年龄-粗略版
  13. 计算机excel操作知识点汇总,【计算机二级之Excel】考点汇总
  14. fastdfs断点续传
  15. 全球500强企业里用的两字母域名!
  16. 【解决方案】Error response from daemon: Conflict. The container name /mongo is already in use by contain
  17. 这些有趣的Python库一定会亮到你
  18. 最详细的北京摩托车上牌流程-自己跑流程
  19. ssm+mysql+安卓app大学生社团信息管理系统-计算机毕业设计源码99953
  20. 西门子1500与SMC EX260总线阀岛通讯组态

热门文章

  1. expressjs mp4_了解如何在ExpressJS 4.0中使用新路由器
  2. 霍兰德人格分析雷达图的两个坑
  3. 百度云盘照片导入华为相册里_怎么把云相册的照片导到手机相册里?
  4. 杰理之获取恒流充电的挡位值【篇】
  5. VR教育虚拟现实技术应用的价值
  6. 低调,中国的FPGA到底有多强?!
  7. 【优化求解】基于秃鹰算法BES求解最优目标matlab代码
  8. 教你如何使用SwipeRefreshLayout来构建一个上拉加载下拉刷新框架
  9. 怎样在matlab q-q图上读出斜率,Matlab的常见问题
  10. 美国国土安全部和MSF相继发布了Citrix漏洞的测试利用工具