目录
一:任务内容
具体内容
二:整体分析
需要使用的硬件:
整体思路:
三:代码实现
(1)定时器扫描矩阵键盘
(2)初始化DS1302,数码管显示时间
(3)调节模式
(4)时钟复位
(5)时间存储和读取
(6)串口发送数据
(7)蜂鸣器
1.按键九:蜂鸣器发出提示音
2.蜂鸣器整点报时
3.闹钟
总代码
四:实验现象
五:实验总结
(1)通过矩阵按键输入调整时间
(2)使用 DS1302 计时
(3)通过数码管显示时间
(4)通过串口输出时间
(5)存储当前时间
1 、初始状态:初始状态下 DS1302 时间初始化为 12:00:00,数码管显示从 DS1302 获取的时间 其中“-”以 1s 为周期闪烁(指一段时间内亮灭各占一半,不是每隔 1 秒就闪一下下)
2 、调节模式:按下矩阵键盘中的 S4 进入调节模式 按键功能: 其中 S1 对小时进行加,S5 对小时进行减 S2 对分钟进行加,S6 对分钟进行减 S3 对秒进行 加,S7 对秒进行减;当调整某一位时,该位数字以 500ms 为周期闪烁,其余位保持不动(闪烁说明同上)
例如:当按下 S1 或者 S5 时,小时位闪烁,并且能够通过 S1 或者 S5 对该位数值进行调整; 之后当按下 S2 或者 S6 时,小时位停止闪烁,同时分钟位开始闪烁,并且能够通过 S2 或者 S6 对该位数值进行调整。
3、计时模式
按下矩阵键盘中的 S8 进入计时模式,按下 S8 时首先要将 DS1302 的时间设置为调节模式中调整的时间,然后切换到计时模式 该 模式下显示从 DS1302 中获取的时间(其实就是调节完之后的确定键)
4.其他要求
(1)任务中的所有闪烁要求用定时器实现(10 分) (2)时间的调整要注意边界(5 分) (3)按键不能影响程序的正常运行(可以简单理解为当按键按下的时候,数码管还可以正 常显示)(15 分) (4)当 S13 按下时按键按下,时钟复位到 12:00:00(10 分) (5)当按键 S14 按下时,存储当前时间(要求:当单片机重新上电时仍能够读取),当按 下 S15 时,显示上一次存储的时间(25 分) (6)当 S16 按下时,通过串口发送当前时间(25 分) (7)发挥你的创意,加入自定义功能(如使用蜂鸣器作为闹钟等)(50 分)
本次任务内容的本质是调配一个功能稍微全面一点的时钟,仅此而已。
(1)DS1302时钟芯片:作为时间的来源,为数码管显示的内容
(2)定时器:通过定时器来实现数码管的闪烁等
(3)矩阵键盘:通过矩阵键盘来切换模式
(4)数码管:显示时间
(5)AT24C20,I2C总线:用来储存数据,掉电不丢失
(6)UART:通过串口向电脑发送时间数据
(7)蜂鸣器:实现闹钟等功能(我自己加的)
(1)改造之前的矩阵键盘扫描程序,并使用定时器让单片机每隔20ms扫描一次矩阵键盘按键情况
(2)初始化DS1302,定义一个数组储存时间数据,然后让数码管显示
(3)分别对“时分秒”还有“-”定义一个闪烁标识位,方便闪烁
(4)先编写调节模式,当S4按下时,进入调节模式,此时数码管不闪烁,接下来每次按下S4“时分秒”会依次闪烁,按下S8退出调节模式
(5)时钟复位,按下S13,直接修改DS1302内的值实现时钟复位
(6)初始化AT24C20之后按下S14写入当前数据,按下S15读出并显示之前写入的数据,这里也是通过直接修改DS1302内的值实现
(7)初始化串口之后按下S16直接向电脑输入此时DS1302内的值
(8)按下S9,蜂鸣器响一下,通过快速变换蜂鸣器IO口的电平实现
(9)按下S10,进入准点报时模式,通过定时器实现
(10)按下S11,进入闹钟模式,当达到指定时间后直接让蜂鸣器响起来就行
先调一下定时器
矩阵键盘扫描代码:
函数 MatrixKey_GetState()获取扫描时刻的按键情况
函数MatrixKey_Loop(void)通过20ms前的按键情况与现在的按键情况进行对比,来判断按键是否已经按下并且松开,也就是说,如果一直按着不放,是不会调用按键对应功能的。
数码管初始化:
写一个函数表示数码管显示:
由于DS1302中的数据(时分秒)都是一位或者两位,而数码管一直显示两位数据,所以需要先把DS1302中数据的每一位取出来,于是写了一个TimeSplit(void)函数,数组DS1302_Time[]储存着当前的时间数据,让它分别对10取整或取余即可获得十位和个位。
接着TimeShow(void)函数判断完闪烁标识位之后在数码管显示时间,所有闪烁均由定时器实现.
TimeSplit(void)函数一开始我是放在主循环while(1){}里面的,但是这样的话每循环一次就要调用一次函数,误差会很大,所以把它放在定时器里面和闪烁标识位放在一起,每半秒才调用一次,误差会小很多
首先要获取当前矩阵键盘键码值:
一开始我是把MatrixKeyNum=MatrixKey();这句放在while(1){}开头,但这样似乎导致数码管卡住,所以我把它放在TimeShow()后面
定义变量Fix用来判断是否进入调节模式以及调节的是哪一位
对应闪烁标识位通过取反,再由TimeShow()函数判断是否闪烁
接下来是每一位的调节函数:
每按一下对应按键,DS1302内对应的值就会相应地改变,再通过DS1302_WriteByte()函数和TimeShow()函数数码管显示出来的值就会相应地改变
最后根据Fix的值选择对应的调节函数
退出调节模式:将标识位置0即可
也就是所谓的“确定”键.
别忘了将时分秒的闪烁标识位置0,这样就不会闪了
很简单,直接将DS1302的值改成初始值即可
这就需要储存器AT24C02和I2C总线的帮助了。
初始化:【中文注释搬不上来,就当大家都会了(】
先是I2C总线的初始化
然后是AT24C02的初始化
当按键14按下时,储存当前时间:
i是专门给for循环用的,有事先声明
然后就是数据读出了:
还是和之前一样,直接修改DS1302的值即可显示上次记录的时间
串口初始化后调用相应函数即可,但是STC-ISP那里不能显示十进制的数字,只能显示十六进制数字,凑合着看吧
就按下之后,蜂鸣器响一下,拿来凑数的(bushi
先写一个蜂鸣器自定义发声时长函数:
当按键9按下时,蜂鸣器发出提示音
比如刚到12点时,蜂鸣器响12下,说明到12点了
这里我又弄了个定时器1,全放定时器0看的有点乱
当按键10按下时,整点报时标识位置1,每次循环调用报时函数baoshi(),如果分钟和秒钟都是0,说明已经到整点了,此时启动定时器1,每隔一秒中断一次,每次蜂鸣器响一下,一共向DS1302_Time[0]下,然后关闭定时器1.
设定为11:45:14是启动闹钟
闹钟标识位是用来判断闹钟是否被调用
闹钟启动标识位是用来判断被调用的闹钟此时该不该响
逐级判断是为了减少主循环循环一次的时间。
按键12按下,关闭闹钟,只是不响而已
(已经模块化的代码并没有写在上面)
内容好多啊,这里就不展示了
本次任务使用了单片机内部的许多硬件,让我对时钟以及定时器等的原理有了更深入的理解,同时在实际操作的过程中也让我发现了自己的许多不足。
目前还有一些问题尚未得到解决:
(1)在代码没改的前提下,单片机重新上电时数码管会显示异常:比如显示“00-63-00”或“92-00-00”,目前仍不清楚是什么原因,但是重启一下又恢复正常了
(2)在代码没改的前提下,单片机重新上电时数码管会显示异常2.0:一开始显示“12-00-00”,但它会先卡一会,然后才会变化
(3)显示不准确:由于定时器,中断等各种原因,数码管每次变化的时差并不是严格的1s
(4)问题1,2都可以通过多运行几次解决
本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕,E-mail:xinmeigg88@163.com
本文链接:http://www.bhha.com.cn/news/3538.html