找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机万年历(闹钟)+秒表+音乐盒+电子琴Proteus仿真程序

[复制链接]
跳转到指定楼层
楼主
      这是我在“2020年7月初学校组织的时长一周的项目”中做的项目,提前一周的周三开始从咱论坛里参考了几个单独分开的项目来做的。由于是提前自己做的,第一天上午讲解软件安装的的时候就完成了所需要做的项目。但硬件方面只用到了C51和LCD12864,讲解项目的时候又加了一些其他的一些诸如管理时间的DS1302,管理温度的DS18B20。又把项目重做了一遍,做完之后还有点时间顺便做了做其他的几个功能。分享之前先对个人的项目进行说明:

  • 由于特殊原因,上的是网课,不在学校,所以并没有在开发板上测试,只是在仿真里可以运行。
  • 项目所用到的知识点矩阵键盘T0中断LCD12864的使用(显示屏,无字库)DS1302的使用(读写当前时间)。(DS18B20只是一个温度的数值,所以交给辅助去做了,嗯,然后就没加)。
  • 个人认为:适合拿来简单参考了解一下功能是如何实现的,不适用于研究或钻研细节方面的东西
  • 一开始源文件只是一个.c文件,只用到了T0中断来控制秒表、闹钟以及时间,并用四个直接连在C51引脚上的按钮来实现功能。
    但是后来听课了解了一丁点#include命令后,将项目拆分成了各个头文件,并加入了控制时间的DS1302来代替T0管理时间模块。
    按钮也从单独的直接连接C51的引脚,换为了一个3*3的矩阵键盘。由于矩阵键盘没有办法检测按下两个键以上的情况,所以在功能多的前提下按键的安排(哪个按键管什么功能)就开始“放飞自我”:出于做学校项目的目标是及格,所以并没有仔细去规划哪个按钮控制哪个功能,使用方法详见附件内的"说明.docx"或"说明.pdf",这里面简要介绍了功能如何使用。
  • 有关代码的解释只有项目文件的注释。
  • 仿真图我用的是:ISIS7 Professional,项目文件是Keil uVision4
  • 我觉得这个不难实现。做之前啥也不会,慢慢了解了LCD12864是如何输出的,DS1802是如何读出时间、写入时间的;以及矩阵键盘的原理后,很快很容易的就能够做出来项目,详细请百度或参考书籍文献或自行研究别人的项目。

一、功能:
  • 显示时间:

    (没有星期,初衷是想用一个算法根据当前日期算出来星期,结果没时间去做算法,所以就没加,不过如果有了参数去源代码里改改就能显示星期)
    (温度是假的,但可以根据参数修改,理论上是由DS18B20来检测温度获得温度数值,由于和时间一样,甚至都不用修改,所以就没有做)
    .
  • 秒表:

    .
  • 编辑时间:

    .
  • 闹钟:

    .
  • 音乐盒

    (两首曲子)
    .
  • 简易电子琴

    (本来没打算写,后来写音乐盒用到了28个音符的T0定时器高低八位,写在了code的数组中,结合之前调试按键用到的这个界面,花了十几分钟搞定。尽管界面不好看,但也就变成了简单的一个电子琴,不能检测多键按下的情况)
    .
  • 滚动输出(第一种,需要知道原位置是什么字符):

    另一种不完善的滚动输出(直接按行输出):

    当时这样设计是因为第一种编写代码的时候很麻烦,由于不清楚如何检测LCD12864当前屏幕的输出信息,所以有了第二种按行输出。如果知道了如何检测LCD12864的某页的某列的输出信息的话,可以优化不少的东西。


