蓝桥杯(7)——矩阵键盘输入数字

版权声明:让结局不留遗憾,让过程更加完美。 https://blog.csdn.net/Xiaomo_haa/article/details/86695769

J5跳线帽接到KBD端,为矩阵按键功能

功能:
        矩阵键盘分布
        1, 2, 3, ↑
        4, 5, 6, ←
        7, 8, 9,↓
        0, ESC, ENTER, →
        根据键值,在数码管显示所按数字,并支持修改

尚未开发完整

main.c

/*******************************************************************************
* 文件名:main.c
* 描  述:

* 作  者:小默haa
* 版本号:v1.0
* 日  期: 2019年1月28日
* 备  注:矩阵键盘
*         
*******************************************************************************/
#include <STC15F2K60S2.H>
#include "sys.h"

u8 Led_flag = 0;
u8 Led_dat;				//led显示状态

void main(void)
{
	All_Init();
	Time0_Init();
	EA = 1;			//开总中断
	while (1)
	{
		Key_Scan();
	}
}

sys.c

/*******************************************************************************
* 文件名:sys.c
* 描  述:工程中的系统文件
* 作  者:小默haa
* 版本号:v1.0
* 日  期: 2019年1月28日
* 备  注:
*         
******************************************************************************/
#include "sys.h"

/*******************************************************************************
* 函数名	:All_Init
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:开发板初始化函数
* 备注		:CT107D开发板初始化,关闭所有外设   
*******************************************************************************/
void All_Init(void)
{
	P2 = (P2 & 0x1f) | 0x80;	//打开Y4C(LED)
	P0 = 0xff;					//关闭LED
	P2 = (P2 & 0x1f) | 0xe0;	//打开Y7C(数码管)
	P0 = 0xff;					//关闭数码管
	P2 = (P2 & 0x1f) | 0xa0;	//打开Y5C
	P0 = 0x00;					//关闭蜂鸣器、继电器
	P2 = P2 & 0x1f;
}

//定时器0初始化
void Time0_Init(void)
{
	AUXR |= 0x80;	//定时器时钟1T模式
	TMOD &= 0xF0;	//设置定时器模式
	TL0 = 0xcd;		//设置定时初值1ms
	TH0 = 0xd4;		//设置定时初值1ms
	TF0 = 0;		//清除TF0标志
	ET0 = 1;		//允许定时器0中断
	TR0 = 1;		//定时器0开始计时
}

/*******************************************************************************
* 函数名	:Time0
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:定时器0中断函数
* 备注		:定时器0中断函数,定时器0定时1ms,
						执行Key_Drive()和Nixie_Scan()函数。      
*******************************************************************************/
void Time0(void) interrupt 1
{	
	Key_Drive();
	Nixie_Scan();
}


sys.h

/*******************************************************************************
* 文件名:sys.h
* 描  述:工程中的头文件
* 作  者:小默haa
* 版本号:v1.0
* 日  期: 2019年1月28日
* 备  注:工程中所有c文件公用这一个头文件
*         
******************************************************************************/
#ifndef _SYS_H_
#define _SYS_H_

#include <stc15f2k60s2.h>
#include <intrins.h>

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;

//全局变量定义
#define FOSC 11059200L		//系统时钟

//外部变量
extern u8 Led_flag;
extern u8 Led_dat;
extern u8 KeySta[4][4],Key_backup[4][4];


//sys.c
void All_Init(void);
void Time0_Init(void);


//led.c
void Led_illume(u8 dat);


//key.c
sbit KEY_IN_1 = P4^4;
sbit KEY_IN_2 = P4^2;
sbit KEY_IN_3 = P3^5;
sbit KEY_IN_4 = P3^4;
sbit KEY_OUT_1 = P3^0;
sbit KEY_OUT_2 = P3^1;
sbit KEY_OUT_3 = P3^2;
sbit KEY_OUT_4 = P3^3;
void Key_Scan(void);
void Key_Drive(void);
void Key_Action(u8 keycode);


//Nixie_tube.c
extern u8 smg1, smg2, smg3, smg4, smg5, smg6, smg7, smg8;
void Nixie_Scan(void);
void Nixie_Show(void);
void Show_Num(u32 num);






