此篇文章用以记录蓝桥杯单片机的学习。
在蓝桥杯开发板上,有四个按键可以拿出独立使用,如下原理图所示:
其中,将J5跳线帽移动到2与3上,即可将S4,S5,S6,S7当独立的按键使用,四个按钮的一边都接地,另一边与单片机的P30~P33 口相连。
按键的原理简单,但是由于其机械特性,如何使用单片机去消除按键按下与弹开时的机械抖动十分重要。
为了提高单片机的运行效率,独立按键的使用也应该提高效率,因此可以配合定时器和三步消抖法进行消抖,这样即可避免主程序中存在大量的delay,提高单片机的运行效率。
按键程序如下:
Key4.c
#include <STC15F2K60S2.H>
#include "intrins.h"
#define u8 unsigned char
u8 Key_4_value;
//用来记录键值
bit Key_time_falg;
//用来做为计时标志位
unsigned long Key_time;
//用来记录按键按下的时间,进而判断是长按还是短按
u8 Key_scan() //扫描按键按下的情况
{
u8 Key_temp, Key_value;
Key_temp = P3 & 0x0f;
switch (Key_temp) {
case 0x0e:
Key_value = 7; //S7
break;
case 0x0d:
Key_value = 6; //S6
break;
case 0x0b:
Key_value = 5; //S5
break;
case 0x07:
Key_value = 4; //S4
break;
default:
Key_value = 0;
break;
}
return Key_value;
}
void Read_key() //获得键值
{
u8 Key_up, Key_down, Key_temp;
static u8 Key_old = 0;
Key_temp = Key_scan();
Key_down = Key_temp & (Key_old ^ Key_temp); //三步消抖法,Key_donw是按键按下的键值 Key_up是按键弹上的键值 Key_old用来记录上一次的键值
Key_up = ~Key_temp & (Key_old ^ Key_temp);
Key_old = Key_temp;
if (Key_down) //如果需要在按键按下就立马执行 则可以在这里对把Key_donw的值给Key_4_value
{
Key_time_falg = 1; //开始计时
}
if (Key_up) //这里是按键按下 并松手了才执行
{
Key_time_falg = 0; // 已松手 结束计时
if (Key_time >= 500) // 如果按下的时间大于500,则为长按 否则为短按
{
Key_4_value = Key_up + 10;
Key_time = 0;
} else {
Key_4_value = Key_up;
Key_time = 0;
}
}
}
Key4.h
#ifndef _KEY4_H_
#define _KET4_H_
u8 Key_scan();
void Read_key();
#endif
现在,在主程序中配置好定时器和中断即可:
Main.c
#include <STC15F2K60S2.H>
#include "intrins.h"
//#include "74LS138.h"
#include "Key4.h"
extern u8 Key_4_value; //键值
extern unsigned long Key_time; //按键按下的时间
extern bit Key_time_falg; //按键计时标志位
void Timer0Init(void) //定时1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
EA = 1; //打开总中断
ET0 = 1; //打开定时器0中断
TR0 = 1; //定时器0开始计时
}
void main() {
// init_ls138(); // 上电关闭所有外设
Timer0Init();
while (1) {
if (Key_4_value == 16) { //按键S6被长按
//做事情
} else if (Key_4_value == 14) { //按键S4被长按
//做事情
} else if (Key_4_value == 6) { //按键S6被短按
//做事情
} else if (Key_4_value == 4) { //按键S4被短按
//做事情
}
}
}
void Tim0_interrupt() interrupt 1 {
static u8 i = 0;
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
i++;
if (Key_time_falg == 1) { //按键被按下 开始计时
Key_time++;
}
if (i >= 10) { //10ms扫描一次按键
Read_key();
i = 0;
}
}