IAR环境下的程序!
矩阵按键在单片机设计中经常见到,下面给大家几个程序!如果有需求可以看看!
矩阵按键,扫描
下面程序是淘来的!
#include<msp430g2553.h>
/***************全局变量***************/
unsigned char Key_Val; //存放键值
void CtrlKey(unsigned char sw); //控制键盘开关//sw=0关 sw=1开
/*******************************************
函数名称:Init_Keypad
功 能:初始化扫描键盘的IO端口
参 数:无
返回值 :无
********************************************/
void Init_Keypad(void)
{
P1DIR = 0x0f; //P1.0~P1.3设置为输出状态,P1.4~P1.7输入 状态(上拉H)
P1OUT=0;
P1IES =0xf0; //P1.4~P1.7允许中断
P1IE =0xf0; //P1.4~P1.7下降沿触发中断
P1IFG=0; //中断标志清0
Key_Val = 0;
}
/*******************************************
函数名称:Check_Key
功 能:扫描键盘的IO端口,获得键值
参 数:无
返回值 :无
********************************************/
//p14\5\6\7 接上拉电阻
/***************************************
key_Val 对应键值
列:[p14] [p15] [p16] [p17]
↓ ↓ ↓ ↓
行:
[p13]→ 1 2 3 4
[p12]→ 5 6 7 8
[p11]→ 9 10 11 12
[p10]→ 13 14 15 16
***************************************/
void Check_Key(void)
{
unsigned char row ,col,tmp1,tmp2;
unsigned char keymap[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};//设置键盘逻辑键值
tmp1 = 0x08;
for(row = 0;row < 4;row++) //行扫描
{
P1OUT = 0x0f; //P1.0~P1.3输出全1
P1OUT -= tmp1; //P1.0~p1.3输出四位中有一个为0
tmp1 >>=1;
if((P1IN & 0xf0)<0xf0) //是否P1IN的P1.4~P1.7中有一位为0
{
tmp2 = 0x10; // tmp2用于检测出哪一位为0
for(col = 0;col < 4;col++) // 列检测
{
if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是
{
Key_Val = keymap[row*4 + col]; // 获取键值
return; // 退出循环
}
tmp2 <<= 1; // tmp2右移1位
}
}
}
}
/*******************************************
函数名称: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 & 0xf0) < 0xf0) //如果有键按下
{
delay(); //消除抖动
Check_Key(); // 调用check_Key(),获取键值
}
}
/*********************************************************************
控制打开或者关闭键盘中断
SW= 0:关闭; ELSE:打开
*********************************************************************/
void CtrlKey(unsigned char sw)
{
if(sw==0)
P1IE =0; //关闭端口中断
else
P1IE =0xf0; //打开端口中断
}
/*端口1按键中断*/
#pragma vector=PORT1_VECTOR
__interrupt void Port(void)
{
if((P1IFG&0xf0)!=0)
{
Key_Event();
if(Key_Val!=0) //键值!=0有键按下
{
CtrlKey(0); //关键盘中断
}
}
P1IFG=0;P1OUT=0; //清中断标志
}
下面的程序是自己改了下,端口发生了变化!
按键矩阵也发生了变化!
/***********************************************************************************************************************************************************/
#include<msp430g2553.h>
/***************全局变量***************/
unsigned char Key_Val; //存放键值
void main()
{
WDTCTL=WDTPW+WDTHOLD;
Init_Keypad();
_BIS_SR(LPM3_bits + GIE); //最低功耗睡眠
while(1);
}
/*******************************************
函数名称:Init_Keypad
功 能:初始化扫描键盘的IO端口
参 数:无
返回值 :无
********************************************/
void Init_Keypad(void)
{
P1DIR = 0x38; //P1.0~P1.3设置为输出状态,P1.4~P1.7输入 状态(上拉H)
P1OUT=0;
P1IES =0xC0; //P1.4~P1.7允许中断
P1IE =0xC0; //P1.4~P1.7下降沿触发中断
P1IFG=0; //中断标志清0
Key_Val = 0;
}
/*******************************************
函数名称:Check_Key
功 能:扫描键盘的IO端口,获得键值
参 数:无
返回值 :无
********************************************/
//p13\14\15 接上拉电阻
/***************************************
key_Val 对应键值
列:[p13] [p14] [p15]
↓ ↓ ↓
行:
[p17]→ 1 2 3
[p16]→ 4 5 6
***************************************/
void Check_Key(void)
{
unsigned char row ,col,tmp1,tmp2;
unsigned char keymap[] = {1,2,3,4,5,6};//设置键盘逻辑键值
tmp1 = 0x08; //从(xxxx1xxx相左移)
for(row = 0;row < 3;row++) //列扫描
{
P1OUT = 0x38; //P1.3~P1.5输出全1
P1OUT -= tmp1; //P1.3~p1.5输出四位中有一个为0
tmp1 <<=1;
if((P1IN & 0xC0)<0xC0) //是否P1IN的P1.4~P1.7中有一位为0
{
tmp2 = 0x80; // tmp2用于检测出哪一位为0
for(col = 0;col < 2;col++) // 行检测
{
if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是
{
Key_Val = keymap[row*4 + col]; // 获取键值
return; // 退出循环
}
tmp2 >>= 1; // tmp2右移1位
}
}
}
}
/*******************************************
函数名称: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 & 0xf0) < 0xf0) //如果有键按下
{
delay(); //消除抖动
Check_Key(); // 调用check_Key(),获取键值
}
}
#pragma vector=PORT1_VECTOR
__interrupt void Port(void)
{
delay();
if((P1IN&0XC0)<0XC0)
{
Check_Key();
switch(Key_Val)
{
case 1:
{ ;自己接相应按键的功能
break;
}
case 2:
{ ;自己接相应按键的功能
break;
}
case 3:
{ ;自己接相应按键的功能
break;
}
case 4:
{ ;自己接相应按键的功能
break;
}
case 5:
{ ;自己接相应按键的功能
break;
}
case 6:
{ ;自己接相应按键的功能
break;
}
default:break;
}
}
P1IFG=0; //清中断标志
}
下面这个按键用了数组了,存放按键的值,可以应用于密码锁之类的应用!为网上淘来
/************************************************************************************************************************************************************/
// 此示例程序为中断方式,得到键盘的键值,存放在队列keybuff[10]中
// 此示例程序没有显示,
// 键盘的按键按下引起P1口的中断服务程序,得到键盘的键值,保存到键值队列
// 在其他的中断服务程序中通过键值队列中的数据引导程序的流程
#include <msp430x14x.h>
unsigned char keybuff[10];
unsigned char keypoint=0;
void delay(int v)
{
while(v!=0)v--;
}
unsigned char key(void)
{
unsigned char x=0xff;
P1DIR=0X0F;
P1OUT=0X01; //扫描第一行
if((P1IN&0X70)==0X10)
x=0;
else
if((P1IN&0X70)==0X20)
x=1;
else
if((P1IN&0X70)==0x40)
x=2;
else
{
P1OUT=0X2; //扫描第二行
if((P1IN&0X70)==0X10)
x=3;
else
if((P1IN&0X70)==0X20)
x=4;
else
if((P1IN&0X70)==0x40)
x=5;
else
{
P1OUT=0X4; //扫描第三行
if((P1IN&0X70)==0X10)
x=6;
else
if((P1IN&0X70)==0X20)
x=7;
else
if((P1IN&0X70)==0x40)
x=8;
else
{P1OUT=8; //扫描第四行
if((P1IN&0X70)==0X10)
x=9;
else
if((P1IN&0X70)==0X20)
x=10;
else
if((P1IN&0X70)==0x40)
x=11;
}
}
}
return(x);
}
unsigned char keyj(void)
{unsigned char x;
P1DIR=0x0f;
P1OUT=0x0f; //键盘硬件:P10--P13为行线,最上面一根为P10
x=(P1IN&0X70); // P14--P16为列线,最左边一根为P14,列线下拉
return(x); // 无按键,返回 0?; 有按键返回 非0
}
interrupt[PORT1_VECTOR] void port1key(void)
{
if(keyj()!=0X00)
{
delay(300) ; //消抖动
if(keyj()!=0X0)
{
keybuff[keypoint]=key(); //按键见键值保存到队列
keypoint++; //
if(keypoint==10)
keypoint=0;
}
}
P1OUT=0X0F;
P1IFG=0X0; //清除中断标志
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; /* // Stop WDT */
P1DIR=0XF;
P1OUT=0XF;
P1IES=0X0;
P1IE=0X70; //列线上升沿允许P1中断
_EINT(); /*/ Enable interrupts */
while(1)
{
LPM0;
_NOP();
}
}
这个是单个按键是,输入端的P1REN要设为1。允许上拉电阻!为网上淘来
/************************************************************************************************************************************************************/
关于msp430g2553的按键程序,虽然很简单,但是纠结了一个下午,错就错在看视频的时候那个老师的片子没有加上拉电阻但是正常运行,我的却不可以,现在找到问题,希望对和我一样遇着这个问题的人有所帮助;
#include "msp430g2553.h"
#define keyin (P1IN & 0x08)
void delay(void);
int main(void)
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
P1REN |= BIT3;
P1DIR |= BIT6;
P1OUT &= ~BIT6;
while(1)
{
if(keyin != 0x08)
{
delay();
if(keyin != 0x08)
{
while(keyin !=0x08);
P1OUT ^= BIT6;
}
}
}
}
void delay(void)
{
unsigned int i;
for(i=12000; i>0; i--);
}
有意见的读者,可以评论,希望帮到大家了! |