#endif

led.c

#include "sys.h"

/*******************************************************************************
* 函数名	:Led_illume
* 输入值	:LED码 dat
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:LED点亮函数
* 备注		:根据输入的LED码值,点亮LED     
*******************************************************************************/
void Led_illume(u8 dat)
{
	P2 = (P2 & 0x1f) | 0x80;	//打开Y4C(LED)
	P0 = dat;					//关闭LED
	P2 = P2 & 0x1f;
}


key.c

/*******************************************************************************
* 文件名:key.c
* 描  述:
* 作  者:小默haa
* 版本号:v1.0
* 日  期: 2019年1月28日
* 备  注:矩阵键盘核心程序
*         
*******************************************************************************/
#include "sys.h"

u8 KeySta[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};			//当前按键状态
u8 Key_backup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};	//按键状态备份,保存前一次的按键值
u8 code KeyCodeMap[4][4] = {{0x31, 0x32, 0x33, 0x26},			//1,2,3,↑
														{0x34, 0x35, 0x36, 0x25},			//4,5,6,←
														{0x37, 0x38, 0x39, 0x28},			//7,8,9,↓
														{0x30, 0x1b, 0x0d, 0x27}};		//0,ESC,ENTER,→

/*******************************************************************************
* 函数名	:Key_Scan
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:矩阵按键扫描
* 备注		:按键扫描函数,在定时器中断程序里调用,定时器间隔1ms        
*******************************************************************************/
void Key_Scan(void)
{
	u8 i;
	static u8 keyout = 0;		//矩阵按键扫描输出索引
	static u8 keybuff[4][4] = {{0xff, 0xff, 0xff, 0xff},
														 {0xff, 0xff, 0xff, 0xff},
														 {0xff, 0xff, 0xff, 0xff},
														 {0xff, 0xff, 0xff, 0xff}};	//矩阵按键扫描缓存区
	
	keybuff[keyout][0] = (keybuff[keyout][0] << 1) | KEY_IN_1;		//将每一行的4个按键值移入缓存区
	keybuff[keyout][1] = (keybuff[keyout][1] << 1) | KEY_IN_2;
	keybuff[keyout][2] = (keybuff[keyout][2] << 1) | KEY_IN_3;
	keybuff[keyout][3] = (keybuff[keyout][3] << 1) | KEY_IN_4;
		
	//消抖后更新按键状态
	for (i = 0;i < 4;i ++)
	{
		if ((keybuff[keyout][i] & 0x0f) == 0x00)
			KeySta[keyout][i] = 0;		//连续4次扫描值都是0,即4×4s内都是按下状态,认为按键已平稳按下
		else if ((keybuff[keyout][i] & 0x0f) == 0x0f)
			KeySta[keyout][i] = 1;		//连续4次扫描值都是1,即4×4s内都是松开状态,认为按键已稳定弹起
	}
	
	//执行下一次的扫描输出
	keyout ++;
	keyout = keyout & 0x03;		//索引加到4就归零
	switch (keyout)						//根据索引,释放当前输出引脚,拉低下次的输出引脚
	{
		case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
		case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
		case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
		case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
		default:break;
	}
}

/*******************************************************************************
* 函数名	:Key_Drive
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:矩阵按键驱动程序
* 备注		:检测矩阵键盘的动作,调用相应的函数,需要在主循环里调用        
*******************************************************************************/
void Key_Drive(void)
{
	u8 i, j;
	for (i = 0; i < 4; i ++)										//循环检测4×4的矩阵按键
	{	
		for (j = 0; j < 4; j ++)
		{
			if (Key_backup[i][j] != KeySta[i][j])		//检测按键当前动作
			{
				if (Key_backup[i][j] != 0)						//按键按下时执行动作
				{
					Key_Action(KeyCodeMap[i][j]);				//调用按键活动函数
				}
				Key_backup[i][j] = KeySta[i][j];			//更新前一次的备份值
			}
		}
	}
}

