#include <MSP430x44x.h>
#include "hl_key.h"
#include "df_timera.h"
//选用端口定义
#define KEYDIR P1DIR
#define KEYIES P1IES
#define KEYIE P1IE
#define KEYIN P1IN
#define KEYOUT P1OUT
#define KEYIFG P1IFG
//定义键盘管脚
#define KEY_H0 BIT0
#define KEY_H1 BIT1
#define KEY_H2 BIT2
#define KEY_H3 BIT3
#define KEY_L0 BIT4
#define KEY_L1 BIT5
#define KEY_L2 BIT6
#define KEY_MOD_H (KEY_H0+KEY_H1+KEY_H2+KEY_H3)//行端口的模
#define KEY_MOD_L (KEY_L0+KEY_L1+KEY_L2) //列端口的模
#define KEY_LIE 3 //列数
unsigned char key_Map[12]={1,2,3,4,5,6,7,8,9,10,11,12};
unsigned char KeyZhi=KEY_NONE;//经过确认的键值
unsigned char KeyDown=KEY_NONE;//被按下的键
/*******************************
初始化
*******************************/
void InitKey()
{
KEYDIR &= ~KEY_MOD_H; //设置行端口为输入
KEYDIR |= KEY_MOD_L; //设置列端口为输出
KEYOUT &= ~KEY_MOD_L; //设置列端口输出低电平
KEYIES |= KEY_MOD_H; //设置行端口下降沿中断
KEYIE |= KEY_MOD_H; //打开行端口中断
}
/***********************************************
打开或者关闭键盘
sw:0:关闭;100:打开
***********************************************/
void GoKey(unsigned char sw)
{
if(sw==0)
KEYIE &= ~KEY_MOD_H; //关闭端口中断
else
KEYIE |= KEY_MOD_H; //打开端口中断
}
/*******************************
获取键值
*******************************/
unsigned char GetKey()
{
return KeyZhi;
}
/****************************************************
判断按键有效性
****************************************************/
void IsKey()
{
unsigned char key;
//key=ReadKey();
key=check_Key();
if(key==KeyDown)
{
KeyZhi=key; //按键处理程序
}
else
{
KeyDown=KEY_NONE;
GotimeDfA(0); //关闭定时器
GoKey(100); //打开键盘中断
}
}
/******************************************
端口1中断函数
******************************************/
#pragma vector=PORT1_VECTOR
__interrupt void Port1()
{
if((KEYIFG&KEY_MOD_H)!=0) //判断是否是按键触发的中断
{
//KeyDown=ReadKey();
KeyDown=check_Key();
if(KeyDown!=KEY_NONE)
{
GoKey(0); //关闭键盘中断
GotimeDfA(100); //打开定时器A
}
}
KEYIFG=0; //清除中断标志
}
/*************************************************
行列式键盘读取键值,判断哪个键被按下
返回值:读取的键值
*************************************************/
/*unsigned char ReadKey()
{
unsigned char key=0,hang,q0=0,q1;
//判断按键的列的掩码
unsigned char lie=(KEY_MOD_L&(~KEY_L0))+KEY_MOD_H;
//确定按键的行
hang=(~KEYIN)&KEY_MOD_H; //读入的数据取反,然后屏蔽掉不需要的位
if(hang!=0)
{
//确定按键的列
for(q0=0;q0<KEY_LIE-1;q0++)
{
KEYOUT =0XFF;
KEYOUT &= lie; //某一列端口输出低电平,其它输出高电平
q1=KEYIN&KEY_MOD_H;
if((q1&hang)==0)
break; //确定了列值
lie <<=1;
}
if(q0!=KEY_LIE)
key=hang+((~lie)&KEY_MOD_L); //键值为行值加列值
else
key=KEY_NONE;
}
else
key=KEY_NONE;
KEYOUT &= ~KEY_MOD_L; //设置列端口输出低电平
return key;
}*/
/*********************************************
* Check_Key(),检查按键,确认键值
*********************************************/
unsigned char check_Key()
{
unsigned char key_val;
unsigned char row ,col,tmp1,tmp2;
// tmp1用来设置P2OUT的值,使P2.4~P2.6中有一个为0
tmp1 = 0x10;
for(col=0;col<3;col++)
{
KEYOUT |= 0x70; // P2.4-P2.6=1
KEYOUT -= tmp1; // P2.4-P2.6中有一个为0
tmp1 = tmp1*2; // tmp1左移一位
if ((KEYIN & 0x0f) < 0x0f) //确定按键所在列
{ // 是否KEYIN的P2.0-P2.3中有一位为0
tmp2 = 0x01; // tmp2用于检测出那一位为0
for(row =0;row<4;row++)
{ // 行检测
if((KEYIN & tmp2)==0x00)
{ // 是否是该行
key_val =key_Map[ row*3 +col] ; // 获取键值
break;
}
tmp2 *= 2; // tmp2左移
}
}
}
return key_val; // 退出循环
}