独立按键模块
实验简介
CT107D单片机开发板上的独立按键控制, 指示灯亮灭,数码管显示按键值
实验原理图
实验原理
- 器件介绍:按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时, 开关断开。CT107D上的为机械弹性开关,由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。所以我们在实验程序总要注意按键消除抖动(简称“消抖”)的操作。
- 消除抖动:消抖有软件消抖和硬件消抖,为了方便,我们使用软件消抖,具体操作为,先设置按键IO口输入为高电平,读取IO口是否有按键被按下(即有低电平出现),使用软件
延时函数10ms
,再次检测IO口是否仍为低电平,若是,则有按键被按下,进而继续下面的按键程序。 - 实现须知:锁存端LE得为高电平,即得控制Y4C为高电平,下图知Y4C,受Y4控制,WR输入固定为低电平(0),了解数字电路中或非门知识,我们得使得Y4输出低电平,才能使的Y4C输出高电平,而Y4为74HC138芯片(38译码器)的一个管脚,查阅对应芯片手册可知,其真值表满足C = 1,B = 0,A = 0,(对应管脚P27,P26,P25),才能使得Y4输出低电平,同时代码实现时要保证管脚P2的其他的管脚(0~4)保持原来的状态 。同理控制数码管的Y6C和Y7C,以及控制蜂鸣器的Y5C也一样
- 注意:按键功能选择BTN(J5上的跳线2与3相连,此时切换至S7,s6,s5,s4独立按键模块)
实验程序
按下独立键盘上每一个键,对应LED状态取反
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
//typedef unsigned char uchar;
#define uchar unsigned char
void Delay10ms(); //@12.000MHz
#endif
//独立按键部分,记得接线帽切换为BTN
//main.c文件--按下按键S7,LED灯1亮,按下按键S6,LED灯2亮,按下按键S5,LED灯3亮,按下按键S4,LED灯4亮
#include "config.h"
//定义特殊位功能寄名称
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
sbit led1 = P0^0;
sbit led2 = P0^1;
sbit led3 = P0^2;
sbit led4 = P0^3;
void led_init()//LED初始化为全部不亮
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
}
void closeBeep()
{
P2 = (P2 & 0x1f) | 0xa0; //开启译码器的Y6端口,同时不改变其他管脚状态
P0 &= 0xaf;//1010 1111//关闭蜂鸣器和继电器,P06和P04端口分贝输入,输出低电平
P2 &= 0x1f;//P27 ~ 25清零
}
void keyPros()
{
if (S7 == 0)
{
Delay10ms();//消抖
if (S7 == 0)
{
led1 = ~led1;//led灯1的状态取反
}
while(!S7);//判断按键是否松开
}
else if (S6 == 0)
{
Delay10ms();//消抖
if (S6 == 0)
{
led2 = ~led2;//led灯1的状态取反
}
while(!S6);//判断按键是否松开
}
else if (S5 == 0)
{
Delay10ms();//消抖
if (S5 == 0)
{
led3 = ~led3;//led灯1的状态取反
}
while(!S5);//判断按键是否松开
}
else if (S4 == 0)
{
Delay10ms();//消抖
if (S4 == 0)
{
led4 = ~led4;//led灯1的状态取反
}
while(!S4);//判断按键是否松开
}
}
void main()
{
closeBeep();
led_init();
while(1)
{
keyPros();
}
}
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
按键值在数码管上显示
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
//typedef unsigned char uchar;
#define uchar unsigned char
void Delay10ms(); //@12.000MHz
void Delay1000us(); //@12.000MHz
#endif
//独立按键部分,记得接线帽切换为BTN
//main.c文件--按键值在数码管上显示
#include "config.h"
//共阳数码管位选表
uchar smgwei[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//共阴数码管码值表
uchar smgduan[] = { //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
uchar key_num = 20;
uchar tab[8];
//定义特殊位功能寄名称
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
void led_init()//LED初始化为全部不亮
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
}
void closeBeep()
{
P2 = (P2 & 0x1f) | 0xa0; //开启译码器的Y6端口,同时不改变其他管脚状态
P0 &= 0xaf;//1010 1111//关闭蜂鸣器和继电器,P06和P04端口分贝输入,输出低电平
P2 &= 0x1f;//P27 ~ 25清零
}
void keyPros()
{
static bit key_flag = 1;//注意注意static修饰的静态变量使用
if ((!S7 || !S6 || !S5 || !S4) && key_flag)
{
Delay10ms();//消抖
if(S7 == 0) { key_flag = 0; key_num = 7;}
if(S6 == 0) { key_flag = 0; key_num = 6;}
if(S5 == 0) { key_flag = 0; key_num = 5;}
if(S4 == 0) { key_flag = 0; key_num = 4;}
}
else if (S7 && S6 && S5 && S4)
{
key_flag = 1;
}
}
void selectHC573LE(uchar num)
{
switch(num)
{
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;
default: P2 &= 0x1f;break;
}
}
void digDisplay(uchar pos, letter)
{
//位选
selectHC573LE(6);
P0 = smgwei[pos - 1];
//段选
selectHC573LE(7);
P0 = ~smgduan[letter];
Delay1000us();
selectHC573LE(0);
P0 = 0xff;
}
void display()
{
uchar i;
for (i = 0; i < 8; i++)
digDisplay(i + 1, tab[i]);
}
void display_ds(uchar p1, p2, p3, p4, p5, p6, p7, p8)
{
tab[0] = p1;
tab[1] = p2;
tab[2] = p3;
tab[3] = p4;
tab[4] = p5;
tab[5] = p6;
tab[6] = p7;
tab[7] = p8;
}
void main()
{
uchar a = 0;
closeBeep();
led_init();
while(1)
{
keyPros();
display();
if (key_num == 7)
{
a = 7;
key_num = 20;
}
if (key_num == 6)
{
a = 6;
key_num = 20;
}
if (5 == key_num)
{
a = 5;
key_num = 20;
}
if (4 == key_num)
{
a = 4;
key_num = 20;
}
display_ds(16, 16, 16, 16, 16, 16, 16, a);//16为黑屏的对应码值
}
}
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void Delay1000us() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
S4长按显示4,短按显示0,其他显示原来的键值
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
//typedef unsigned char uchar;
#define uchar unsigned char
void Delay10ms(); //@12.000MHz
void Delay1000us(); //@12.000MHz
#endif
//独立按键部分,记得接线帽切换为BTN
//main.c文件--对于S4按键,长按显示4,短按显示0,其他按键显示原来的键值
#include "config.h"
//共阳数码管位选表
uchar smgwei[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//共阴数码管码值表
uchar smgduan[] = { //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
uchar key_num = 20, key_num2 = 100;
uchar tab[8];
//定义特殊位功能寄名称
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
sbit led1 = P0^0;
sbit led2 = P0^1;
sbit led3 = P0^2;
sbit led4 = P0^3;
void led_init()//LED初始化为全部不亮
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
}
void closeBeep()
{
P2 = (P2 & 0x1f) | 0xa0; //开启译码器的Y6端口,同时不改变其他管脚状态
P0 &= 0xaf;//1010 1111//关闭蜂鸣器和继电器,P06和P04端口分贝输入,输出低电平
P2 &= 0x1f;//P27 ~ 25清零
}
void keyPros()
{
static bit key_flag = 1;//注意注意static修饰的静态变量使用
if ((!S7 || !S6 || !S5 || !S4) && key_flag)
{
Delay10ms();//消抖
if(S7 == 0) { key_flag = 0; key_num = 7;}
if(S6 == 0) { key_flag = 0; key_num = 6;}
if(S5 == 0) { key_flag = 0; key_num = 5;}
if(S4 == 0) { key_flag = 0; key_num = 4; key_num2 = 4;}
}
else if (S7 && S6 && S5 && S4)
{
key_num2 = 0;
key_flag = 1;
}
}
void selectHC573LE(uchar num)
{
switch(num)
{
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;
default: P2 &= 0x1f;break;
}
}
void digDisplay(uchar pos, letter)
{
//位选
selectHC573LE(6);
P0 = smgwei[pos - 1];
//段选
selectHC573LE(7);
P0 = ~smgduan[letter];
Delay1000us();
selectHC573LE(0);
P0 = 0xff;
}
void display()
{
uchar i;
for (i = 0; i < 8; i++)
digDisplay(i + 1, tab[i]);
}
void display_ds(uchar p1, p2, p3, p4, p5, p6, p7, p8)
{
tab[0] = p1;
tab[1] = p2;
tab[2] = p3;
tab[3] = p4;
tab[4] = p5;
tab[5] = p6;
tab[6] = p7;
tab[7] = p8;
}
void main()
{
uchar a = 0, b = 20;
closeBeep();
led_init();
while(1)
{
keyPros();
display();
if (key_num == 7)
{
a = 7;
key_num = 20;
}
if (key_num == 6)
{
a = 6;
key_num = 20;
}
if (5 == key_num)
{
a = 5;
key_num = 20;
}
if (4 == key_num)
{
a = 0;
key_num = 20;
}
if (4 == key_num2)//对于S4按键,长按显示4,短按显示0,其他按键显示原来的键值
{
b = 4;
display_ds(16, 16, 16, 16, 16, 16, 16, b);//16为黑屏的对应码值
}
else if (0 == key_num2)
{
display_ds(16, 16, 16, 16, 16, 16, 16, a);//16为黑屏的对应码值
}
}
}
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void Delay1000us() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}