功能实现
MSP-EXP430G2 开发板上 P1.3 接了一个按键,P1.0 和 P1.6 接了 LED(用跳线帽连接),要求短按 P1.3 控制 LED1 的亮灭,长按P1.3 控制 LED2 的亮灭。
状态机
代码
#include "MSP430G2553.h"
//-----对状态机进行宏定义-----
#define IDLE 0
#define SHORT 1
#define LONG 2
#define COUNTER_THRESHOLD 50 /*长键判别门限*/
//-----全局变量-----
unsigned char WDT_Counter=0; /*用于对按键按下时间进行计数*/
//-----在main函数前提前声明函数-----
void GPIO_init();
void WDT_init();
void Key_SM();
unsigned char LongClick_Dect();
void P13_OnShortRelease();
void P13_OnLongClick();
void main(void) {
WDTCTL = WDTPW + WDTHOLD; //关狗
GPIO_init();
WDT_init();
_EINT(); //开总中断
LPM3; //LPM3休眠
}
/******************************************************************************************************
* 名 称:GPIO_init()
* 功 能:设定按键和LED控制IO的方向,启用按键IO的上拉电阻
* 入口参数:无
* 出口参数:无
* 说 明:无
* 范 例:无
******************************************************************************************************/
void GPIO_init()
{
//-----设定P1.0和P1.6的输出初始值-----
P1DIR |= BIT0+BIT6; //设定P1.0和P1.6为输出
P1OUT |= BIT0; //设定P1.0初值
P1OUT &= ~BIT6; //设定P1.6初值
//-----配合机械按键,启用内部上拉电阻-----
P1REN |= BIT3; //启用P1.3内部上下拉电阻
P1OUT |= BIT3; //将电阻设置为上拉
}
/******************************************************************************************************
* 名 称:WDT_init()
* 功 能:设定WDT定时中断为16ms,开启WDT定时中断使能
* 入口参数:无
* 出口参数:无
* 说 明:WDT定时中断的时钟源选择ACLK,可以用LPM3休眠。
* 范 例:无
******************************************************************************************************/
void WDT_init()
{
//-----设定WDT为-----
WDTCTL=WDT_ADLY_16;
//-----WDT中断使能-----
IE1|=WDTIE;
}
/******************************************************************************************************
* 名 称:WDT_ISR()
* 功 能:响应WDT定时中断服务
* 入口参数:无
* 出口参数:无
* 说 明:不能直接判断事件,需启用状态机
* 范 例:无
******************************************************************************************************/
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
//-----启用按键状态机-----
Key_SM();
}
/******************************************************************************************************
* 名 称:Key_SM()
* 功 能:判断出长短键
* 入口参数:无
* 出口参数:无
* 说 明:本状态机为Mealy型状态机,在Switch(State)中需要判断事件
* 范 例:无
******************************************************************************************************/
void Key_SM()
{
static unsigned char State=0; //状态机的状态变量
static unsigned char Key_Now=0; //记录按键的当前电平
unsigned char Key_Past=0; //记录按键的前一次电平
unsigned char Key_Dect=0; //按键状态值
Key_Past=Key_Now;
//-----查询IO的输入寄存器-----
if(P1IN&BIT3) Key_Now=1;
else Key_Now=0;
//-----电平前高后低,表明按下-----
if((Key_Past==1)&&(Key_Now==0))
Key_Dect=1;
//-----电平前低后高,表明弹起-----
if((Key_Past==0)&&(Key_Now==1))
Key_Dect=2 ;
switch(State) //该状态机靠扫描的按键值Key_Dect跳转状态
{
case IDLE:
WDT_Counter=0; //空闲状态对计数清零
if(Key_Dect==1) State=SHORT; //路径1
break;
case SHORT:
if(Key_Dect==2) //路径2
{
State=IDLE;
P13_OnShortRelease(); //短按事件处理函数
break;
}
if(LongClick_Dect()) //路径3
{
State=LONG;
P13_OnLongClick(); //长按事件处理函数
}
break;
case LONG:
WDT_Counter=0; //长按状态对计数清零
if(Key_Dect==2) State=IDLE; //路径4
break;
default: State=IDLE; break;
}
}
/******************************************************************************************************
* 名 称:LongClick_Dect()
* 功 能:对WDT中断计时,计满清零并返回”长键“信息
* 入口参数:无
* 出口参数:1:长按键;0:非长按键
* 说 明:无
* 范 例:无
******************************************************************************************************/
unsigned char LongClick_Dect()
{
WDT_Counter++;
if (WDT_Counter==COUNTER_THRESHOLD)
{
WDT_Counter=0;
return(1);
}
else return(0);
}
/******************************************************************************************************
* 名 称:P13_OnShortRelease()
* 功 能:P1.3的短按事件处理函数,即当P1.3键被”短按“后,下一步干什么
* 入口参数:无
* 出口参数:无
* 说 明:使用事件处理函数的形式,可以增强代码的移植性和可读性
* 范 例:无
******************************************************************************************************/
void P13_OnShortRelease() //P1.3的事件处理函数
{
//----翻转P1.3IO电平-----
P1OUT ^= BIT0;
}
/******************************************************************************************************
* 名 称:P13_OnLongClick()
* 功 能:P1.3的长按事件处理函数,即当P1.3键被”长按“后,下一步干什么
* 入口参数:无
* 出口参数:无
* 说 明:使用事件处理函数的形式,可以增强代码的移植性和可读性
* 范 例:无
******************************************************************************************************/
void P13_OnLongClick() //P1.3的事件处理函数
{
//----翻转P1.6IO电平-----
P1OUT ^= BIT6;
}