文章目录
- 需求
- 思路介绍
- 程序源码
需求
MSP430f5529单片机的开发板上面只有2个按键硬件,但是通过识别双击,就可以拥有4个按键了!
识别按键,单击P2.1返回1,单击P1.1返回2,双击P2.1返回3,双击P1.1返回4,无按键返回0。
PS:看了一些别人写的,好像用不了,就自己造轮子。当然,程序可以扩展到所有类型的单片机上去,自己写的理解起来还是轻松的。
思路介绍
这段程序是一个用于识别按键输入的函数。在MSP430单片机上,P2.1和P1.1分别连接了两个按键。
程序的主要功能是判断按键的状态,根据不同的点击方式返回相应的结果。
程序中使用了几个变量来跟踪按键的状态:
key1_state和key2_state表示P2.1和P1.1按键的状态,初始状态为0,表示没有按下。
key1_count和key2_count用于计数按键持续按下的时间,单位是10毫秒。
程序首先检测P2.1按键(KEY1),如果按键被按下,根据当前状态进行判断:
如果按键之前处于未按下状态(key1_state为0),则将状态设置为1,表示第一次按下。
如果按键之前处于按下后释放状态(key1_state为2)且按键持续按下的时间小于设定的时间敏感度(Time_sensitivity),则将状态设置为3,表示第二次按下。
如果按键未被按下,再根据当前状态进行判断:
如果按键之前处于第一次按下状态(key1_state为1),则将状态设置为2,表示按键已释放。
如果按键之前处于第二次按下状态(key1_state为3),则将状态设置为4,并重置计数器key1_count,用于记录按键持续按下的时间。
再次判断按键持续按下的时间是否小于设定的时间敏感度(Time_sensitivity),如果是,则将key_value设置为3,表示双击了P2.1按键。 同时将状态设置为0,并重置计数器key1_count。
最后对key1_state进行处理:
如果key1_state不为0,则递增计数器key1_count。
如果key1_state为2且key1_count大于设定的时间敏感度(Time_sensitivity),则将key_value设置为1,表示单击了P2.1按键。 同时将状态设置为0,并重置计数器key1_count。
类似地,程序还处理了P1.1按键(KEY2),返回相应的结果。
最后,函数返回key_value,表示按键的结果。如果没有按键被触发,返回值为0,表示无按键操作。
驱动代码,这里是2个按键的,扩展到更多的话自有发挥~
程序源码
驱动如下
#include "msp430.h"
void init_key(void)
{
//p2.1
P2DIR &= ~BIT1;
P2REN |= BIT1;
P2OUT |= BIT1;
//p1.1
P1DIR &= ~BIT1;
P1REN |= BIT1;
P1OUT |= BIT1;
}
#define KEY1 (P2IN&BIT1)
#define KEY2 (P1IN&BIT1)
//识别按键,单击P2.1返回1,单击P1.1返回2,双击P2.1返回3,双击P1.1返回4,无按键返回0
//300ms内只有一次点击是单击,否则就是一次双击
//这个函数10ms执行一次
unsigned char get_key(void) {
//状态0 没有按下
//状态1 第一次按下
//状态2 第一次按下后释放
//状态3 第二次按下
//状态4 第二次按下后释放
static unsigned char key1_state = 0, key2_state = 0;
static unsigned char key1_count = 0, key2_count = 0;
const static unsigned char Time_sensitivity = 30;//300ms
unsigned char key_value = 0;
//key1
if (!KEY1) {
if (key1_state == 0) {
key1_state = 1;
} else if ((key1_state == 2) && (key1_count < Time_sensitivity)) {
key1_state = 3;
}
} else {
if (key1_state == 1) {
key1_state = 2;
} else if (key1_state == 3) {
key1_state = 4;
key1_count = 0;
if (key1_count < Time_sensitivity) {
key_value = 3;
key1_state = 0;
key1_count = 0;
}
}
}
if (key1_state) {
key1_count++;
}
if ((key1_state == 2) && (key1_count > Time_sensitivity)) {
key_value = 1;
key1_state = 0;
key1_count = 0;
}
//key2
if (!KEY2) {
if (key2_state == 0) {
key2_state = 1;
} else if ((key2_state == 2) && (key2_count < Time_sensitivity)) {
key2_state = 3;
}
} else {
if (key2_state == 1) {
key2_state = 2;
} else if (key2_state == 3) {
key2_state = 4;
key2_count = 0;
if (key2_count < Time_sensitivity) {
key_value = 4;
key2_state = 0;
key2_count = 0;
}
}
}
if (key2_state) {
key2_count++;
}
if ((key2_state == 2) && (key2_count > Time_sensitivity)) {
key_value = 2;
key2_state = 0;
key2_count = 0;
}
return key_value;
}
调用方式:
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; /* Stop watchdog timer */
init_key();
while (1)
{
delay_ms(10);
key = get_key();
if (key)
{
//显示按键
count = 0;
disp[count++] = key % 100 / 10 + '0';
disp[count++] = key % 10 / 1 + '0';
disp[count++] = 0;
OLED_ShowString(0, 0, disp, 0);
//处理按键
do_key(key);
}
}
}