/*******************************************************************************
* 函数名	:Key_Action
* 输入值	:键值 keycode
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:矩阵按键动作函数
* 备注		:矩阵键盘动作函数,根据键值执行相应程序        
*******************************************************************************/
void Key_Action(u8 keycode)
{
	static u32 addend = 0, NUM[8] = {0, 0, 0, 0, 0, 0, 0, 0};
	u32 result = 0;
	static u8 num_bit = 0, temp = 0;		//记录输入位数
	u8 i;
	
	if ((keycode >= 0x30) && (keycode <= 0x39) && num_bit < 8)		//输入0~9数字
	{
		addend = (addend * 10) + (keycode - 0x30);	//整体十进制左移,新数字进入个位
		num_bit ++;													//每输入一个数字,位数加1
		Show_Num(addend);										//数码管显示
	}
	else if (keycode == 0x1b)		
	{		
		addend = 0;													//ESC键清屏
		num_bit = 0;
		temp = 0;
		Show_Num(addend);										//数码管显示
	}
	else if ((keycode == 0x25) && (num_bit > 0))	// ← 删除最后一位
	{
		addend = addend / 10;
		num_bit --;													//删除最后一位
		Show_Num(addend);										//数码管显示
	}
}


Nixie_tube.c

/*******************************************************************************
* 文件名:Nixie_tube.c
* 描  述:数码管相关程序
* 作  者:小默haa
* 版本号:v1.0
* 日  期: 2019年1月28日
* 备  注:与数码管相关的所有函数
*         
*******************************************************************************/
#include "sys.h"

u8 code Nixie[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};	//共阳数码管码字
u8 NixieBuff[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};	//数码管显示缓冲区,初值0xff确保启动时都不亮
u8 code Symbol[] = {0xff,0xbf};	//全灭,-

u8 smg1 = 0, smg2 = 0, smg3 = 0, smg4 = 0, smg5 = 0, smg6 = 0, smg7 = 0, smg8 = 0;

/*******************************************************************************
* 函数名	:Nixie_Scan
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:数码管扫描函数
* 备注		:根据数码管显示数组,点亮数码管   
*******************************************************************************/
void Nixie_Scan(void)
{
	static u8 index = 0;
	P2 = (P2 & 0x1f) | 0xe0;	//数码管消隐
	P0 =0xff;
	
	P2 = (P2 & 0x1f) | 0xc0;	//数码管片选
	P0 = 0x01 << index;
	
	P2 = (P2 & 0x1f) | 0xe0;	//数码管段选
	P0 = NixieBuff[index];
	P2 &= 0x1f;
	
	index ++;
	index &= 0x07;
}

/*******************************************************************************
* 函数名	:Nixie_Show
* 输入值	:无
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:数码管显示函数
* 备注		:根据每一位的数码管需要显示内容,选择相应码子存放进数码管显示数组   
*******************************************************************************/
void Nixie_Show(void)
{
    NixieBuff[0] = Nixie[smg1];
	NixieBuff[1] = Nixie[smg2];
	NixieBuff[2] = Nixie[smg3];
	NixieBuff[3] = Nixie[smg4];
	NixieBuff[4] = Nixie[smg5];
	NixieBuff[5] = Nixie[smg6];
	NixieBuff[6] = Nixie[smg7];
	NixieBuff[7] = Nixie[smg8];
	
	for(i = 0; i <= 7; i ++)
	{
		if(NixieBuff[i] == 0xc0)		//从最高位开始,遇0转换为空格
			NixieBuff[i] = 0xff;
		else
			break;	
	}
}

/*******************************************************************************
* 函数名	:Show_Num
* 输入值	:数值 num
* 返回值	:无
* 作者		:小默haa
* 时间		:2019年1月29日
* 功能描述:数值显示处理
* 备注		:将数值每一位分离,存放进每一位数码管显示指示变量smg中   
*******************************************************************************/
void Show_Num(u32 num)
{
	smg8 = num % 10; num /= 10;
	smg7 = num % 10; num /= 10;
	smg6 = num % 10; num /= 10;
	smg5 = num % 10; num /= 10;
	smg4 = num % 10; num /= 10;
	smg3 = num % 10; num /= 10;
	smg2 = num % 10; num /= 10;
	smg1 = num % 10;
	
	Nixie_Show();
}


猜你喜欢

转载自blog.csdn.net/Xiaomo_haa/article/details/86695769