目录
一、前提
按键这一板块主要是以记忆为主,我直接给大家讲解代码去实现我要配置的功能。本次我要做的项目是板子上的按键有S4~S19,我希望任意一个按键可以显示对应的两位数,按下两个不同的按键可以一前一后各显示出两位数字,也就是生成四位数字,再按下另外一个按键实现清零的功能。
按键的原理图
二、代码配置
bsp_key.c文件
#include "bsp_key.h"
//函数名:按键码值读取函数
//入口参数:无
//返回值:按键的码值
//函数功能:返回按键码
unsigned char Key_Read(void)
{
unsigned int Key_NEW;
unsigned char Key_Value;//返回值
P44 = 0;P42 = 1;P35 = 1;P34 = 1;//第一列扫描
Key_NEW = P3 & 0X0F; //P3 = 0000 1000---P37~P30,高位无效,只看P33~P30
P44 = 1;P42 =0;P35 = 1;P34 = 1;//第二列扫描
Key_NEW = (Key_NEW << 4) | (P3 & 0X0F); //将原来的数值挪到次4位,本次数值放到最低4位,占用了8位
P44 = 1;P42 =1;P35 = 0;P34 = 1;//第三列扫描
Key_NEW = (Key_NEW << 4) | (P3 & 0X0F); //将原来的数值挪到次次4位,本次数值放到最低4位,占用了12位
P44 = 1;P42 =1;P35 = 1;P34 = 0;//第三列扫描
Key_NEW = (Key_NEW << 4) | (P3 & 0X0F); //将原来的数值挪到次次次4位,本次数值放到最低4位,占用了16位
switch(~Key_NEW)//Key_Value的数值对应按键的编号
{
case 0X8000:Key_Value = 4;break;
case 0X4000:Key_Value = 5;break;
case 0X2000:Key_Value = 6;break;
case 0X1000:Key_Value = 7;break;
case 0X0800:Key_Value = 8;break;
case 0X0400:Key_Value = 9;break;
case 0X0200:Key_Value = 10;break;
case 0X0100:Key_Value = 11;break;
case 0X0080:Key_Value = 12;break;
case 0X0040:Key_Value = 13;break;
case 0X0020:Key_Value = 14;break;
case 0X0010:Key_Value = 15;break;
case 0X0008:Key_Value = 16;break;
case 0X0004:Key_Value = 17;break;
case 0X0002:Key_Value = 18;break;
case 0X0001:Key_Value = 19;break;
default :Key_Value = 0;
}
return Key_Value;
}
main.c文件
#include "bsp_init.h"
#include "bsp_seg.h"
#include "Timer0.h"
#include "bsp_key.h"
#include "bsp_key.h"
#include "STDIO.H"
/* 函数声明 */
void Key_Proc(void);//按键处理
void Seg_Proc(void);//显示处理
/* 全局变量 */
unsigned char seg_buf[8];//放置字符串转换后的段码到数组
unsigned char seg_string[10];//放置字符串
unsigned char pos = 0;//中断显示专用
unsigned char Key_Value;//读取按键的数值存储变量
unsigned char Key_Down,Key_Old;
unsigned char num_buffer[2] = {0, 0}; // 存储2个按键编号
unsigned char num_count = 0; // 当前存储的数字个数
unsigned char Seg_Show_Num;//准备显示出来的数值
void main()
{
Cls_Peripheral();
Timer0Init(); //1毫秒@12.000MHz
EA = 1;
while(1)
{
Key_Proc();//按键处理
Seg_Proc();//显示处理
}
}
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
Seg_Disp( seg_buf, pos );
if(++pos ==8) pos = 0;
}
/* Key_Proc */
void Key_Proc(void)//按键处理,底层数据变更
{
Key_Value = Key_Read();//读取按键按下的编号
Key_Down = Key_Value & (Key_Old ^ Key_Value);//^异或(0000^0101)= 0101 0101 & 0101 = //0101 如果按键发生了下降沿的变化,输出结果和本次按键数值相同
//^异或(0101^0101)= 0000 0101 & 0000 = //0000 如果按键发生了下降沿的变化,输出结果和本次按键数值相同
Key_Old = Key_Value;
if(Key_Down)//如果捕捉到下降沿跳变
{
if (num_count < 2) // 如果存储的按键个数小于2
{
num_buffer[num_count++] = Key_Down; // 存储按键编号
}
else // 如果已经存储了两个按键编号
{
// 清零操作
num_count = 0; // 清空按键个数
}
}
}
/* Seg_Proc */
void Seg_Proc(void)//显示处理,显示信息生成
{
if (num_count == 1) // 如果只存储了一个按键编号
{
// 显示第一个按键编号的两位数字
sprintf(seg_string, " %02d", (unsigned int)num_buffer[0]);
}
else if (num_count == 2) // 如果存储了两个按键编号
{
// 显示两个按键编号的四位数字
sprintf(seg_string, " %02d%02d", (unsigned int)num_buffer[0], (unsigned int)num_buffer[1]);
}
else // 如果没有存储任何按键编号
{
// 显示全0
sprintf(seg_string, " 0000");
}
Seg_Tran( seg_string,seg_buf);
}
main.c文件的详细讲解
-
显示逻辑调整: 在
Seg_Proc
函数中:-
如果
num_count
为0,显示全0。 -
如果
num_count == 2
,显示两个按键编号的四位数字(如0405
)。 -
如果
num_count == 1
,只显示第一个按键编号的两位数字(如04
)。
-
-
按键逻辑调整:
在Key_Proc
函数中:-
如果
num_count == 2
,按下任意按键清零。 -
如果
num_count < 2
,存储按键编号。
-
-
数码管显示位数调整:
数码管的动态扫描范围为8位,显示内容通过sprintf
格式化为8位数码管的显示格式。
功能实现
-
按下第一个按键:
-
显示该按键对应的两位数字(如
04
)。
-
-
按下第二个按键:
-
显示两个按键对应的四位数字(如
0405
)。
-
-
按下任意第三个按键:
-
清零显示内容,显示
0000
。
-
注意事项
-
确保按键编号
S4
到S19
与实际硬件的按键编号一致。 -
如果按键编号不是从
4
到19
的连续数字,需要根据实际硬件调整按键编号的判断逻辑。 -
显示内容前面有4个空格,确保显示内容在8位数码管的中间位置。如果需要调整显示位置,可以修改
sprintf
中的空格数量。