咱直接贴代码
因为水平本就不高
希望大家能加不好的地方指出
main.c
/********************************************************************
//DM430-A型开发板矩阵键盘控制程序,通过数码管显示按键值,采用逐行扫描
//4X4键盘接在P1口,通过控制IO口状态变化,逐行扫描按键是否按下
//调试环境:EW430 V5.30
//作者:mmp
//创客
P1口设置为按键插入口
更改引脚在Config.h文件中
有黑的地方插P1.0~P1.3 因为有上拉电阻
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
本程序按键布局
按照需求更改
case 0xee:key=1;break; //上拉电阻按下按键,P1.4输出低电平
case 0xed:key=2;break; //P1.5输出低电平
case 0xeb:key=3;break; //P1.6输出低电平
case 0xe7:key=4;break; //P1.7输出低电平
这个位置
********************************************************************/
#include
#include "Config.h" //开发板配置头文件,主要配置IO端口信息
#include "delay.h"
//***********************************************************************
// MSP430IO口初始化
//***********************************************************************
void Port_Init()
{
LED8SEL = 0x00; //设置IO口为普通I/O模式,此句可省
LED8DIR = 0xFF; //设置IO口方向为输出
LED8PORT = 0xFF; //P2口初始设置为FF
KEYSEL = 0x00; //设置IO口为普通I/O模式,此句可省
KEYDIR = 0xf0; //低位输入模式(vcc流入)模式,外部上拉电阻
KEYPORT= 0x0f; //初始值0xF0 0x0f
}
//**********************************************************************
// 键盘扫描子程序,采用逐行(列)扫描的方式
//**********************************************************************
uchar Key_Scan(void)
{
uchar statevalue,key_checkin,key_check;
KEYPORT=0x0f; //在IO口由输出方式变为输入方式时要延迟一个周期
KEYPORT=0x0f; //采取写两次的方法延时
key_checkin=KEYIN; //读取IO口状态,判断是否有键按下
if(key_checkin!=0x0f) //IO口值发生变化则表示有键按下
{
Delay_Nms(20); //键盘消抖,延时20MS
key_checkin=KEYIN;
if(key_checkin!=0x0f)
{
KEYPORT=0xef; //逐行扫描开始 将P1.4 输出低电平 来扫描第一行
KEYPORT=0xef; //写两次延时,下同
key_check=KEYIN;
switch (key_check) //根据读到的IO口值判断按键的按下情况
{ //上拉电阻平时为高电平,按下按键为低电平
case 0xee:key=1;break; //上拉电阻按下按键,P1.4输出低电平
case 0xed:key=2;break; //P1.5输出低电平
case 0xeb:key=3;break; //P1.6输出低电平
case 0xe7:key=4;break; //P1.7输出低电平
}
KEYPORT=0xdf;
KEYPORT=0xdf;
key_check=KEYIN;
switch (key_check)
{
case 0xde:key=5;break;
case 0xdd:key=6;break;
case 0xdb:key=7;break;
case 0xd7:key=8;break;
}
KEYPORT=0xbf;
KEYPORT=0xbf;
key_check=KEYIN;
switch (key_check)
{
case 0xbe:key=9;break;
case 0xbd:key=10;break;
case 0xbb:key=11;break;
case 0xb7:key=12;break;
}
KEYPORT=0x7f;
KEYPORT=0x7f;
key_check=KEYIN;
switch (key_check)
{
case 0x7e:key=13;break;
case 0x7d:key=14;break;
case 0x7b:key=15;break;
case 0x77:key=16;break;
}
}
}
else
{
statevalue=0xff; //无按键时返回值
key=statevalue;
return(key);
}
return(key);
}
//*************************************************************************
// 主程序
//*************************************************************************
void main(void)
{
WDT_Init(); //看门狗初始化
Port_Init(); //端口初始化,用于控制IO口输入或输出
while(1)
{
Key_Scan(); //键盘扫描,看是否有按键按下
if(key!=0xff) //如果有按键按下,则显示该按键键值0~15
{
{
switch(key)
{
case 1: LED8PORT = BIT0 + BIT1 ;break; //根据键值显示到数码管上
case 2: LED8PORT = BIT2 + BIT3 ;break;
case 3: LED8PORT = BIT4 + BIT5 ;break;
case 4: LED8PORT = BIT6 + BIT7 ;break;
case 5: LED8PORT = BIT1 + BIT2 ;break;
case 6: LED8PORT = BIT1 + BIT3 ;break;
case 7: LED8PORT = BIT1 + BIT4 ;break;
case 8: LED8PORT = BIT1 + BIT5 ;break;
case 9: LED8PORT = BIT1 + BIT6 ;break;
case 10: LED8PORT = BIT0 + BIT1;break;
case 11: LED8PORT = BIT0 + BIT2;break;
case 12: LED8PORT = BIT0 + BIT3 ;break;
case 13: LED8PORT = BIT0 + BIT4 ;break;
case 14: LED8PORT = BIT0 + BIT5 ;break;
case 15: LED8PORT = BIT0 + BIT6 ;break;
case 16: LED8PORT = BIT0 + BIT7 ;break;
}
}
}
else
{
LED8PORT = 0XFF ; //没有按键的时候显示上次的键值 第八个灯灭,其它的亮
//第八个灯亮
}
}
}
#define CPU_F ((double)8000000)
//#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
//#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/*当BRCLK=CPU_F时用下面的公式可以计算,否则要根据设置加入分频系数*/
#define baud 9600 //设置波特率的大小
#define baud_setting (uint)((ulong)CPU_F/((ulong)baud)) //波特率计算公式
#define baud_h (uchar)(baud_setting>>8) //提取高位
#define baud_l (uchar)(baud_setting) //低位
#define LED8PORT P2OUT //P2接8个LED灯
#define LED8SEL P2SEL //P2接8个LED灯
#define LED8DIR P2DIR //P2接8个LED灯
#define KEYPORT P1OUT //按键所在的端口P3
#define KEYSEL P1SEL //控制口功能寄存器,控制功能模式
#define KEYDIR P1DIR //控制口方向寄存器
#define KEYIN P1IN //键盘扫描判断需要读取IO口状态值
uchar key; //键值变量
//***********************************************************************
// MSP430内部看门狗初始化
//***********************************************************************
void WDT_Init()
{
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
}
```c
#ifndef __DELAY
#define __DELAY
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
void Delay_Nus(uint n);
void Delay_1ms(void);
void Delay_Nms(uint n);
#endif
```c
/********************************************
文件名:delay.c
编写者:xdq
描述:延时程序。用于14xx系列。
MCLK:12m SCLK:4kHz ACLK:
版本:2012-6
********************************************/
#include
#include "delay.h"
/*******************************************
函数名称:Delay_Nus
功 能:延时N个us的时间
参 数:n--延时长度
返回值 :无
********************************************/
void Delay_Nus(uint n)
{
uchar i;
for(i = n;i > 0;i--)
_NOP();
}
/*******************************************
函数名称:Delay_1ms
功 能:延时约1ms的时间
参 数:无
返回值 :无
********************************************/
void Delay_1ms(void)
{
uchar i;
for(i = 150;i > 0;i--) _NOP();
}
/*******************************************
函数名称:Delay_Nms
功 能:延时N个1ms的时间
参 数:n--延时长度
返回值 :无
********************************************/
void Delay_Nms(uint n)
{
uint i;
for(i = n;i > 0;i--) Delay_1ms();
}
上面的代码对于初学者更加易懂
下面是改进版原理是一样的
首先,确保您的单片机P1.0~P1.3是否有上拉电阻
才能直接使用本程序
根据您的开发板来确定哪个I/O口连接4x4矩阵按键
#define u8 unsigned charu8 b[]={0xef, 0xdf, 0xbf, 0x7f};
void IO_Init()
{
P1DIR = 0xf0; // 把P3.0-3.3//输入模式,3.4-3.7为输出模式
}
void Key_Board(void)
{
u8 j,n;//第0行检测
for(n=0; n<4; n++)
{
P1OUT = b[n]; // XXXX 1110
//判断是否有按键被按下 bit4-7
if((P1IN&0X0f) !=0x0f) //1101 xxxx &1111 0000 ->1101 0000
{
delay_ms(2);//延时消抖2ms
if((P1IN&0X0f) != 0x0f)//判断是否有按键真的被按下
{
//判断倒是是那个按键被按下
j = P1IN&0X0f; //对P1口值,与f0目的是将低四位清零
switch(j)
{
case 0x0e: temp =0+n*4; break;// 1110 0000
case 0x0d: temp =1+n*4; break;// 1101 0000
case 0x0b: temp =2+n*4; break;// 1011 0000
case 0x07: temp =3+n*4; break;// 0111 0000
}
}
}
}
}