蓝桥杯单片机组备赛指南请查看 :本专栏第1篇文章
本文章针对蓝桥杯-单片机组比赛开发板所写,代码可直接在比赛开发板上使用。
型号:国信天长4T开发板(绿板),芯片:IAP15F2K61S2
(使用国信天长蓝板也可以完美兼容,与绿板几乎无差别)
恭喜各位看到这里,大势已去,接下来只是额外学习一点省赛的小技巧
1. 功能概览
大部分省赛里,官方会考察矩阵键盘,就不会考察大家对于长按与短按的操作
但是一旦遇到考独立按键的试题,就一定会有长短按的考察
推荐大家掌握定时器方式,短按加1,长按不松手清0方式。其他方式为供大家共同学习,一起进步所写,有任何问题欢迎指出。
2. 代码目的
按下独立按键S7,数码管两位数显示加1。长按独立按键S7超过1秒,则数码管示数清0。
性能指标:数码管亮度均匀,最大计数值99
3. 实现思路
只涉及一个S7按键,因此我们将长短按的检测放到 keyrunning()按键检测函数中。
当S7==0,表示按键被按下,我们一个 TR0=1 启动定时器;
当while( S7 == 0 );循环结束,表示按键被松开,我们一个 TR0=0 停止定时器;
此时读取定时过程中记录的时间,如果大于1则将显示数值清0.
4. 代码参考
4.1 定时器方式:短按加1,长按不松手清0代码
#include <reg52.h>
#include <intrins.h>
unsigned char code duanma[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
sbit S7 = P3^0;
sbit AUXR = 0x8e;
unsigned char count_num = 0;
void SMGrunning ();
void select_HC573 ( unsigned char channal )
{
switch ( channal )
{
case 4:
P2 = ( P2 & 0x1f ) | 0x80;
break;
case 5:
P2 = ( P2 & 0x1f ) | 0xa0;
break;
case 6:
P2 = ( P2 & 0x1f ) | 0xc0;
break;
case 7:
P2 = ( P2 & 0x1f ) | 0xe0;
break;
}
}
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
select_HC573 ( 7 );
P0 = 0xff;
select_HC573 ( 6 );
P0 = 0x01 << pos_SMG;
select_HC573 ( 7 );
P0 = value_SMG;
}
void state_SMG_all ( unsigned char value_SMG )
{
select_HC573 ( 6 );
P0 = 0xff;
select_HC573 ( 7 );
P0 = value_SMG;
}
void init_sys ()
{
select_HC573 ( 4 );
P0 = 0xff;
select_HC573 ( 5 );
P0 = 0x00;
}
//用定时器0,产生20ms一次的中断
void init_timer0(void) //20毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初始值
TH0 = 0xB8; //设置定时初始值
TF0 = 0; //清除TF0标志
EA = 1;
ET0 = 1;
}
unsigned char count_20ms = 0;
bit count_1s = 0;
void timer0_service () interrupt 1
{
TL0 = 0x00; //设置定时初始值
TH0 = 0xB8; //设置定时初始值
count_20ms++;
if ( count_20ms == 50 )
{
count_20ms = 0;
count_1s = 1;
}
if ( count_1s == 1 )
{
count_num = 0;
}
}
void Delay2ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 22;
j = 128;
do
{
while (--j);
} while (--i);
}
void keyrunning ()
{
if ( S7 == 0 )
{
Delay2ms();//适当消除一点点抖动
if ( S7 == 0 )
{
TR0 = 1;
while ( S7 == 0 )
{
SMGrunning ();
}
TR0 = 0;
count_20ms = 0;
if ( count_1s == 1 )
{
count_1s = 0;
}
else
{
count_num ++;
if ( count_num == 100 )
{
count_num = 0;
}
}
}
}
}
void SMGrunning ()
{
state_SMG ( 6 , duanma[count_num/10] );
Delay2ms();
state_SMG ( 7 , duanma[count_num%10] );
Delay2ms();
state_SMG_all ( 0xff );
}
void main ()
{
init_sys ();
init_timer0 ();
while( 1 )
{
SMGrunning ();
keyrunning ();
}
}
4.2 定时器方式:短按加1,长按松手清0代码
为了节省篇幅,这里我来给讲要怎么修改程序实现:
我们的思路就是,删去中断服务函数中直接响应清0的语句,在按键检测函数中加入清0语句
步骤一:在中断服务函数timer0_service() 中,注释掉或者删掉这4行代码
步骤二:在键值扫描函数keyrunning()中,添加这1行代码:
4.3 延时函数方式:短按加1,长按松手清0代码
思路就是,循环20ms的软件延时,当循环个数达到50个时,则表示时间经过了1s
代码如下:
#include <reg52.h>
#include <intrins.h>
unsigned char code duanma[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
sbit S7 = P3^0;
sbit AUXR = 0x8e;
unsigned char count_num = 0;
unsigned char count_20ms = 0;
void SMGrunning ();
void select_HC573 ( unsigned char channal )
{
switch ( channal )
{
case 4:
P2 = ( P2 & 0x1f ) | 0x80;
break;
case 5:
P2 = ( P2 & 0x1f ) | 0xa0;
break;
case 6:
P2 = ( P2 & 0x1f ) | 0xc0;
break;
case 7:
P2 = ( P2 & 0x1f ) | 0xe0;
break;
}
}
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
select_HC573 ( 7 );
P0 = 0xff;
select_HC573 ( 6 );
P0 = 0x01 << pos_SMG;
select_HC573 ( 7 );
P0 = value_SMG;
}
void state_SMG_all ( unsigned char value_SMG )
{
select_HC573 ( 6 );
P0 = 0xff;
select_HC573 ( 7 );
P0 = value_SMG;
}
void init_sys ()
{
select_HC573 ( 4 );
P0 = 0xff;
select_HC573 ( 5 );
P0 = 0x00;
}
void Delay2ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 22;
j = 128;
do
{
while (--j);
} while (--i);
}
//数码管刷新函数自带4ms,因此这里我们设置16ms
void Delay16ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 173;
j = 28;
do
{
while (--j);
} while (--i);
}
void keyrunning ()
{
if ( S7 == 0 )
{
Delay2ms();//适当消除一点点抖动
if ( S7 == 0 )
{
while ( S7 == 0 )
{
SMGrunning ();//数码管扫描函数内自带4ms
Delay16ms();
count_20ms++;
if( count_20ms > 50 )
{
count_num = 99;
count_20ms = 50;
}
}
count_20ms = 0;
count_num ++;
if ( count_num == 100 )
{
count_num = 0;
}
}
}
}
void SMGrunning ()
{
state_SMG ( 6 , duanma[count_num/10] );
Delay2ms();
state_SMG ( 7 , duanma[count_num%10] );
Delay2ms();
state_SMG_all ( 0xff );
}
void main ()
{
init_sys ();
while( 1 )
{
SMGrunning ();
keyrunning ();
}
}