/*************************************************
作者:罗国辉
****************************************************/
这是我大二的时候第一次学单片机的时候写的第一个程序,后面大三的时候,我们专业才开单片机的课程,又真正系统的学习了一遍,才算是真正对单片掌握了,对我后面的嵌入式开发做了一定的铺垫。不过,建议学单片的读者,一开始不要用C语言去写,一开始最好是用汇编去写程序,这样子,对51片子的一些东西可以更好的理解。
1.原理图:
2.程序:
#include
#include
#include
#include
#define LEDcom0 XBYTE[0x4ff0]
#define LEDcom1 XBYTE[0x4ff1]
#define LEDcom2 XBYTE[0x4ff2]
#define LEDcom3 XBYTE[0x4ff3]
#define LEDcom4 XBYTE[0x4ff4]
#define LEDcom5 XBYTE[0x4ff5]
#define LEDcom6 XBYTE[0x4ff6]
#define LEDcom7 XBYTE[0x4ff7]
#define keycom XBYTE[0x2fff]
#define HI ((65536 - 50000) / 256)
#define LO ((65536 - 50000) % 256)
#define _TH0_TL0_ (65536 - 50000)
#define M 20 //中断次数
unsigned char code SEG_TAB_A[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9码码值
unsigned char code SEG_TAB_B[10] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //0.-9.码值
static unsigned char hou = 12, min = 0, sec = 0;
unsigned char keyflag=0,keyflag2=0;
void keynum(void);
void readkey0(void);
void readkey1(void);
void readkey2(void);
void readkey3(void);
void readkey4(void);
void readkey5(void);
void readkey6(void);
void readkey7(void);
void Timer0(void) interrupt 1 using 1 //T/C0中断服务程序,定时50ms
{
static unsigned char count = 0; //定义静态变量count,中断记数
TR0 = 0;
TL0 += (_TH0_TL0_ + 9) % 256;
TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY;
TR0 = 1;
count++;
if(keycom==0xfd)
{
keynum();
}
if(count == M)
{
count = 0;
sec++;
if(sec == 60)
{
min++;
sec = 0;
if(min == 60)
{
hou++;
min = 0;
if(hou == 24)
{
hou = 0;
}//if hou=24
}//if min=60
}//if sec=60
}//if count=M
}
void Timer0Init(void) //定时器0
{
TMOD = 0x01;
TH0 = HI; //载入高8位初值
TL0 = LO; //载入低8位初值
TR0 = 1; //启动定时器
EA = 1; //开总中断
ET0 = 1; //开定时器中断.若为0则表示关闭
}
void Delay(unsigned char a)//延时a*1MS
{
unsigned char j;
while(a-- != 0)
{
for (j = 0; j < 125; j++);
}
}
int pkey(void)//判断键是否被按下,通过返回值确定
{
if(keycom!=0xff)
{
Delay(200);
if(keycom!=0xff)
return 1;
else
return 0;
}
else
return 0;
}
void keynum(void)//按键确定
{
keyflag2=1;
TR0 = 0;//定时器关闭
EA = 0;//总中断关闭
ET0 = 0;//定时器中断关闭
while(keyflag2)
{
//Delay(500000);
if(pkey()==1)
{
switch(keycom)
{
case 0x7f:
{ readkey0();} break;
case 0xbf:
{ readkey1();} break;
case 0xdf:
{ readkey2();} break;
case 0xef:
{ readkey3();} break;
case 0xf7:
{ readkey4();} break;
case 0xfb:
{ readkey5();} break;
default: break;
}
}
readkey7();
}
}
/*-----时间调整-------
1=hour+ ; 2=minute+ ; 3=second+ ;4=hour- ;5=minute- ; 6=second-
-----------------------*/
void readkey0()
{
while(keycom==0x7f)
{keyflag=1;}
if(hou==24)
{
hou=0;
}
hou++;
}
void readkey1()
{
while(keycom==0xbf)
{keyflag=2;}
if(min==60)
{
min=0;
}
min++;
}
void readkey2()
{
while(keycom==0xdf)
{keyflag=3;}
if(sec==60)
{
sec=0;
}
sec++;
}
void readkey3()
{
while(keycom==0xef)
{keyflag=4;}
if(hou==0)
{
hou=24;
}
hou--;
}
void readkey4()
{
while(keycom==0xf7)
{keyflag=5;}
if(min==0)
{
min=24;
}
min--;
}
void readkey5()
{
while(keycom==0xfb)
{keyflag=6;}
if(sec==0)
{
sec=24;
}
sec--;
}
/*unsigned char readkey6()
{
while(keycom==0xfe)
{keyflag=6;}
key6++;
if(key7>9)
{
key7=0;
}
}
*/
void readkey7()
{
while(keycom==0xfe)
{keyflag=8;}
keyflag2=0;//退出时间调整,置0
/*中断重启*/
TL0 += (_TH0_TL0_ + 9) % 256;
TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY;
TR0 = 1;
EA = 1;
ET0 = 1;
}
void Disp(void)//数码管显示函数
{
LEDcom0 = SEG_TAB_A[ hou / 10 ];
LEDcom1 = SEG_TAB_A[ hou % 10 ];
LEDcom2 = 0x40;
LEDcom3 = SEG_TAB_A[ min / 10 ];
LEDcom4 = SEG_TAB_A[ min % 10 ];
LEDcom5 = 0x40;
LEDcom6 = SEG_TAB_A[ sec / 10 ];
LEDcom7 = SEG_TAB_A[ sec % 10 ];
}
void main(void) //主函数
{
keycom=1;
Timer0Init();
while(1)
{
Disp();
}
}
--------------------------------------
3.问题:
键盘无反应,请教!
---------------
4.答案:
调试了一下,结果发现了错误原因:
由于按鍵等待时间太少,故readkey7()一进入循环就执行,根本就不能处理其它按鍵,所以只需把readkey7()放到switch()里面即可,用7的键值来确定退出!
-----------------罗国辉 2007.6.21
-----------------------
while(keyflag2)
{
//Delay(5000000);
if(pkey()==1)
{
switch(keycom)
{
case 0x7f:
{ readkey0();} break;
case 0xbf:
{ readkey1();} break;
case 0xdf:
{ readkey2();} break;
case 0xef:
{ readkey3();} break;
case 0xf7:
{ readkey4();} break;
case 0xfb:
{ readkey5();} break;
default:
{ readkey7();} break;
}
}