|
近些天图书馆收书,规定人离开座位不能超过15分钟不然就会把书收走,所以制作了一个计时器,用来指示人离开的时长,按照最简需求设计,计时时长为1小时,超出时间清零。
附带了一个按键,用于计时过程中的暂停,这样这个计时器可以当作秒表使用了,做个题什么的限制一下时间又不用占用手机。而且最关键的是小巧,看起来不会太蠢...
说明:
1.单片机使用STC15F104W,共有6个I/O
2.数码管为时钟样式的数码管,中间带有“:”的,焊接时按照最短路径焊接,移植程序请考虑修改smgduan[10]的段选值
3.程序定时器0初始值是在12MHz晶振下的初始值,移植程序时请注意修改
4.数码管采用74HC138+74HC595驱动,595典型连接方式到单片机普通I/O,138改为2-4线驱动,S2=0,Y0~Y3进行位选
5.清零操作就重新上电就好啦,毕竟是最简需求嘛
6.整个板子需要4根跳线,分别是
74HC595的SRCLR'到VCC
74HC138的S2到GND
板子连接时138译码器GND到供电地的跳线
板子背面使用较硬铁丝(剪下的元件引线)连接数码管第4位到138译码器Y3
程序设计思路:
初始化一个5ms的定时器,每计数200次为1s,每秒将时间值变量加一,在主程序中循环处理这个数据,对60取模得到分钟数,取余得到秒数。
将所取到的分钟和秒按位取出,得到待显示的每一位数据,存放在Display_time[4]数组中。调用数码管显示函数进行显示。
在循环中加入一个按键检测,如果按键按下,就将定时器运行位取反,实现暂停效果。
设定一个标志位point,每秒的前一半令其为1,后一半令其为0,在显示函数中对这一位进行判断,决定数码管小数点位是否亮。
注意:时钟数码管的中间“:”是第二位小数点,但是为了简便,将所有小数点全部点亮了。
- #include<STC15.H>
- #include<intrins.h>
- sbit S1=P3^0;
- sbit S2=P3^5;
- sbit SER=P3^1;
- sbit RCLK=P3^2;
- sbit SRCLK=P3^3;//74HC595管脚定义
- sbit KEY=P3^4;
- //全局变量表
- unsigned char code smgduan[10]={0xf5,0x05,0xb3,0x97,0x47,0xd6,0xf6,0x85,0xf7,0xd7};//给74HC595的段选值
- unsigned char Display_Time[4]={0,0,0,0};
- unsigned int time=0;
- unsigned char cnt=0;//定时器周期计数
- bit point=1;
- /*##############################################################################################
- 设计名称:简易一小时计时器
- 设计者:清河
- 平台:STC15F104W
- 硬件部分
- 数码管显示:位选使用74HC138改为2-4线译码、段选使用74HC595减少IO口使用
- 使用4位共阴极数码管,时钟数码管,显示无符号位
- 注意:为尽可能保证精度,晶振选取12MHz
- ##############################################################################################*/
- void delay(unsigned int cnt)//调用该函数进行一段时间的延时
- {
- while(cnt--);
- }
- void Timer0Init(void) //5毫秒@12.000MHz
- {
- EA=1;
- ET0=1;
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD &= 0xF0; //设置定时器模式
- TL0 = 0xA0; //设置定时初值
- TH0 = 0x15; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- }
- void hc595send(unsigned char dat)//使用SPI向74HC595发送一个字节的数据
- {
- unsigned char a;
- SRCLK=0;
- RCLK=0;
- for(a=0;a<8;a++)
- {
- SER=dat>>7;
- dat<<=1;
- SRCLK=1;
- _nop_();
- _nop_();
- SRCLK=0;
- }
- RCLK=1;
- _nop_();
- _nop_();
- RCLK=0;
- }
- void smgdisplay()//数码管显示函数,参数为需要显示的数组
- {
- unsigned char i;
- for(i=0;i<4;i++)
- {
- switch(i)//位选,选择点亮的数码管
- {
- case(0):
- S1=0;S2=1; break;
- case(1):
- S1=1;S2=0; break;
- case(2):
- S1=0;S2=0; break;
- case(3):
- S1=1;S2=1; break;
- }
- if(point)
- {
- hc595send(smgduan[Display_Time[i]]|0x08);
- }
- else
- {
- hc595send(smgduan[Display_Time[i]]);
- }
- delay(10); //间隔一段时间扫描
- hc595send(0x00);//消隐
- }
- }
- void main()
- {
- Timer0Init();
- while(1)
- {
- Display_Time[0]=(time/60)/10;
- Display_Time[1]=(time/60)%10;
- Display_Time[2]=(time%60)/10;
- Display_Time[3]=(time%60)%10;
- smgdisplay();
-
- if(KEY==0)
- {
- delay(5000);
- if(KEY==0)
- {
- TR0=!TR0;
- point=1;
- }
- while(!KEY);
- }
- }
- }
- void Timer0() interrupt 1
- {
- TL0 = 0xA0; //设置定时初值
- TH0 = 0x15; //设置定时初值
-
- if(cnt==200)//计数到1s
- {
- cnt=0;//清空
- point=1;//秒闪烁:亮
- time++;//时间加1秒
- }
- else
- {
- if(cnt==100)//当计数半秒
- {
- point=0;//秒闪烁:灭
- }
- cnt++;
- }
-
- if(time==3600)//满值清空
- {
- time=0;
- }
- }
复制代码 插入的代码似乎格式有问题,复制应该不影响编译,但建议下载源代码。
备注:由于该作品的耗电量很小,故使用“充满自停”的移动电源供电时,可能会出现一段时间后自动停止供电的情况,解决办法是使用无充电保护的移动电源或者增加作品负载(加几个灯什么的...)
凌净清河
虽然程序很简单,不用回帖就可以下载,但是还是很期待大家的评论呢!
简易一小时计时器 凌净清河.zip
(23.53 KB, 下载次数: 42)
|
评分
-
查看全部评分
|