min++; sec = 0;
if(min == 60) {
hou++; min = 0; if(hou == 24) {
hou = 0; } }//if }//if }//if }
/******************************************************************************************/
void Timer0Init(void) //定时器0 {
TMOD = 0x01;
TH0 = HI; TL0 = LO; TR0 = 1;
ET0 = 1; EA = 1; }
/******************************************************************************************/
void main(void) //主函数 {
Timer0Init(); while(1) {
Disp(); } }
简单吧,还是有点看不懂哦,那你自己慢慢体会吧,如果你自己能写个时钟程序来,那么你的51单片机也就学了80 % 了。中断和
定时/记数器器,是个很重要的东西,几乎用到单片机的地方都会涉及到中断和定时!所以大家要好好掌握哦! ^_^
哈哈,赶紧编译HEX文件,搭好硬件,烧入单片机,上电看看效果先!呵呵,现在你应该有成就感了吧,想不到一个时钟居然那么
简单, 嘿嘿!但是问题来了!时钟虽然做出来了,但是他的精度怎么样呢?一两个小时,或许看不出什么误差,但是一天或者一年呢?
晕,我的天呀,要是按年来算的话,那这个时钟根本没有实用价值!人家都说用C写不出,精度高的时钟程序来的!!!是不是有点后悔
了,去学汇编吧!但是既然选择了C,那么就不要后悔!嘿嘿,想想C的高级语言,怎么会输给汇编呢 ^_^ 呵呵!看下面这段代码:
static unsigned char count = 0;
TR0 = 0;
TL0 += (_TH0_TL0_ + 9) % 256;
TH0 += (_TH0_TL0_ + 9) / 256 + (char)CY; TR0 = 1;
count++;
在中断处理服务程序中,我们加入上面的代码。 TR0 = 0; 先关闭定时器T0,然后重新给TH0和TL0 赋值,再开启 TR0 = 1;烧入单片
机看看效果,怎么样,你第一次精确多了吧。但是还是有误差!郁闷!为什么呢?那是硬件造成的误差,我们可以用软件来弥补!我们先
把时钟点亮,让他走上几个小时或者是几天,看看到底误差是多少!取个平均值。(这里比如我们10小时快1秒)那么可以通过以下语句 if(hour % 10 = 0) { sec--;
}
来弥补!这样可能会出现这样的现象:秒直接跳变!我们可以再通过细分来实现,不要10小时那么大,小些的就行!具体的操作还是留给 朋友们吧!
(七)
这回我们来讲讲键盘,大家肯定见过银行柜员机吧,取钱输入密码就要用到键盘,超市购物取回寄存物品要输入密码,还有你现在在
用的PC机的键盘。但是键盘的是怎么工作的呢?一般有2种方式:(1)扫描法,不断扫描键盘的状态,送CPU判断并处理。如果键盘数目一
大的话,显然不适合(2)线反转法,通过行列状态的改变来判断有无键被按下! 现在我们在P1口接个4*4的键盘,P1.0--P1.3接行,P1.4---P1.7接列,再接4个4K7的上拉电阻至VCC。代码如下:
//----键盘扫描法程序------- //----用数码管显示相应的键值----- //P1.0--P1.3接行------- //P1.4---P1.7接列------- #include
unsigned char code tab[ ]={0x3F,0x06,0x5B,0x4F, 0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x39,0x5E,0x79,0x71};//0到F的16个键植
/******************************************************************************/
void Delayt(unsigned char t)//延时函数 {
unsigned char i; for(t=0;i<=t;t++)
for(i=0;i<255;i++); }
/******************************************************************************/
bit pkey(void)//判断键的否被按下,通过返回值确定 {
P1=0xf0; if(P1!=0xf0) {
Delayt(25); if(P1!=0xf0) return 1; else return 0; } else
return 0; }
/******************************************************************************/
void main(void)//主函数
{
unsigned char key,j,k,s; while(1) {
if(pkey()==1) { P1=0xfe; k=0xfe;
for(j=0;j<4;j++) {
s=P1&0xf0; switch(s)
{
case 0xe0: key=4*j+0; break; case 0xd0: key=4*j+1; break; case 0xb0: key=4*j+2; break; case 0x70: key=4*j+3; break; default: break; }
k=(k<<1)|0x01; P1=k;
}//for }//if
//if((P1&0xf0)==0xf0) P0=tab[key]; P2=1;
Delayt(50); }//while }
还有一种就是线反转法,实现如下:
1.和扫描法相同,把列线置低电平,行置高,读行状态 2.与1相反,把行置低,列置高,读列状态
3.若有键按下,则为2次所读状态的结果即为键所在的位置,这样2次输出和2次读入可以完成键的识别!!!
子函数如下:
unsigned char key_vscan(void) {
unsigned char row, col; P1 = 0xF0;
row = P1&0xF0; row = row&0xF0;
P1 = 0x0F;
col = P1&0x0F; col = col&0x0F;
return(key_val(row|col)); }
下面我们再来介绍介绍一键多能的程序,即按下一个键,可以执行不同的命令!
void main (void) {
unsigned char b = 0; while( 1 ) {
if(P1_0 == 0) { Delay(10); if(P1_0 == 0)
{
b++;
if( b == N )//N为键的功能数目 {
b = 0; }
while(P3_2 == 0);//等待键松开 } } switch( b ) {
case 1: P2_0 = 0xFE; break;
case 2: P2_1 = 0xfd;
//..............add your code here! } } }
(八)//以上的文字写于2005年5月,由于时间关系,一直未能将此完成,最近闲着无聊又接着写了些文字,以下写于2006年6月5日!