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
#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
#include
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();
}