📄 key.c
字号:
/*--------------------------------------------------------------------*-
key.C (V1.00)
-*---------------------------------------------------------------------*/
/*
* Copyright (c) 2006,wsl
* All rights reserved
*
* 文件名称: key.C
* 功能描述:
* 其它说明:
*
* 当前版本: V1.0 * 取代版本:
* 作 者: wsl * 修 改:
* 版本信息: 2006-12-16 * 修改信息: :
*/
//***********************************************************************
#include"main.H"
#include"Port.H"
#include"SCH51.H"
#include "MMI.h"
#include"Uart.h"
#include"LedDisp.h"
#include"key.h"
#include"LedDispInterface.h"
//----------------------------------------------------------------------
// 定义键盘扫描程序返回数据类型
typedef struct
{
unsigned char ShiftValue; // 存放最后扫描到的引导键键值
unsigned char ShiftCnt; // 统计上档键的个数
unsigned char FunctionValue; // 存放最后扫描到的功能键键值
unsigned char FunctionCnt; // 统计功能键的个数
}keyret;
// 定义以下键值允许连击
#define DOUBLE_KEY_1 K_Up
#define DOUBLE_KEY_2 'B'
// 按键年龄上限
#define KEYAGE (2)
#define MAXRATE (50) // 重复前的延迟值 600 MS
#define MINRATE (20) // 连击速度 240 MS
//----------------------------------------------------------------------
// 私有函数
static void KeyPadScan(keyret *pKey);
unsigned char i = 0;
//-----------------------------------------------------------------------
// 存放上次功能键和引导档的键值(keybuffer[0]存放功能键值)
static unsigned char keybuffer[2]={0, 0};
static unsigned char keyagecnt; // 按键年龄计数器
static bit Flag_keystate; // 按键状态指示: 为 1 时按键处于去抖动期间
static bit Flag_keyesc; // 按键释放标志: 为 0 时已释放
static bit Flag_keydone; // 按键任务完成标志: 为 1 时已完成
static bit Flag_keyprocess; // 按键有效标志: 为 1 时对按键执行
/*---------------------------------------------------------*-
* 函数名称: KeyPadScan()
* 参 数:
* 返 回:
* 函数功能: 按键扫描
*
* 说 明: 扫描引导键/功能键键值及个数
*
* 当前版本: V1.0 * 取代版本:
* 作 者: wsl * 修 改:
* 版本信息: 2006-12-16 * 修改信息:
-*---------------------------------------------------------*/
void KeyPadScan(keyret *pKey)
{
if ( 0 == Shift )
{ // 此键为引导键
(*pKey).ShiftValue = K_Shift;
(*pKey).ShiftCnt++;
}
if ( 0 == Up )
{
(*pKey).FunctionValue = K_Up;
(*pKey).FunctionCnt++;
}
if ( 0 == LoopRight )
{
(*pKey).FunctionValue = K_LoopRight;
(*pKey).FunctionCnt++;
}
if ( 0 == Enter )
{
(*pKey).FunctionValue = K_Enter;
(*pKey).FunctionCnt++;
}
}
/*---------------------------------------------------------*-
* 函数名称: KeyPad()
* 参 数:
* 返 回:
* 函数功能: 按键处理
*
* 说 明:
*
* 当前版本: V1.0 * 取代版本:
* 作 者: wsl * 修 改:
* 版本信息: 2006-12-16 * 修改信息:
-*---------------------------------------------------------*/
void KeyPad(void)
{
static bit Flag_key_init = 0; // 按键初始化标志,为1时初始化已完成
keyret keytemp = {0x00, 0x00, 0x00, 0x00};
// 按键初始化
if ( !Flag_key_init )
{ // 每次开机按键初始化只运行一次
//KEYPAD_PORT = 0xFF;
Flag_keystate = 1;
Flag_keyprocess = 0;
Flag_keydone = 1;
// 按键初始化完成,将此标志置位
Flag_key_init = 1;
}
if ( Flag_keydone )
{ // 扫描按键
KeyPadScan(&keytemp);
// 若无功能键按下或多于一个功能键及引导键按下,程序将作按键无效处理
if ( (0x00 == keytemp.FunctionCnt) || (keytemp.FunctionCnt > 0x01) || (keytemp.ShiftCnt > 0x01) )
{
keyagecnt = 0; // 按键年龄计数器清"0"
keybuffer[0] = 0; // 上次功能键缓冲区清"0"
keybuffer[1] = 0; // 上次引导键缓冲区清"0"
Flag_keyesc = 0; // 清按键释放标志
Flag_keystate = 1; // 置位按键状态
return;
}
// 若是上次按键末释放则返回
if (Flag_keyesc)
{
return;
}
// 若本次功能键/引导键不同,则用本次键值更新上次键值
if ( (keybuffer[0] != keytemp.FunctionValue) || (keybuffer[1] != keytemp.ShiftValue) )
{
keybuffer[0] = keytemp.FunctionValue;
keybuffer[1] = keytemp.ShiftValue;
keyagecnt = 0; // 按键年龄计数器清"0"
Flag_keystate = 1; // 置位第一次按下标志
return;
}
// 键值和上次相同,按键年龄加1
keyagecnt++;
// 是第一次按下吗?
if (Flag_keystate)
{ // 是第一按下
if ( keyagecnt == KEYAGE )
{ // 确定按键按下
Flag_keyprocess = 1; // 对按键解析执行
Flag_keydone = 0; // 清按键任务完成标志(表当前任务正在执行)
Flag_keystate = 0; // 清第一次按下标志
keyagecnt = 0; // 置位按键年龄计数器
/*键音提示*/
OpenBuzzer();
SCH_Add_Task(CloseBuzzer, 10, 0); // 提示音长10毫秒
// 是功能键还是复合键
if (0 != keytemp.ShiftCnt)
{ // 是复合键,等待按键释放
Flag_keyesc = 1; // 置位Flag_keyesc标志,等待按键释放
return;
}
else
{ // 是功能键
if ( (keytemp.FunctionValue == DOUBLE_KEY_1) || (keytemp.FunctionValue == DOUBLE_KEY_2) )
{ // 该功能键允许连击
return;
}
else
{ // 不允许连击
Flag_keyesc = 1; // 置位Flag_keyesc标志,等待按键释放
return;
}
}
}
else
{ // 是抖动就返回
return;
}
}
else
{ // 是连击键.不是第一次按下则判断按键年龄是否等于重复的延缓时间,不等于则返回.
if (keyagecnt == MAXRATE)
{ // 进入连击状态
keyagecnt = keyagecnt - MINRATE; // 按键年龄减重复速度
Flag_keyprocess = 1; // 对按键解析执行
Flag_keydone = 0; // 清按键任务完成标志(表当前任务正在执行)
return;
}
else
{ // 不等于重复的延缓时间返回
return;
}
}
}
}
/******************************************************************************************************/
/*设置主菜单状态寄存器, 1进入设置标志*/
unsigned char g_SET = 0;
/*子功能选项*/
unsigned char g_subset = 0;
/*定义数据指针*/
unsigned char *pF; /*头*/
unsigned char Led_i;
/*闹铃点计数器*/
unsigned char RingCnt;
/*---------------------------------------------------------*-
* 函数名称: KeyProcess()
* 参 数:
* 返 回:
* 函数功能: 键值处理
*
* 说 明:
*
* 当前版本: V1.0 * 取代版本:
* 作 者: wsl * 修 改:
* 版本信息: 2006-12-16 * 修改信息:
-*---------------------------------------------------------*/
void KeyProcess(void)
{
// 若无按键请求则返回
if ( Flag_keyprocess )
{
Flag_keyprocess = 0; // 清按键有效标志
// 是引导键
switch ( keybuffer[1] )
{
case 0:
// 是功能键
switch ( keybuffer[0] )
{
case K_Up:
switch (g_SET)
{
case 0: CloseBuzzer(); break;
case 1:
g_subset++;
if (g_subset > 9) {g_subset = 0;}
Main_MENU_interface(g_subset);
break;
/***************/
case 2:
case 3:
*(pF+Led_i) = *(pF+Led_i)+1; /*指针指向的变量加1*/
if (Led_i == 0) { if (*(pF+Led_i) > 2) {*(pF+Led_i) = 0;} }
else if(Led_i == 2) { if (*(pF+Led_i) > 5) {*(pF+Led_i) = 0;} }
else { if (*(pF+Led_i) > 9) {*(pF+Led_i) = 0;} }
if (*pF == 2) {if (*(pF+1) > 3) {*(pF+1) = 0;}}
break;
/*******************/
default: break;
}
break;
case K_LoopRight:
switch (g_SET)
{
case 0: CloseBuzzer(); break;
case 2:
case 3:
Led_i++;
Flag &= 0x0f;
if (Led_i>3) {Led_i = 0;}
SETBIT(Flag, Led_i+4);
break;
default: break;
}
break;
case K_Enter:
switch (g_SET)
{
case 0: CloseBuzzer(); break;
case 1:
switch (g_subset)
{ /*进入时钟设置板面*/
case 0:
/*进入系统设置板面*/
Led_i = 0;
DATA_Amend(now.hour, now.min, Led_i);
pF = &dispbuf[0]; /*指向显示缓冲区首地址*/
g_SET = 2;
break;
/*进入闹铃设置板面*/
case 1:
/*进入闹铃系统设置板面*/
Led_i = 0;
RingCnt = 0;
DATA_Amend(Ring[RingCnt].hour, Ring[RingCnt].min, Led_i);
/*如果RingIDRegister某位为1,说明该点闹铃声已设置*/
if (GETBIT(BackupRingID, RingCnt))
{ /*点亮最后一位的小数点表示该点闹铃声已设置*/
Dlink4 = 1;
}
else
{
Dlink4 = 0;
}
pF = &dispbuf[0]; /*指向显示缓冲区首地址*/
g_SET = 3;
break;
default: break;
}
break;
/***************************/
case 2: /*保存时间修改设置*/
now.sec = 0x00;
now.min = dispbuf[2]*10 + dispbuf[3];
now.hour = dispbuf[0]*10 + dispbuf[1];
g_UpdataFlagEn = 1; /*数码显示缓冲区更新*/
g_SET = 0; /*清设置标志*/
g_subset = 0;
RTC_interface();
break;
/*********************************/
case 3: /*读闹铃*/
RingCnt++;
if (RingCnt>8-1) {RingCnt = 0;} /*C语言变量从0开始计数,而闹铃点只有8个*/
Led_i = 0; /*数码管闪烁从时的首位开始*/
DATA_Amend(Ring[RingCnt].hour, Ring[RingCnt].min, Led_i);
/*如果RingIDRegister某位为1,说明该点闹铃声已设置*/
if (GETBIT(BackupRingID, RingCnt))
{ /*点亮最后一位的小数点表示该点闹铃声已设置*/
Dlink4 = 1;
}
else
{
Dlink4 = 0;
}
pF = &dispbuf[0]; /*指向显示缓冲区首地址*/
break;
/*********************************/
default: break;
}
break;
default: break;
}
break;
case K_Shift:
if ( keybuffer[0] == K_Up )
{
/*退出设置板面且不保存已修改的数据*/
RTC_interface();
g_UpdataFlagEn = 1; /*数码显示缓冲区更新*/
g_SET = 0; /*清设置标志*/
g_subset = 0;
}
// 是复合键
if (keybuffer[0] == K_Enter)
{
switch (g_SET)
{
case 0:
g_SET = 1; /*置位设置标志*/
g_UpdataFlagEn = 0; /*数码显示缓冲区不更新*/
g_subset = 0;
/*进入系统设置板面*/
Main_MENU_interface(g_subset);
break;
case 3:
/*保存闹铃修改设置*/
dispbuf[0] = (dispbuf[0]<<4) + dispbuf[1];
dispbuf[2] = (dispbuf[2]<<4) + dispbuf[3];
SetRing(dispbuf[0] , dispbuf[2], RingCnt);
dispbuf[0] = dispbuf[0]>>4;
dispbuf[2] = dispbuf[2]>>4;
g_UpdataFlagEn = 1; /*数码显示缓冲区更新*/
g_SET = 0; /*清设置标志*/
g_subset = 0;
RTC_interface();
break;
default : break;
}
}
break;
default: break;
}
}
// 置位按键任务完成标志
Flag_keydone = 1;
}
/*****************************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -