高考倒计时程序求教
本帖最后由 695482588 于 2017-12-22 11:24 编辑各位坛友大家好,本人是一名中学物理老师,同时也是一名电子爱好者,也会经常做一些电子制作,但毕竟是业余学习,所以程序都是学习网上和求助网友的。
因为前两年带高三,所以用三个八段数码管做了一个高考倒计时的牌子,由于编程水平有限,所以用的是1302时钟芯片,提前在程序中设置好几月几日离高考的剩余天数,再将时间设置好。这样使用一点问题也没有,但随着其他班的使用,发现每次用之前都得重新改程序里边的日期及剩余天数,如果班级多了,所以改起来就比较费力,所以我想着能不能每次用之前,用按键将剩余天数改好,并按天倒计时,断电仍然能正常倒计时。由于水平限制,所以在这里求教一下坛友,谁有思路,请指导一下。
下面是原来的程序:
/****************高考倒计时最终程序******************/
/***************************************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
/***************************************************/
sbit sck=P3^2;//1302shift register clock input
sbit io=P3^3;
sbit rst=P3^4;
sbit rck=P1^1;//595storage register clock input
sbit scke=P1^0;//595shift register clock input
sbit de=P1^2;
/***************************************************/
uchar code smg_du[]={0xfa,0x30,0xd9,0x79,0x33,0x6b,0xeb,0x38,0xfb,0x7b};
uchar time_data={16,7,3,8,16,35,50};// 年 周 月 日 时 分 秒
uchar write_add={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};
uchar read_add={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};
uchar disp;
/***************************************************/
void write_ds1302_byte(uchar dat);
void write_ds1302(uchar add,uchar dat);
uchar read_ds1302(uchar add);
void set_rtc(void);
void read_rtc(void);
//void gkrq_judge(void);//中考日期的判断
void display(void);
void senddata(unsigned char dat);
void outall();
/***************************************************/
void delay_50us(uint t)
{
uchar j;
for(t;t>0;t--)
for(j=19;j>0;j--);
}
/***************************************************/
void write_ds1302_byte(uchar dat)
{
uint i;
for(i=0;i<8;i++)
{
sck=0;
io=dat&0x01;
dat=dat>>1;
sck=1;
}
}
/***************************************************/
void write_ds1302(uchar add,uchar dat)
{
rst=0;
_nop_();
sck=0;
_nop_();
rst=1;
_nop_();
write_ds1302_byte(add);
write_ds1302_byte(dat);
rst=0;
_nop_();
io=1;
sck=1;
}
/***************************************************/
uchar read_ds1302(uchar add)
{
uchar i,value;
rst=0;
_nop_();
sck=0;
_nop_();
rst=1;
_nop_();
write_ds1302_byte(add);
for(i=0;i<8;i++)
{
value=value>>1;
sck=0;
if(io)
value=value|0x80;
sck=1;
}
rst=0;
_nop_();
sck=0;
_nop_();
sck=1;
io=1;
return value;
}
/***************************************************/
void set_rtc(void)
{
uchar i,j;
for(i=0;i<7;i++)
{
j=time_data/10;
time_data=time_data%10;
time_data=time_data+j*16;
}
write_ds1302(0x8e,0x00);//去除写保护
for(i=0;i<7;i++)
{
write_ds1302(write_add,time_data);
}
write_ds1302(0x8e,0x80);//加上写保护
}
/***************************************************/
void read_rtc(void)
{
uchar i;
for(i=0;i<7;i++)
{
time_data=read_ds1302(read_add);
}
}
/***************************************************/
/***************************************************/
/**************************************************/
void senddata(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
scke=0;
de=dat&0x80;
scke=1;
dat=dat<<1;
}
}
/**************************************************/
void outall()
{
rck=1;
_nop_();
_nop_();
rck=0;
}
/***************************************************/
void dispaly(void)
{
senddata(smg_du);
senddata(smg_du);
senddata(smg_du);
outall();
delay_50us(10);
}
/***************************************************/
void gkrq_judge(void)
{
uchar year,mon,day,hour,bb,ss,gg;
uint dd;
year=time_data;
mon=time_data;
day=time_data;
hour=time_data;
if(hour>=0x07&&hour<0x19)
{
//2015年8月
//2016年3月
if(year=0x16&&mon==0x03&&day==0x01){dd=107;}
if(year=0x16&&mon==0x03&&day==0x02){dd=106;}
if(year=0x16&&mon==0x03&&day==0x03){dd=105;}
if(year=0x16&&mon==0x03&&day==0x04){dd=104;}
if(year=0x16&&mon==0x03&&day==0x05){dd=103;}
if(year=0x16&&mon==0x03&&day==0x06){dd=102;}
if(year=0x16&&mon==0x03&&day==0x07){dd=101;}
if(year=0x16&&mon==0x03&&day==0x08){dd=100;}
if(year=0x16&&mon==0x03&&day==0x09){dd=99;}
if(year=0x16&&mon==0x03&&day==0x10){dd=98;}
if(year=0x16&&mon==0x03&&day==0x11){dd=97;}
if(year=0x16&&mon==0x03&&day==0x12){dd=96;}
if(year=0x16&&mon==0x03&&day==0x13){dd=95;}
if(year=0x16&&mon==0x03&&day==0x14){dd=94;}
if(year=0x16&&mon==0x03&&day==0x15){dd=93;}
if(year=0x16&&mon==0x03&&day==0x16){dd=92;}
if(year=0x16&&mon==0x03&&day==0x17){dd=91;}
if(year=0x16&&mon==0x03&&day==0x18){dd=90;}
if(year=0x16&&mon==0x03&&day==0x19){dd=89;}
if(year=0x16&&mon==0x03&&day==0x20){dd=88;}
if(year=0x16&&mon==0x03&&day==0x21){dd=87;}
if(year=0x16&&mon==0x03&&day==0x22){dd=86;}
if(year=0x16&&mon==0x03&&day==0x23){dd=85;}
if(year=0x16&&mon==0x03&&day==0x24){dd=84;}
if(year=0x16&&mon==0x03&&day==0x25){dd=83;}
if(year=0x16&&mon==0x03&&day==0x26){dd=82;}
if(year=0x16&&mon==0x03&&day==0x27){dd=81;}
if(year=0x16&&mon==0x03&&day==0x28){dd=80;}
if(year=0x16&&mon==0x03&&day==0x29){dd=79;}
if(year=0x16&&mon==0x03&&day==0x30){dd=78;}
if(year=0x16&&mon==0x03&&day==0x31){dd=77;}
//2016年4月
if(year=0x16&&mon==0x04&&day==0x01){dd=76;}
if(year=0x16&&mon==0x04&&day==0x02){dd=75;}
if(year=0x16&&mon==0x04&&day==0x03){dd=74;}
if(year=0x16&&mon==0x04&&day==0x04){dd=73;}
if(year=0x16&&mon==0x04&&day==0x05){dd=72;}
if(year=0x16&&mon==0x04&&day==0x06){dd=71;}
if(year=0x16&&mon==0x04&&day==0x07){dd=70;}
if(year=0x16&&mon==0x04&&day==0x08){dd=69;}
if(year=0x16&&mon==0x04&&day==0x09){dd=68;}
if(year=0x16&&mon==0x04&&day==0x10){dd=67;}
if(year=0x16&&mon==0x04&&day==0x11){dd=66;}
if(year=0x16&&mon==0x04&&day==0x12){dd=65;}
if(year=0x16&&mon==0x04&&day==0x13){dd=64;}
if(year=0x16&&mon==0x04&&day==0x14){dd=63;}
if(year=0x16&&mon==0x04&&day==0x15){dd=62;}
if(year=0x16&&mon==0x04&&day==0x16){dd=61;}
if(year=0x16&&mon==0x04&&day==0x17){dd=60;}
if(year=0x16&&mon==0x04&&day==0x18){dd=59;}
if(year=0x16&&mon==0x04&&day==0x19){dd=58;}
if(year=0x16&&mon==0x04&&day==0x20){dd=57;}
if(year=0x16&&mon==0x04&&day==0x21){dd=56;}
if(year=0x16&&mon==0x04&&day==0x22){dd=55;}
if(year=0x16&&mon==0x04&&day==0x23){dd=54;}
if(year=0x16&&mon==0x04&&day==0x24){dd=53;}
if(year=0x16&&mon==0x04&&day==0x25){dd=52;}
if(year=0x16&&mon==0x04&&day==0x26){dd=51;}
if(year=0x16&&mon==0x04&&day==0x27){dd=50;}
if(year=0x16&&mon==0x04&&day==0x28){dd=49;}
if(year=0x16&&mon==0x04&&day==0x29){dd=48;}
if(year=0x16&&mon==0x04&&day==0x30){dd=47;}
//2016年5月
if(year=0x16&&mon==0x05&&day==0x01){dd=46;}
if(year=0x16&&mon==0x05&&day==0x02){dd=45;}
if(year=0x16&&mon==0x05&&day==0x03){dd=44;}
if(year=0x16&&mon==0x05&&day==0x04){dd=43;}
if(year=0x16&&mon==0x05&&day==0x05){dd=42;}
if(year=0x16&&mon==0x05&&day==0x06){dd=41;}
if(year=0x16&&mon==0x05&&day==0x07){dd=40;}
if(year=0x16&&mon==0x05&&day==0x08){dd=39;}
if(year=0x16&&mon==0x05&&day==0x09){dd=38;}
if(year=0x16&&mon==0x05&&day==0x10){dd=37;}
if(year=0x16&&mon==0x05&&day==0x11){dd=36;}
if(year=0x16&&mon==0x05&&day==0x12){dd=35;}
if(year=0x16&&mon==0x05&&day==0x13){dd=34;}
if(year=0x16&&mon==0x05&&day==0x14){dd=33;}
if(year=0x16&&mon==0x05&&day==0x15){dd=32;}
if(year=0x16&&mon==0x05&&day==0x16){dd=31;}
if(year=0x16&&mon==0x05&&day==0x17){dd=30;}
if(year=0x16&&mon==0x05&&day==0x18){dd=29;}
if(year=0x16&&mon==0x05&&day==0x19){dd=28;}
if(year=0x16&&mon==0x05&&day==0x20){dd=27;}
if(year=0x16&&mon==0x05&&day==0x21){dd=26;}
if(year=0x16&&mon==0x05&&day==0x22){dd=25;}
if(year=0x16&&mon==0x05&&day==0x23){dd=24;}
if(year=0x16&&mon==0x05&&day==0x24){dd=23;}
if(year=0x16&&mon==0x05&&day==0x25){dd=22;}
if(year=0x16&&mon==0x05&&day==0x26){dd=21;}
if(year=0x16&&mon==0x05&&day==0x27){dd=20;}
if(year=0x16&&mon==0x05&&day==0x28){dd=19;}
if(year=0x16&&mon==0x05&&day==0x29){dd=18;}
if(year=0x16&&mon==0x05&&day==0x30){dd=17;}
if(year=0x16&&mon==0x05&&day==0x31){dd=16;}
//2016年6月
if(year=0x16&&mon==0x06&&day==0x01){dd=15;}
if(year=0x16&&mon==0x06&&day==0x02){dd=14;}
if(year=0x16&&mon==0x06&&day==0x03){dd=13;}
if(year=0x16&&mon==0x06&&day==0x04){dd=12;}
if(year=0x16&&mon==0x06&&day==0x05){dd=11;}
if(year=0x16&&mon==0x06&&day==0x06){dd=10;}
if(year=0x16&&mon==0x06&&day==0x07){dd=9;}
if(year=0x16&&mon==0x06&&day==0x08){dd=8;}
if(year=0x16&&mon==0x06&&day==0x09){dd=7;}
if(year=0x16&&mon==0x06&&day==0x10){dd=6;}
if(year=0x16&&mon==0x06&&day==0x11){dd=5;}
if(year=0x16&&mon==0x06&&day==0x12){dd=4;}
if(year=0x16&&mon==0x06&&day==0x13){dd=3;}
if(year=0x16&&mon==0x06&&day==0x14){dd=2;}
if(year=0x16&&mon==0x06&&day==0x15){dd=1;}
if(year=0x16&&mon==0x06&&day==0x16){dd=0;}
bb=dd/100;
ss=dd%100/10;
gg=dd%10;
if(dd>99)
{
senddata(smg_du);
senddata(smg_du);
senddata(smg_du);
outall();
}
if(100>dd&&dd>9)
{
senddata(0x00);
senddata(smg_du);
senddata(smg_du);
outall();
}
if(10>dd)
{
senddata(0x00);
senddata(0x00);
senddata(smg_du);
outall();
}
}
else
{
senddata(0x00);
senddata(0x00);
senddata(0x00);
outall();
}
}
/***************************************************/
/***************************************************/
void main(void)
{
// set_rtc();
while(1)
{
read_rtc();
gkrq_judge();
delay_50us(10);
}
}
/***************************************************/
补充内容 (2017-12-25 10:53):
电路图在12楼,我的主要问题是按这个程序,断电可以计时。但是每次倒计时完毕,也就是变为0之后,再次计时又得修改程序,所以想着能不能不改程序,直接改用按键或红外遥控的方式修改时间,重复利用。 增加一个按键检测程序,长按某一键或键组合进入设置程序,再用键修改参数(变量),再按某键或键组合保存并推出开始计数,不按键则一段时间后直接推出,按原计数值计数。 这个计数器是挂在教室里的吗?加上时分秒的倒计时效果更好。 fshwen 发表于 2017-12-22 15:05
增加一个按键检测程序,长按某一键或键组合进入设置程序,再用键修改参数(变量),再按某键或键组合保存并 ...
关键是这样断电时间就按原来的设置走了啊,又不会用存储器,所以不知道该怎么做 本帖最后由 夏国特 于 2017-12-22 17:06 编辑
电池供电啊!
RTC芯片都有备用电池输入端,功耗很小的,用个3220锂电池做备用电池,掉电也继续跑。
RTC芯片内部一般都自带CMOS RAM,用这个存储高考时间,掉电也不会丢失。
还有,程序代码里那么多IF预计做判断,完全没有必要,做个表就好了嘛! 本帖最后由 fshwen 于 2017-12-22 17:25 编辑
695482588 发表于 2017-12-22 16:26
关键是这样断电时间就按原来的设置走了啊,又不会用存储器,所以不知道该怎么做
你没说清楚想解决的问题,遇到了什么样的困难。没挂电池如果停电或意外断电就会从头开始计数;最好把你用的硬件图也传上来,遇到的问题描述详细(不要怕啰嗦)。
按键不行的话就上红外遥控,不用断电就可以设置 倒计时这样搞很复杂……
给你提供一个最简单的算法:
1-设定两个参数:下一次高考日期,如2018年6月6日9时1分1秒;当前时间,如2017年12月22日21时50分1秒——这个当前时间校正后,每次都从RTC里读出。两个时间分别保存到tm结构体dest和cur里。
2-显示前,调用mktime()函数,分别把dest和cur结构体转换成1970年1月1日流逝至今的秒数:dest_s和cur_s
3-dest_s减去cur_s,即可得到现在离高考还剩下多少秒钟,然后把它除以(60*60*24)即可得到剩余天数
4-用sprintf把剩余天数转换成类似"175"这样的字符串
5-显示字符串
上文中出现的tm结构体,mktime和sprintf函数,百度搜一下,找到相应源码移植一下即可。 不知为啥,我想起三体里面质子吓人搞的那个倒计时。。。 本帖最后由 李雨萌 于 2017-12-23 20:24 编辑
个人感觉要么就复杂点,增加倒数读秒的功能,使学生看清时间的流逝,增加紧迫感。要么就简单点,弄块小黑板每天用粉笔写一次,或者找做广告的打印泡沫板每天换一下,既方便又环保。
高考日期的月份和日期直接烧写到单片机里,然后读取DS1302的当前时间,算一下离明年的高考日期有多少天,算法应该不会难,算好每个月份有多少天(包括闰年的2月)。用带有RTC的单片机和DS1302其实是一样的。 眉间尺 发表于 2017-12-22 15:33
这个计数器是挂在教室里的吗?加上时分秒的倒计时效果更好。
是在教室里的,因为是主要还是天计时,加时分秒的话数码管的数量就会增多,所以刚开始就没考虑 fshwen 发表于 2017-12-22 17:23
你没说清楚想解决的问题,遇到了什么样的困难。没挂电池如果停电或意外断电就会从头开始计数;最好把你 ...
这是我的电路图,因为倒计时牌都挂教室了,所以没办法拍照,我的主要问题是按这个程序,断电可以计时。但是每次倒计时完毕,也就是变为0之后,再次计时又得修改程序,所以想着能不能不改程序,直接改用按键或红外遥控的方式直接重新设置倒计时日期,重复使用。 简燕 发表于 2017-12-22 17:39
大概看了一下楼主的设计需求,可能麻烦点在时间数据的运算上.
"时间日期"的数据类型,通常有两种方式:
这个计时器里已经给RTC电池供电了,所以断电后还是可以继续计时,但就是倒计时变为0,重新使用时又必须改程序,所以太麻烦,想着用按键或红外遥控的方式,看了您的留言,收获还是很多,因为是业余学习,所以你所说的时间函数和加存储器还都不会,但您推荐的使用三个四位DIP开关,我感觉我还可以实现,方式也比较简单。谢谢您的指导啊 李雨萌 发表于 2017-12-23 20:15
个人感觉要么就复杂点,增加倒数读秒的功能,使学生看清时间的流逝,增加紧迫感。要么就简单点,弄块小黑板 ...
做成电子自动倒计时就是为了方便点,因为之前好多班都在使用小黑板书写倒计时,碰到周末或假期,经常会忘记修改那个时间。刚开始也考虑过增加时分秒,但由于自己编程水平限制和数码管的数量,所以就只实现了天的倒计时,日期的判断和您说的一样,只不过我没计算,是把每天的的数值事先计算出来。对于您说的带有RTC的单片机能否给说一下型号,我学习一下啊。 695482588 发表于 2017-12-25 10:51
做成电子自动倒计时就是为了方便点,因为之前好多班都在使用小黑板书写倒计时,碰到周末或假期,经常会忘 ...
stm32系列的都有rtc。不过本质上和ds1302一样的,都要纽扣电池和32768晶振。你要是不急的话,元宵节之后我帮你做一个,免费。 李雨萌 发表于 2017-12-25 10:54
stm32系列的都有rtc。不过本质上和ds1302一样的,都要纽扣电池和32768晶振。你要是不急的话,元宵节之 ...
太感谢了啊,stm32的单片机我还没学习过,所以自己还不会用,着急倒也不着急,如果您能帮我做一个的话真的太谢谢了,到时候材料钱和运费我出,我就是碍于水平有限,好多问题一直得不到解决,所以您能给点帮助我对电子制作又会学习到很多的。
页:
[1]
2