通过232串口设置MSP430F149IPM单片机液晶显示时间的程序
下面介绍一段通过232串口设置MSP430F149IPM单片机液晶显示时间的程序。用户通过串口发送0X01,0X02,0X03,0X04可以改变单片机液晶显示时间,当到达一定设置时间时,单片机P2端口输出7路高电平,1路低电平,
第二段程序,可以从单片机按键像计算机232串口发送0x00,同时单片机液晶屏显示时间。
MSP430单片机电路如下,程序通过IAR430V5.3软件编译通过,生成.txt文件,使用BSL下载软件-Msp430BSL
通过USB端口把.TXT文件烧写到单片机中。程序和电路可以在下面的网址下载:链接:pan.baidu.com/s/1PxUz7CXQ… ;
提取码:2kcy
链接:pan.baidu.com/s/1e1uS02vl… ;
提取码:kuw9
程序1:
/*****************************************************
程序功能:在1602液晶上显示用MCU的TimerA模拟的数字
式实时时钟。
测试说明:观察液晶显示
程序功能:接收来自PC机的字符,然后重新发送给PC机
程序功能:串口发送十六进制数01,液晶显示时间25:25:25,
串口发送十六进制数02,液晶显示时间35:35:35,
串口发送十六进制数03,液晶显示时间11:11:34,
液晶计时11:10:60时,P2口输出01111111,液晶显示33:33:11
通信格式:N.8.1, 9600
无校验,8个数据位,1个停止位,波特率9600
*****************************************************/
#include <msp430x14x.h>
#include "cry1602.h"
#include "clock.h"
#include "cry1602.c"
#include "clock.c"
#define keyin P3IN
uchar tishi[]={"Current Time is"}; //提示信息
void delay(void);
extern uchar second,minute,hour,hour0;
extern uchar pmin,phour,ps1;
#define SetTime(H,M,S) {second=S;minute=M;hour=H;hour0=H;}
uchar scandata[16] ;
/*主函数/
void main(void)
{
/下面六行程序关闭所有的IO口/
P1DIR = 0XFF;P1OUT = 0XFF;
P2DIR = 0XFF;P2OUT = 0XFF;
P3DIR = 0XFF;P3OUT = 0XFF;
P4DIR = 0XFF;P4OUT = 0XFF;
P5DIR = 0XFF;P5OUT = 0XFF;
P6DIR = 0XFF;P6OUT = 0XFF;
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
// P6DIR |= BIT2;P6OUT |= BIT2;//关闭电平转换
// P6DIR |= BIT6;P6OUT &= ~BIT6;//关闭电平转换
P3SEL |= 0x30; // 选择P3.4和P3.5做UART通信端口
ME1 |= UTXE0 + URXE0; // 使能USART0的发送和接受
UCTL0 |= CHAR; // 选择8位字符
UTCTL0 |= SSEL0; // UCLK = ACLK
UBR00 = 0x03; // 波特率9600
UBR10 = 0x00; //
UMCTL0 = 0x4A; // Modulation
UCTL0 &= ~SWRST; // 初始化UART状态机
// IE1 |= URXIE0; // 使能USART0的接收中断
CCR0 = 32768 - 1; //设置定时器A的中断时间为1S
TACTL = TASSEL_1 + MC_1; //计数时钟ACLK, 增计数模式
CCTL0 |= CCIE; //使能CCR0比较中断
_EINT(); //打开全局中断
// IE1 |= URXIE0; // 使能USART0的接收中断
//请在此处设置正确时间
SetTime(11,11,34); //顺序:时,分,秒,格式:BCD码
LcdReset();
DispNChar(0,0,15,tishi); //显示提示文字
Disp1Char(6,1,':'); //显示字符 :
Disp1Char(9,1,':');
P2DIR = 0xff; //设置P2口方向为输出
// SetTime( RXBUF0, RXBUF0, RXBUF0);
// P2OUT = 0x40;
// if(IFG1 & URXIFG0) //如果收到字符
// {
//SetTime( RXBUF0, RXBUF0, RXBUF0); //顺序:时,分,秒,格式:BCD码
// }
//else
// {
// SetTime(11,11,34); //顺序:时,分,秒,格式:BCD码
//}
while(1)
{
// _EINT(); //打开全局中断
// LPM1; //进入LPM1模式
// while (!(IFG1 & UTXIFG0)); //等待以前的字符发送完毕
// TXBUF0 = RXBUF0; //将收到的字符发送出去
// if(IFG1 & URXIFG0) //如果收到字符
//{
// switch(RXBUF0)
// {
//case 0x01:
if(RXBUF0 == 0x01) //如果是第一个按键被按下
{
second=25;
minute=25;
hour=25;
//SetTime(19,19,19);
TXBUF0 = RXBUF0;
// }
//}
}
if(RXBUF0 == 0x02) //如果是第一个按键被按下
{
second=35;
minute=35;
hour=35;
//SetTime(19,19,19);
TXBUF0 = RXBUF0;
// }
//}
}
if(RXBUF0 == 0x03) //如果是第一个按键被按下
{
second=34;
minute=11;
hour=11;
//SetTime(19,19,19);
TXBUF0 = RXBUF0;
// }
//}
}
// else
// {
// SetTime(11,11,34); //顺序:时,分,秒,格式:BCD码
// }
//scandata[16] =RXBUF0;
// if(RXBUF0!=0X00)
// {
// SetTime( RXBUF0, RXBUF0, RXBUF0); //顺序:时,分,秒,格式:BCD码
// }
//LPM3; //进入LPM3低功耗模式
Display();
if(second == 60&minute==10&hour==11) //如果是第一个按键被按下
{
P2OUT = 0x80;
SetTime(33,33,11);
}
if(keyin == 0xbf) //如果是第一个按键被按下
{
delay();
if(keyin == 0xbf)
{
while(keyin != 0xbf); //等待按键放开
SetTime(22,22,11); //顺序:时,分,秒,格式:BCD码
return;
}
}
}
}
/*******************************************
函数名称:TimerA_ISR
功 能:定时器A的中断服务函数
参 数:无
返回值 :无
********************************************/
#pragma vector=TIMERA0_VECTOR
__interrupt void TimerA_ISR(void)
{
Clock();
LPM3_EXIT;
}
void delay(void)
{
uint tmp;
for(tmp = 12000;tmp > 0;tmp--);
}
/*******************************************
函数名称:UART0_RXISR
功 能:UART0的接收中断服务函数,在这里唤醒
CPU,使它退出低功耗模式
参 数:无
返回值 :无
********************************************/
#pragma vector = UART0RX_VECTOR
__interrupt void UART0_RXISR(void)
{
LPM1_EXIT; //退出低功耗模式
}
//#include <msp430x44x.h>
#include "cry1602.h"
/全局变量**/
uchar second,minute,hour,hour0; //秒、分、时变量
uchar pmin,phour,ps1; //辅助计算变量
/*******************************************
函数名称:Clock
功 能:计算当前时间
参 数:无
返回值 :无
说明 :本函数对本文件开头定义的second,minute,
hour,hour0四个全局变量进行操作
********************************************/
void Clock(void)
{
second -= 1;
// second<=60& second>=0;
// minute<=60&minute>=0;
// hour<=100&hour>=0;
if(second == 0)
{
second = 60;
minute -= 1;
if(minute == 0)
{
minute = 60;
hour -= 1; hour0 -= 1;
if(hour == 0) hour = 24;
}
}
}
//void Clock(void)
//{
// second -= 1;
// second<=60& second>=0;
// minute<=60&minute>=0;
// hour<=100&hour>=0;
//if(second == 60)
// {
// second = 0;
// minute -= 1;
//if(minute == 60)
//{
// minute = 0;
// hour -= 1; hour0 -= 1;
// if(hour == 24) hour = 0;
//}
// }
//}
/*******************************************
函数名称:Display
功 能:在1602液晶上显示时间
参 数:无
返回值 :无
说明 :本函数对本文件开头定义的全局变量进行
操作
********************************************/
void Display(void)
{
uchar s0,s1;
uchar m0,m1;
uchar h0,h1;
s1 = second / 10; //十位
s0 = second - (s1 * 10); //个位
s1 += 48; //加上48等于其对应的ASCII码
s0 += 48;
Disp1Char(11,1,s0);
if(ps1 != s1)
{
ps1 = s1;
Disp1Char(10,1,s1);
}
if(pmin != minute)
{
pmin = minute;
m1 = minute / 10;
m0 = minute - (m1 * 10);
m1 += 48;
m0 += 48;
Disp1Char(7,1,m1);
Disp1Char(8,1,m0);
}
if(phour != hour)
{
phour = hour;
h1 = hour / 10;
h0 = hour - (h1 * 10);
h1 += 48;
h0 += 48;
Disp1Char(4,1,h1);
Disp1Char(5,1,h0);
}
}
void Clock(void);
void Display(void);
#include <msp430x14x.h>
#include "cry1602.h"
typedef unsigned char uchar;
typedef unsigned int uint;
/宏定义*/
#define DataDir P2DIR
#define DataPort P2OUT
#define Busy 0x80
#define CtrlDir P6DIR
#define CLR_RS P6OUT&=~BIT3; //RS = P3.0
#define SET_RS P6OUT|=BIT3;
#define CLR_RW P6OUT&=~BIT4;//RW = P3.1
#define SET_RW P6OUT|=BIT4;
#define CLR_EN P6OUT&=~BIT5;//EN = P3.2
#define SET_EN P6OUT|=BIT5;
/*******************************************
函数名称:DispNchar
功 能:让液晶从某个位置起连续显示N个字符
参 数:x--位置的列坐标
y--位置的行坐标
n--字符个数
ptr--指向字符存放位置的指针
返回值 :无
********************************************/
void DispNChar(uchar x,uchar y, uchar n,uchar *ptr)
{
uchar i;
for (i=0;i<n;i++)
{
Disp1Char(x++,y,ptr[i]);
if (x == 0x0f)
{
x = 0;
y ^= 1;
}
}
}
/*******************************************
函数名称:LocateXY
功 能:向液晶输入显示字符位置的坐标信息
参 数:x--位置的列坐标
y--位置的行坐标
返回值 :无
********************************************/
void LocateXY(uchar x,uchar y)
{
uchar temp;
temp = x&0x0f;
y &= 0x01;
if(y) temp |= 0x40; //如果在第2行
temp |= 0x80;
LcdWriteCommand(temp,1);
}
/*******************************************
函数名称:Disp1Char
功 能:在某个位置显示一个字符
参 数:x--位置的列坐标
y--位置的行坐标
data--显示的字符数据
返回值 :无
********************************************/
void Disp1Char(uchar x,uchar y,uchar data)
{
LocateXY( x, y );
LcdWriteData( data );
}
/*******************************************
函数名称:LcdReset
功 能:对1602液晶模块进行复位操作
参 数:无
返回值 :无
********************************************/
void LcdReset(void)
{
CtrlDir |= 0x38; //控制线端口设为输出状态
DataDir = 0xFF; //数据端口设为输出状态
LcdWriteCommand(0x38, 0); //规定的复位操作
Delay5ms();
LcdWriteCommand(0x38, 0);
Delay5ms();
LcdWriteCommand(0x38, 0);
Delay5ms();
LcdWriteCommand(0x38, 1);//显示模式设置
LcdWriteCommand(0x08, 1);//显示关闭
LcdWriteCommand(0x01, 1); //显示清屏
LcdWriteCommand(0x06, 1);//写字符时整体不移动
LcdWriteCommand(0x0c, 1);//显示开,不开游标,不闪烁
}
/*******************************************
函数名称:LcdWriteCommand
功 能:向液晶模块写入命令
参 数:cmd--命令,
chk--是否判忙的标志,1:判忙,0:不判
返回值 :无
********************************************/
void LcdWriteCommand(uchar cmd,uchar chk)
{
if (chk) WaitForEnable(); // 检测忙信号?
CLR_RS;
CLR_RW;
_NOP();
DataPort = cmd; //将命令字写入数据端口
_NOP();
SET_EN; //产生使能脉冲信号
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
函数名称:LcdWriteData
功 能:向液晶显示的当前地址写入显示数据
参 数:data--显示字符数据
返回值 :无
********************************************/
void LcdWriteData( uchar data )
{
WaitForEnable(); //等待液晶不忙
SET_RS;
CLR_RW;
_NOP();
DataPort = data; //将显示数据写入数据端口
_NOP();
SET_EN; //产生使能脉冲信号
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
函数名称:WaitForEnable
功 能:等待1602液晶完成内部操作
参 数:无
返回值 :无
********************************************/
void WaitForEnable(void)
{
P2DIR &= 0x00; //将P4口切换为输入状态
CLR_RS;
SET_RW;
_NOP();
SET_EN;
_NOP();
_NOP();
while((P2IN & Busy)!=0); //检测忙标志
CLR_EN;
P2DIR |= 0xFF; //将P4口切换为输出状态
}
/*******************************************
函数名称:Delay5ms
功 能:延时约5ms
参 数:无
返回值 :无
********************************************/
void Delay5ms(void)
{
uint i=40000;
while (i != 0)
{
i--;
}
}
/*******************************************
函数名称:Delay400ms
功 能:延时约400ms
参 数:无
返回值 :无
********************************************/
void Delay400ms(void)
{
uchar i=50;
uint j;
while(i--)
{
j=7269;
while(j--);
}
}
void DispNChar(unsigned char x,unsigned char y, unsigned char n,unsigned char *ptr);
void LocateXY(unsigned char x,unsigned char y);
void Disp1Char(unsigned char x,unsigned char y,unsigned char data);
void LcdReset(void);
void LcdWriteCommand(unsigned char cmd,unsigned char chk);
void LcdWriteData( unsigned char data );
void WaitForEnable(void);
void Delay5ms(void);
void Delay400ms(void);
第二段程序
#include <msp430x14x.h>
typedef unsigned char uchar;
typedef unsigned int uint;
//unsigned char uchar;
//unsigned int uint;
/全局变量/
uchar key_Pressed; //按键是否被按下:1--是,0--否
uchar key_val; //存放键值
uchar key_Flag; //按键是否已放开:1--是,0--否
//设置键盘逻辑键值与程序计算键值的映射
uchar key_Map[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
/*******************************************
函数名称:Init_Keypad
功 能:初始化扫描键盘的IO端口
参 数:无
返回值 :无
********************************************/
void Init_Keypad(void)
{
P1DIR = 0xf0; //P1.0P1.3设置为输入状态, P1.4P1.7设置为输出状态
P1OUT |= 0xf0; // P1.4~P1.7输出高电平
key_Flag = 0;
key_Pressed = 0;
key_val = 0;
}
/*********************************************
- Check_Key(),检查按键,确认键值
*********************************************/
/*******************************************
函数名称:Check_Key
功 能:扫描键盘的IO端口,获得键值
参 数:无
返回值 :无
********************************************/
void Check_Key(void)
{
uchar row ,col,tmp1,tmp2;
tmp1 = 0x80;
for(row = 0;row < 4;row++) //行扫描
{
P1OUT = 0xf0; //P1.4~P1.7输出全1
P1OUT -= tmp1; //P1.4~p1.7输出四位中有一个为0
tmp1 >>=1;
if ((P1IN & 0x0f) < 0x0f) //是否P1IN的P1.0~P1.3中有一位为0
{
tmp2 = 0x01; // tmp2用于检测出那一位为0
for(col = 0;col < 4;col++) // 列检测
{
if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是
{
key_val = key_Map[row * 4 + col]; // 获取键值
return; // 退出循环
}
tmp2 <<= 1; // tmp2右移1位
}
}
}
}
/*******************************************
函数名称:delay
功 能:延时约15ms,完成消抖功能
参 数:无
返回值 :无
********************************************/
void delay()
{
uint tmp;
for(tmp = 12000;tmp > 0;tmp--);
}
/*******************************************
函数名称:Key_Event
功 能:检测按键,并获取键值
参 数:无
返回值 :无
********************************************/
void Key_Event(void)
{
uchar tmp;
P1OUT &= 0x00; // 设置P1OUT全为0,等待按键输入
tmp = P1IN; // 获取 p1IN
if ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有键按下
{
key_Pressed = 1; // 如果有按键按下,设置key_Pressed标识
delay(); //消除抖动
Check_Key(); // 调用check_Key(),获取键值
}
else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按键已经释放
{
key_Pressed = 0; // 清除key_Pressed标识
key_Flag = 1; // 设置key_Flag标识
}
else
{
_NOP();
}
}
//#include <msp430x44x.h>
#include "cry1602.h"
/全局变量**/
uchar second,minute,hour,hour0; //秒、分、时变量
uchar pmin,phour,ps1; //辅助计算变量
/*******************************************
函数名称:Clock
功 能:计算当前时间
参 数:无
返回值 :无
说明 :本函数对本文件开头定义的second,minute,
hour,hour0四个全局变量进行操作
********************************************/
void Clock(void)
{
second -= 1;
// second<=60& second>=0;
// minute<=60&minute>=0;
// hour<=100&hour>=0;
if(second == 0)
{
second = 60;
minute -= 1;
if(minute == 0)
{
minute = 60;
hour -= 1; hour0 -= 1;
if(hour == 0) hour = 24;
}
}
}
//void Clock(void)
//{
// second -= 1;
// second<=60& second>=0;
// minute<=60&minute>=0;
// hour<=100&hour>=0;
//if(second == 60)
// {
// second = 0;
// minute -= 1;
//if(minute == 60)
//{
// minute = 0;
// hour -= 1; hour0 -= 1;
// if(hour == 24) hour = 0;
//}
// }
//}
/*******************************************
函数名称:Display
功 能:在1602液晶上显示时间
参 数:无
返回值 :无
说明 :本函数对本文件开头定义的全局变量进行
操作
********************************************/
void Display(void)
{
uchar s0,s1;
uchar m0,m1;
uchar h0,h1;
s1 = second / 10; //十位
s0 = second - (s1 * 10); //个位
s1 += 48; //加上48等于其对应的ASCII码
s0 += 48;
Disp1Char(11,1,s0);
if(ps1 != s1)
{
ps1 = s1;
Disp1Char(10,1,s1);
}
if(pmin != minute)
{
pmin = minute;
m1 = minute / 10;
m0 = minute - (m1 * 10);
m1 += 48;
m0 += 48;
Disp1Char(7,1,m1);
Disp1Char(8,1,m0);
}
if(phour != hour)
{
phour = hour;
h1 = hour / 10;
h0 = hour - (h1 * 10);
h1 += 48;
h0 += 48;
Disp1Char(4,1,h1);
Disp1Char(5,1,h0);
}
}
void Clock(void);
void Display(void);
#include <msp430x14x.h>
#include "cry1602.h"
typedef unsigned char uchar;
typedef unsigned int uint;
/宏定义*/
#define DataDir P2DIR
#define DataPort P2OUT
#define Busy 0x80
#define CtrlDir P6DIR
#define CLR_RS P6OUT&=~BIT3; //RS = P3.0
#define SET_RS P6OUT|=BIT3;
#define CLR_RW P6OUT&=~BIT4;//RW = P3.1
#define SET_RW P6OUT|=BIT4;
#define CLR_EN P6OUT&=~BIT5;//EN = P3.2
#define SET_EN P6OUT|=BIT5;
/*******************************************
函数名称:DispNchar
功 能:让液晶从某个位置起连续显示N个字符
参 数:x--位置的列坐标
y--位置的行坐标
n--字符个数
ptr--指向字符存放位置的指针
返回值 :无
********************************************/
void DispNChar(uchar x,uchar y, uchar n,uchar *ptr)
{
uchar i;
for (i=0;i<n;i++)
{
Disp1Char(x++,y,ptr[i]);
if (x == 0x0f)
{
x = 0;
y ^= 1;
}
}
}
/*******************************************
函数名称:LocateXY
功 能:向液晶输入显示字符位置的坐标信息
参 数:x--位置的列坐标
y--位置的行坐标
返回值 :无
********************************************/
void LocateXY(uchar x,uchar y)
{
uchar temp;
temp = x&0x0f;
y &= 0x01;
if(y) temp |= 0x40; //如果在第2行
temp |= 0x80;
LcdWriteCommand(temp,1);
}
/*******************************************
函数名称:Disp1Char
功 能:在某个位置显示一个字符
参 数:x--位置的列坐标
y--位置的行坐标
data--显示的字符数据
返回值 :无
********************************************/
void Disp1Char(uchar x,uchar y,uchar data)
{
LocateXY( x, y );
LcdWriteData( data );
}
/*******************************************
函数名称:LcdReset
功 能:对1602液晶模块进行复位操作
参 数:无
返回值 :无
********************************************/
void LcdReset(void)
{
CtrlDir |= 0x38; //控制线端口设为输出状态
DataDir = 0xFF; //数据端口设为输出状态
LcdWriteCommand(0x38, 0); //规定的复位操作
Delay5ms();
LcdWriteCommand(0x38, 0);
Delay5ms();
LcdWriteCommand(0x38, 0);
Delay5ms();
LcdWriteCommand(0x38, 1);//显示模式设置
LcdWriteCommand(0x08, 1);//显示关闭
LcdWriteCommand(0x01, 1); //显示清屏
LcdWriteCommand(0x06, 1);//写字符时整体不移动
LcdWriteCommand(0x0c, 1);//显示开,不开游标,不闪烁
}
/*******************************************
函数名称:LcdWriteCommand
功 能:向液晶模块写入命令
参 数:cmd--命令,
chk--是否判忙的标志,1:判忙,0:不判
返回值 :无
********************************************/
void LcdWriteCommand(uchar cmd,uchar chk)
{
if (chk) WaitForEnable(); // 检测忙信号?
CLR_RS;
CLR_RW;
_NOP();
DataPort = cmd; //将命令字写入数据端口
_NOP();
SET_EN; //产生使能脉冲信号
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
函数名称:LcdWriteData
功 能:向液晶显示的当前地址写入显示数据
参 数:data--显示字符数据
返回值 :无
********************************************/
void LcdWriteData( uchar data )
{
WaitForEnable(); //等待液晶不忙
SET_RS;
CLR_RW;
_NOP();
DataPort = data; //将显示数据写入数据端口
_NOP();
SET_EN; //产生使能脉冲信号
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
函数名称:WaitForEnable
功 能:等待1602液晶完成内部操作
参 数:无
返回值 :无
********************************************/
void WaitForEnable(void)
{
P2DIR &= 0x00; //将P4口切换为输入状态
CLR_RS;
SET_RW;
_NOP();
SET_EN;
_NOP();
_NOP();
while((P2IN & Busy)!=0); //检测忙标志
CLR_EN;
P2DIR |= 0xFF; //将P4口切换为输出状态
}
/*******************************************
函数名称:Delay5ms
功 能:延时约5ms
参 数:无
返回值 :无
********************************************/
void Delay5ms(void)
{
uint i=40000;
while (i != 0)
{
i--;
}
}
/*******************************************
函数名称:Delay400ms
功 能:延时约400ms
参 数:无
返回值 :无
********************************************/
void Delay400ms(void)
{
uchar i=50;
uint j;
while(i--)
{
j=7269;
while(j--);
}
}
void DispNChar(unsigned char x,unsigned char y, unsigned char n,unsigned char *ptr);
void LocateXY(unsigned char x,unsigned char y);
void Disp1Char(unsigned char x,unsigned char y,unsigned char data);
void LcdReset(void);
void LcdWriteCommand(unsigned char cmd,unsigned char chk);
void LcdWriteData( unsigned char data );
void WaitForEnable(void);
void Delay5ms(void);
void Delay400ms(void);
#include <msp430x14x.h>
typedef unsigned char uchar;
typedef unsigned int uint;
//unsigned char uchar;
//unsigned int uint;
/全局变量/
uchar key_Pressed; //按键是否被按下:1--是,0--否
uchar key_val; //存放键值
uchar key_Flag; //按键是否已放开:1--是,0--否
//设置键盘逻辑键值与程序计算键值的映射
uchar key_Map[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
/*******************************************
函数名称:Init_Keypad
功 能:初始化扫描键盘的IO端口
参 数:无
返回值 :无
********************************************/
void Init_Keypad(void)
{
P1DIR = 0xf0; //P1.0P1.3设置为输入状态, P1.4P1.7设置为输出状态
P1OUT |= 0xf0; // P1.4~P1.7输出高电平
key_Flag = 0;
key_Pressed = 0;
key_val = 0;
}
/*********************************************
- Check_Key(),检查按键,确认键值
*********************************************/
/*******************************************
函数名称:Check_Key
功 能:扫描键盘的IO端口,获得键值
参 数:无
返回值 :无
********************************************/
void Check_Key(void)
{
uchar row ,col,tmp1,tmp2;
tmp1 = 0x80;
for(row = 0;row < 4;row++) //行扫描
{
P1OUT = 0xf0; //P1.4~P1.7输出全1
P1OUT -= tmp1; //P1.4~p1.7输出四位中有一个为0
tmp1 >>=1;
if ((P1IN & 0x0f) < 0x0f) //是否P1IN的P1.0~P1.3中有一位为0
{
tmp2 = 0x01; // tmp2用于检测出那一位为0
for(col = 0;col < 4;col++) // 列检测
{
if((P1IN & tmp2) == 0x00) // 是否是该列,等于0为是
{
key_val = key_Map[row * 4 + col]; // 获取键值
return; // 退出循环
}
tmp2 <<= 1; // tmp2右移1位
}
}
}
}
/*******************************************
函数名称:delay
功 能:延时约15ms,完成消抖功能
参 数:无
返回值 :无
********************************************/
void delay()
{
uint tmp;
for(tmp = 12000;tmp > 0;tmp--);
}
/*******************************************
函数名称:Key_Event
功 能:检测按键,并获取键值
参 数:无
返回值 :无
********************************************/
void Key_Event(void)
{
uchar tmp;
P1OUT &= 0x00; // 设置P1OUT全为0,等待按键输入
tmp = P1IN; // 获取 p1IN
if ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有键按下
{
key_Pressed = 1; // 如果有按键按下,设置key_Pressed标识
delay(); //消除抖动
Check_Key(); // 调用check_Key(),获取键值
}
else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按键已经释放
{
key_Pressed = 0; // 清除key_Pressed标识
key_Flag = 1; // 设置key_Flag标识
}
else
{
_NOP();
}
}