二、代码:
main.c
  1. #include<reg52.h>
  2. #include"dingyi.h"                                                            //引脚以及宏定义
  3. #include"key.h"                                                               //检测按键,以及根据按键去做什么。
  4. #include"clock.h"                                                             //DS1302的使用
  5. #include"LCD12864.h"                                                      //包含LCD12864的最基本的使用函数。
  6. #include"LCD12864_use.h"                                               //这里面包含了对LCD12864.h中写的函数的使用的函数,例如:调用kaifazhe()就能再LCD12864上输出开发者;调用ShowTime(...)可以根据参数输出时间等。
  7. #include"music.h"                                                            //这个用来播放音乐以及闹钟播放
  8. #include"show.h"                                                            //这个用来配合按键输出的,还未写入,所以没用
  9. unsigned char nowkey;                                                     //检测到的当前按下的值
  10. unsigned char state_key[3]={0,0,0};                                 //当前模块,按钮4可切换的最大值,按钮4当前状态(切换更改的数值)
  11. unsigned char clock_time[6]={0,0,0,0x31,1,0x20};              //秒、分、时、日、月、年
  12. unsigned char alarm[4]={1,10,45,23};                                //闹钟启动状态,秒、分、时
  13. unsigned char chronograph[6]={0,0,0,0,0,0};                     //百分秒、秒、分钟、小时、开启状态、暂停状态
  14. unsigned char music[4]={0,0,0,0};                                    //音乐开关状态、当前音乐、高八位、低八位
  15. unsigned int pwd;                                                           //按键检测模式计数用
  16. /************************************************************************
  17. *函数名:initT0()
  18. *函数功能:初始化T0,让T0处于一开就能使用的状态
  19. *形式参数:无
  20. *返回值:
  21. *用途:初始化
  22. *************************************************************************/
  23. void initT0()
  24. {
  25.         TMOD=0x01;                                                                                        //定时器T0工作在方式1,定时模式
  26.         TH0=(65536-10000)/256;                                                                //一次中断10ms
  27.         TL0=(65536-10000)%256;
  28.         EA=1;                                                                                                //开总中断
  29.         ET0=1;                                                                                                //定时器T0允许中断
  30.         TR0=0;                                                                                                //定时器初始处于关闭状态
  31. }
  32. /************************************************************************
  33. *函数名:initMain()
  34. *函数功能:初始化T0,lcd,时钟,让T0处于一开就能使用的状态
  35. *形式参数:无
  36. *返回值:
  37. *用途:初始化
  38. *************************************************************************/
  39. void initMain()
  40. {
  41.         init_lcd();
  42.         Clock_Fresh(clock_time);
  43.         Clock_Initial(clock_time);
  44.         initT0();
  45.         state_key[0]=0;                                                                                                   //按键状态初始化
  46.         state_key[1]=0;
  47.         state_key[2]=0;                                                                                                   
  48.         alarm[0]=1;                                                                                                           //alarm初值这样赋只是方便演示,当然这么写很不严谨!!!。闹钟设定开启
  49.         alarm[1]=0;                                                                                                           //秒→0
  50.         alarm[2]=clock_time[1]/16*10+clock_time[1]%16+1;                           //分→系统时间下一分,如果此时是59分很明显59+1就溢出了
  51.         alarm[3]=clock_time[2]/16*10+clock_time[2]%16;                                   //时→当前时
  52.         chronograph[0]=0;
  53.         chronograph[1]=0;
  54.         chronograph[2]=0;
  55.         chronograph[3]=0;
  56.         chronograph[4]=0;
  57.         chronograph[5]=0;
  58.         music[0]=0;        
  59.         music[1]=1;                                                                                                           //初始化闹钟的铃声是第二首歌曲“梦中的婚礼”
  60.         music[2]=0;        
  61.         music[3]=0;
  62. }
  63. /************************************************************************
  64. *函数名:main()
  65. *函数功能:执行主函数
  66. *形式参数:无
  67. *返回值:
  68. *用途:顺序执行编写好的程序,中间有可能被T0中断
  69. *************************************************************************/
  70. void main()
  71. {
  72.         REBEGIN:                                                                                                                //恢复出场设置时用
  73.         initMain();
  74.         Clr_Scr();
  75.         kaifazhe();                                                                                                                //这个加到这里之后删不掉了。。。删除掉反而提示内存溢出。。。
  76.         while(1)
  77.         {
  78.                 if(alarm[0]==1)                                                                                                 //检查闹钟
  79.                 if(clock_time[2]%16+clock_time[2]/16*10==alarm[3]&&
  80.                 clock_time[1]%16+clock_time[1]/16*10==alarm[2]&&
  81.                 clock_time[0]%16+clock_time[0]/16*10==alarm[1]
  82.                 )
  83.                 {
  84.                                 Clr_Scr();

  85.                                 music[0]=1;
  86.                                 while(~puzi(music));                                                                //如果按下了7键返回1才能往下执行
  87.                                 music[0]=0;
  88.                                 TR0=0;                                                           
  89.                                 alarm[0]=0;
  90.                                 Clr_Scr();
  91.                 }


  92.                 nowkey=keyyyy();                                                                                        //检测当前键
  93.                 dosomething(nowkey,state_key,clock_time,alarm,chronograph,music);                //根据当前键对数值进行改变

  94.                 //下面本来想也封装个函数,写到show.h中,但是没时间了,就不写封装了。
  95.                 if(state_key[0]==0)                                                                                                                         //0.显示模式
  96.                 {
  97.                         Clock_Fresh(clock_time);                                                                                                   //时间刷新
  98.                         ShowTime(10,alarm[0],clock_time,7);                                                                                   //输出时间
  99.                 }
  100.                 else if(state_key[0]==1)                                                                                                         //1.秒表
  101.                 {
  102.                         if(chronograph[state_Chronograph_Show_Pause]==0)                                                   //如果此时处于不处于暂停状态才播放,
  103.                                                                                                                                                                            //这里会导致换个模式后如果还是处于暂停状态
  104.                         MiaoBiao(chronograph[3],chronograph[2],chronograph[1],chronograph[0]);         //秒表模式显示        
  105.                 }
  106.                 else if(state_key[0]==2)                                                                                                         //2.编辑时间
  107.                 {
  108.                         Clock_Fresh(clock_time);                                                                                                   //时间刷新
  109.                         ShowTime(state_key[2],alarm[0],clock_time,7);                                                            //状态2输出编辑模式时间
  110.                 }
  111.                 else if(state_key[0]==3)                                                                                                         //3.编辑闹钟
  112.                 {
  113.                         ShowAlarm(alarm[0],state_key[2],alarm[3],alarm[2],alarm[1]);                            //闹钟状态显示
  114.                 }
  115.                 else if(state_key[0]==4)                                                                                                         //4.音乐盒
  116.                 {
  117.                         showmusic(music[1]);                                                                                                           //音乐模式显示
  118.                 }
  119.                 else if(state_key[0]==5)                                                                                                         //5.电子琴
  120.                 {
  121.                         while(1)
  122.                         {
  123.                                 TR0=0;
  124.                                 pwd=0;
  125.                                 nowkey=keyyyy();                                                                                                //检查按下的哪个键
  126.                                 music[2]=FREQH[nowkey+7];                                                                                //高八位赋初值
  127.                                 music[3]=FREQL[nowkey+7];                                                                                //低八位赋初值
  128.                                 showkey(nowkey);
  129.                                 TR0=1;                                                                                                                        //启动T0中断
  130.                                 music[0]=1;                                                                                                                //允许播放音乐
  131.                                 while(nowkey!=0&&nowkey==keyyyy())
  132.                                 {
  133.                                         delay(1);                                                                                                        //当有键按下,每1ms左右pwd+1(1s=1000ms)
  134.                                         pwd++;
  135.                                         if(pwd>3000&&nowkey==9)                                                                                   //9键按下了3s左右,关闭T0中断(不再响),进入内部函数
  136.                                         {        
  137.                                                 TR0=0;
  138.                                                 kaifazhe2();
  139.                                         }
  140.                                 }
  141.                                 TR0=0;
  142.                                 music[0]=0;
  143.                                 
  144.                                 if(pwd>3000)goto NEXT;                                                                                        //while内部结束后检测按键按下了几秒,如果超过了3s,跳转到NEXT
  145.                                 
  146.                         }
  147.                         NEXT:
  148.                         Clr_Scr();        
  149.                         state_key[0]=0;
  150.                 }
  151.                 else ;
  152.                 if(nowkey==9)                                                                                                                        //检查按下的按键是否是9,是的话需要按下3s左右,恢复出厂设置
  153.                 {
  154.                         pwd=0;
  155.                         for(pwd=0;pwd<300;pwd++)
  156.                         {
  157.                                 delay(10);
  158.                                 if(keyyyy()==nowkey);
  159.                                 else goto MAINEND;
  160.                         }
  161.                         goto REBEGIN;

  162.                 }
  163.                 MAINEND:;         
  164.         }
  165. }

  166. void T0int()interrupt 1
  167. {
  168.         if(music[0]==1)                                                                                                                                //T0启动,检查是否要播放音乐
  169.         {
  170.                 TH0=music[2];
  171.                 TL0=music[3];
  172.                 P3_7=~P3_7;
  173.         }
  174.         else if(chronograph[state_Chronograph_On_Off]==1)                                                        //否则再检测是否要启动秒表
  175.         {
  176.                 //给下一次定时赋值
  177.                 TH0=(65536-10000)/256;                                                                                                        //高八位赋初值
  178.                 TL0=(65536-10000)%256;                                                                                                        //低八位赋初值
  179.                 chronograph[chronograph_10ms]++;                                                                                //加百分之一秒,然后进行溢出判断以及处理
  180.                 if(chronograph[chronograph_10ms]>98)
  181.                 {
  182.                         chronograph[chronograph_10ms]=0;
  183.                         chronograph[chronograph_sec]++;
  184.                         if(chronograph[chronograph_sec]>59)
  185.                         {
  186.                                 chronograph[chronograph_sec]=0;
  187.                                 chronograph[chronograph_min]++;
  188.                         }
  189.                         if(chronograph[chronograph_min]>59)
  190.                         {
  191.                                 chronograph[chronograph_min]=0;
  192.                                 chronograph[chronograph_hour]++;
  193.                         }
  194.                         if(chronograph[chronograph_hour]>23)
  195.                         {
  196.                                 chronograph[chronograph_hour]=0;
  197.                         }
  198.                 }
  199.         }
  200.         else
  201.         {
  202.                 TR0=0;                                                                                                                                   //在不播放音乐,不启动定时器的状态下开启了定时器,则关闭定时器。
  203.         }
  204. }
复制代码


三、问题:
如mian.c代码:第75行,明明删掉一整个函数调用却提示溢出,如图:

个人在项目展示前写好了两个输出函数用来展示,但是当时也是只能放一个到主函数中,再放会溢出。后来改了改部分代码,又加了几个按钮功能才把两个输出函数都加进去。现在的状态是想删删不掉,又没想去对这个项目文件进行优化、或者深入,所以不对其进行处理。下次做小项目的时候得提前做好代码层细节上的优化,这次就不再对项目进行修改了。

四、压缩包内文件说明:
项目文件:

仿真图:


全部资料51hei下载地址:
万年历(闹钟)+秒表+音乐盒+电子琴.zip (295.56 KB, 下载次数: 94)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:782856 发表于 2020-7-18 17:27 | 只看该作者
。。。图片没加上,还有附件也没弄上,想保存草稿来着
回复

使用道具 举报

板凳
ID:328014 发表于 2020-7-19 15:39 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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