这3天都在为这个时钟忙。。 终于写好了。。
因为水平有限,所以大部分编程技巧都是借用zjzj007在论坛发的那个纯软件时钟。
下面就来说说我的时钟。
/***********************************
软件名称:数码管显示时钟
版本:V1.0
作者:hnrain
完成时间:2008/12/7
功能描述:完成基本的时钟功能。24小时制
有三个按键分别为set键K1,调整加键K2,调整减键K3。
按一次set键,进入分设置.分钟位闪烁,此时按k2分钟加,按k3分钟减。
第二次按set键,进入时设置.时钟位闪烁,此时按k2分钟加,按k3分钟减。
第三次按set键,退出,显示为调整后的时间。
************************************/
呵呵。。这算是最简单的时钟了。。。我将陆续改写其他版本。程序内部有较详细的说明。
这一次我将结合我的时钟讲时钟算法,也就是编程思路。
时钟也就是让秒分达到60时,时达到24时自动加1,进位。通过按键让其进入特定的函数执行程序进行相应操作。
我的时钟程序中用到的函数:
delay(uchar i)
void timer1() interrupt 3
void display(uchar seg_count)
void timer0() interruption 1
uchar keyscan()
void setadd()
void setdec()
void main()
主要的执行过程:没有按键时。始终执行主程序判断按键情况,并通过两个中断自动的进行时间加,和显示。有按键时跳到相应的按键程序执行。
我们写的每个函数都要用到执行,要么是被其他函数调用,要么自动执行。
如
uchar keyscan()
void setadd()
void setdec()
delay(uchar i)
void display(uchar seg_count)
就是被其他函数调用执行。
而
void main()
void timer1() interrupt 3
void timer0() interruption 1
就是被自动执行的!!
算法就是这样。具体的编写技巧。就要看大家的编写程序了。。这方面我也是菜鸟刚学。。
这几天通过分析,编程学到很多东西1!
呵呵。。。
我希望和大家一起共同学习,进步。。
下面是代码,可以下载压缩包.
/***********************************
软件名称:数码管显示时钟
版本:V1.0
作者:hnrain
完成时间:2008/12/7
功能描述:完成基本的时钟功能。24小时制
有三个按键分别为set键K1,调整加键K2,调整减键K3。
按一次set键,进入分设置.分钟位闪烁,此时按k2分钟加,按k3分钟减。
第二次按set键,进入时设置.时钟位闪烁,此时按k2分钟加,按k3分钟减。
第三次按set键,退出,显示为调整后的时间。
************************************/
#include "reg51.h"
#define uchar unsigned char
#define uint unsigned int
uchar reg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
// 分别是0,1,2,3,4,5,6,7,8,9,消隐
uchar dis[4]={0};
uchar miao="0",fen=30,shi=12,key_count,t=0,seg_count=0,key=0;
/********************
函数名:delay(uchar i)
函数功能:消除键盘抖动,被uchar keyscan()函数调用
调用变量:局部变量j
********************/
void delay(uchar i)
{
uchar j;
while(i--)
{
for(j=0;j<200;j++);
}
}
/**************************************
函数名:void timer1() interrupt 3
函数功能:定时计数中断 ,时间进位
调到变量:全局变量t
***************************************/
void timer1() interrupt 3
{
TF1=0;
TH1=((65536-45900)/256);
TL1=((65536-45900)%256); //因为是采用方式1,这里是重新装载数据
t++;
while(t==20) //定时器1定时50MS,中断20次就是1S
{
t="0";
miao++;
if(miao==60)
{
miao="0";
fen++;
if(fen==60)
{
fen="0";
shi++;
if(shi==24)
{
shi="0";
}
}//fen
}//miao
}
}
/******************************
函数名:void display(uchar seg_count)
函数功能:将时钟数据送到数码管中显示。对数码管进行扫描,判断按键情况并做出是否闪动的操作!
调用函数:被void timer0() interrupt 1函数调用。
**********************************/
void display(uchar i)
{
switch(i)
{
case 0: P1=0xfe; //通过seg_count函数的值判断选通那个数码管
break;
case 1: P1=0xfd;
break;
case 2: P1=0xfb;
break;
case 3: P1=0xf7;
break;
default: break;
}
dis[0]=shi/10; //将需要显示的数据放到数组中缓存。
dis[1]=shi%10;
dis[2]=fen/10;
dis[3]=fen%10;
if(key_count==0) //没有按键时,让第二个数码管的小数点每半秒闪动一次。
{
if((seg_count==1)&&(t<10))
P0=(reg[dis[seg_count]]&0x7f);
else P0=reg[dis[seg_count]];
}
else if(key_count==1) //set键按了一次,让分钟位闪烁
{
if(seg_count==3|seg_count==2)
{
if(t<10) P0=reg[dis[seg_count]];
else P0=reg[10]; //让数码管灭,就输出0xff
}
else {
P0=reg[dis[seg_count]];
}
}
else if(key_count==2) //set键按了两次,让时钟位闪烁
{
if(seg_count==0|seg_count==1)
{
if(t<10) P0=reg[dis[seg_count]];
else P0=reg[10];
}
else {
P0=reg[dis[seg_count]];
}
}
}
/*****************************
函数名:void timer0() interruption 1
函数功能:数码管动态扫描中断,让数码管显示现在的时间
所用变量:seg_count,调用void display(uchar seg_count)
******************************/
void timer0() interrupt 1
{
TF0=0;
TH0=((65536-5000)/256);
TL0=((65536-5000)%256); //定时器重装载。
display(seg_count);
seg_count++;
if(seg_count>3)seg_count=0; //当按键数大于3时清零
}
/*******************************
函数名:uchar keyscan()
函数功能:对键盘进行扫描,确定那个按键有用。
所用变量:局部变量 scancode,tempcode。
************************************/
uchar keyscan()
{ uchar scancode,tempcode;
P2=0xf0;
if((P2&0xf0)!=0xf0) //仅仅是判断是否有按键按下,有则P2口数据会变化,往下执行。
{
delay(20); //调延时防抖动
if((P2&0xf0)!=0xf0) //再判断是否有按键按下,防止误操作
{
scancode="0xfe"; //将P2.0口至0其他位至1
while((scancode&0x10)!=0) //判断是否P2.4为0.
{ P2=scancode;
if((P2&0xf0)!=0xf0) //判断是否有按键按下。。有的话P2.4,P2.5至少有一个为0
{
tempcode=((P2&0xf0)|0x0f); //得出到底是那个高位键按下。如果是P2.4则P2.4为0,其他位为1
while((P2&0xf0)!=0xf0);
return ((~scancode)+(~tempcode)); //通过列,行得出到底是那个键按下。
}
else scancode=((scancode<<1)|0x01); //通过左移,不断的扫描低4位。
}//while
} //if
}//if
else return 0 ; //没按键则返回0
}
/***********************************
函数名:void setadd()
函数功能:调节时钟,对其进行加功能
所用函数: 被主函数调用
*************************************/
void setadd()
{
if(key_count==1)
{
fen++;
if(fen==60)fen=0;
}
else if(key_count==2)
{
shi++;
if(shi==24)shi=0;
}
}
/****************************
函数名:void setdec()
函数功能:调节时钟,对其进行减功能
所用函数:被主函数调用
****************************/
void setdec()
{
if(key_count==1)
{
if(fen==0)fen=60; //这两行可以改成这样。if(fen)fen--; else fen="59";
fen--;
}
else if(key_count==2)
{
if(shi==0)shi=24; //不能写成这样shi--; if(shi==0)shi=24; 避免出现0减一的情况。减了就会出错。
shi--;
}
}
/********************
函数名:void main()
函数功能:初始化程序,不断的对是键盘进行扫描
所用函数:
***********************/
void main()
{
TMOD="0x11";
TH1=((65536-45900)/256);
TL1=((65536-45900)%256);
TH0=((65536-5000)/256);
TL0=((65536-5000)%256);
EA="1";
ET0=1;
ET1=1;
IP="0x08";
TR0=1;
TR1=1;
while(1)
{ key="keyscan"();
switch(key) //键值识别语句
{
case 0x18: //k1键,为set设置键 ,数据由keyscan函数返回。
key_count++; //有键按下就加1
if(key_count>2)key_count=0; //按键超过2次,就清零
break;
case 0x24: //加号键
setadd(); //进入时间调整子程序,进行加1操作
break;
case 0x28: //减号键
setdec(); //进入时间调整子程序,进行减1操作
break;
}
}
}
文章评论(0条评论)
登录后参与讨论