⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key.c

📁 《时间触发嵌入式系统设计模式》一书中的合作式调度器的算法
💻 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 + -