我使用MSP430F427A芯片在IAR平台下面做一个电子称系统,主要包括SD16AD转换、12864显示和4*3键盘输入。工作正常后发现
键盘第一行'0'、‘1’、‘2’三个按键开始输入正常,几轮输入以后按下'0'、‘1’都显示为'0',有时按‘2’也显示为'0',其他9
个按键工作一直正常。排除了硬件问题后单步跟踪键盘程序,最终发现问题出在下面:
按下'1' 第一行第2列 运行到
Key_Val = keymap[row*3 + col]; // 获取键值
此时 row = 0 col = 1 Key_Val 应该 = 1 , 但是Key_Val = 0 ? 不能赋值,为什么?敬请各位老师赐教!
keymap[]定义如下:
unsigned char keymap[] = {0,1,2,3,4,5,6,7,8,9,10,11};//设置键盘逻辑键值
键盘程序如下:
#include "jp.h"
#include "12864.h"
unsigned char Key_Val; //存放键值
unsigned char keymap[] = {0,1,2,3,4,5,6,7,8,9,10,11};//设置键盘逻辑键值
// unsigned char *p2;
/*******************************************
函数名称:Init_Keypad
功 能:初始化扫描键盘的IO端口
参 数:无
返回值 :无
********************************************/
void Init_Keypad(void)
{
P1DIR = 0x8f; //P1.0~P1.3设置为输出状态,P1.4~P1.6输入 状态(上拉H)
//P1.7 方向为输出,连接蜂鸣器的信号输入脚
P1IES =0x70; //P1.4~P1.6允许中断
P1IE =0x70; //P1.4~P1.6下降沿触发中断
P1IFG=0; //中断标志清0
Key_Val = 0;
}
/*******************************************
函数名称:Check_Key
功 能:扫描键盘的IO端口,获得键值
参 数:无
返回值 :无
********************************************/
//p14\5\6 接上拉电阻
/***************************************
Key_Val 对应键值
列:[p14] [p15] [p16]
↓ ↓ ↓
行:
[p13]→ 0 1 2
[p12]→ 3 4 5
[p11]→ 6 7 8
[p10]→ 9 10 11
***************************************/
void Check_Key(void)
{
unsigned char row ,col,tmp1,tmp2;
// unsigned char keymap[] = {0,1,2,3,4,5,6,7,8,9,10,11};//设置键盘逻辑键值
// unsigned char *p2;
// p2=keymap;
//与程序计算键值的映射
tmp1 = 0x08; // 0000 1000
for(row = 0;row < 4;row++) //行扫描
{
P1OUT = 0x0f; //P1.0~P1.3输出全1
P1OUT -= tmp1; //P1.4~p1.6输出四位中有一个为0
tmp1 >>=1; //0000 0100 0000 0010 0000 0001
if((P1IN & 0x70)<0x70) //是否P1IN的P1.0~P1.3中有一位为0
{
tmp2 = 0x10; // tmp2用于检测出哪一列为0
for(col = 0;col < 3;col++) // 列检测
{
if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是
{
Key_Val = keymap[row*3 + col]; // 获取键值 问题出在此行,有时不能赋值
return; // 退出循环
}
tmp2 <<= 1; //0001 0000 0010 0000 0100 0000
}
}
}
}
/*******************************************
函数名称:delay
功 能:延时约15ms,完成消抖功能
参 数:无
返回值 :t= tmp*5*clk 根据使用时钟调整tmp值
********************************************/
void delay(void)
{
unsigned int tmp;
for(tmp = 12000;tmp > 0;tmp--);
}
/*******************************************
函数名称:Key_Event
功 能:检测按键,并获取键值
参 数:无
返回值 :无
********************************************/
void Key_Event(void)
{
unsigned char tmp;
P1OUT =0; // 设置P1OUT全为0,等待按键输入
tmp = P1IN; // 获取 p1IN
if((tmp & 0x70) < 0x70) //如果有键按下
{
delay(); //消除抖动
Check_Key(); // 调用check_Key(),获取键值
}
}
/*********************************************************************
控制打开或者关闭键盘中断
SW= 0:关闭; ELSE:打开
*********************************************************************/
/*
void CtrlKey(unsigned char sw)
{
if(sw==0)
P1IE =0; //关闭端口中断
else
P1IE =0xf0; //打开端口中断
}*/
/*******************************************
函数名称:*IntToStr
功 能:整数转化成字符串
参 数:int num, char str[]
返回值 :str
********************************************/
/**/
char *IntToStr(int num, unsigned char str[])
{
int i = 0, j = 0;
char temp[100];
while(num)
{
temp[i] = num % 10 + '0'; //取模运算得到从后往前的每一个数字变成字符
num = num / 10;
i++;
}
temp[i] = 0; //字符串结束标志
i = i - 1; //回到temp最后一个有意义的数字
while(i >= 0)
{
str[j] = temp[i];
i--;
j++;
}
str[j] = 0; //字符串结束标志
return str;
}
/*端口1按键中断*/
#pragma vector=PORT1_VECTOR /*端口1按键中断*/
__interrupt void Port1(void)
{
Key_Event(); //
if(Key_Val<10) //处理0~9按键,前一次键值*10+本次键值
{
tmp=tmp+Key_Val; //tmp=键入饲料数量
LCD_SetTextPos(2,5); //第三行右边位置
IntToStr(tmp, h0); //整数转换为字符串函数
LCD_Print(h0); //显示键入值
tmp=tmp*10;
if(tmp>10000)tmp=0; //防止键入值过大超界
}
else if(Key_Val==10) //显示下一个饲料和数量
{
Next(p,p1);
}
else if(Key_Val==11)
{
repl(p,p1); //用键入值替换slsl[]表值
}
KEY_IFG=0;
KEY_OUT=0; //清中断标志
}
void main( void )
{
p=slmc[0];
p1=slsl;
tmp=0;
i=0;
szxb=0;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
Init_Sys();
Init_Keypad(); //初始化键盘
LCD_Clear(); //清屏
KEY_DIR&=~fmq; //关闭蜂鸣器
cshpm(p,p1); //初始化平屏幕
KEY_IE =0x70; //打开P1端口中断
__enable_interrupt(); //开启总中断,这一步没有的话,所有的中断都不能触发
while(1);
}