帮我看一下这个基于状态机的按键扫描程序怎么不起作用呢?(问题解决)
extern volatile int8_t keytime;//定时10ms 自加,在定时器中处理#define Key1 (PIND&_BV(0))//按键1
#define Key2 (PINE&_BV(6))//按键2
#define Key3 (PINE&_BV(7))//按键3
#define KEY_A 0x01
#define KEY_B 0x02
#define KEY_C 0x04
#define NULL 0
#define STATE_A 0
#define STATE_B 1
#define STATE_C 2
void keyportinit(void)
{
PORTD|=_BV(PD0); //置上接电阻
PORTE|=_BV(PD6)|_BV(PD7);//置上拉电阻
DDRD&=~_BV(PD0); //输入
DDRE&=~_BV(PD6)|~_BV(PD7);//输入
asm volatile ("nop");
asm volatile ("nop");
}
uint8 getkeyvalue(void)//取得键值
{
static uint8 keyvalue;
if(Key1==0)
keyvalue=KEY_A;
if(Key2==0)
keyvalue=KEY_B;
if(Key3==0)
keyvalue=KEY_C;
else
keyvalue=NULL;
return keyvalue;
}
uint8 keyscan(void)
{
static uint8_t event = 0;
volatile uint8_t key_press;
if(getkeyvalue()!=0)
{
key_press=getkeyvalue();
keytime=0;
}
else
{
key_press=0;
}
if(key_press!=0)
{
if((keytime > 1) && (keytime < 8)) //判断按键时间
{
switch(key_press)
{
case KEY_A:
event=STATE_A;
break;
case KEY_B:
event=STATE_B;
break;
case KEY_C:
event=STATE_C;
break;
default:
event=NULL;
break;
}
}
}
return event;
}
以上代码片断
以下是正确代码
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#define MCU_XTAL 7372800
#define TIMER1_START0x0C // Start value Timer1, Prescaler 256, CTC mode, OCR1A = Top
#define TIMER1_STOP 0x00 // Stop Timer1 value
// OCR1A Top value, 100ms interrupt
#define TICK_100MS (uint16_t)(10000/(1000000UL/(MCU_XTAL/256)))
// auto power off time, default 60s
#define AUTO_OFF_TIME 600
volatile int8_t keytime;//定时10ms 自加,在定时器中处理
#define Key1 (PIND&_BV(0))//按键1
#define Key2 (PINE&_BV(6))//按键2
#define Key3 (PINE&_BV(7))//按键3
#define KEY_A 0x01
#define KEY_B 0x02
#define KEY_C 0x04
#define NULL 0
#define STATE_A 0
#define STATE_B 1
#define STATE_C 2
void keyportinit(void)
{
PORTD|=_BV(PD0); //置上接电阻
PORTE|=_BV(PD6)|_BV(PD7);//置上拉电阻
DDRD&=~_BV(PD0); //输入
DDRE&=~_BV(PD6)|~_BV(PD7);//输入
asm volatile ("nop");
asm volatile ("nop");
}
uint8_t getkeyvalue(void)//取得键值
{
uint8_t keyvalue=0;
if(Key1==0)
keyvalue=KEY_A;
if(Key2==0)
keyvalue=KEY_B;
if(Key3==0)
keyvalue=KEY_C;
return keyvalue;
}
uint8_t keyscan(void)
{
volatile uint8_t event = 0;
volatile uint8_t key_press;
if(getkeyvalue()!=0)
{
key_press=getkeyvalue();
}
else
{
key_press=0;
keytime=0;
}
if(key_press!=0)
{
if((keytime > 1)&&(keytime<8)) //判断按键时间
{
switch(key_press)
{
case KEY_A:
event=STATE_A;
break;
case KEY_B:
event=STATE_B;
break;
case KEY_C:
event=STATE_C;
break;
default:
event=NULL;
break;
}
}
}
return event;
}
void Timer1_Init(void)
{
OCR1A = TICK_100MS; // define TIMER1 overflow value in CTC mode
TIMSK = _BV (OCIE1A); // enable Timer1 output compare A interrupt
TCCR1B = _BV (WGM12) | _BV (CS12);// start Timer1
}
ISR(TIMER1_COMPA_vect)
{
keytime++;
}
int main(void)
{
Timer1_Init();
keyportinit();
sei();
while(1)
{
volatile uint8_t a;
a=keyscan();
switch(a)
{
...
}
return 0;
} 没有人回应呢? markk 而马老师的按键状态机如下:
if (10ms计时标志)
{
清除10ms计时标志
switch (状态机)
{
case 状态0:
读键端口
if (有按键按下)
转状态1
break;
case 状态1:
读键端口
if (前后两次相同)
{
置按键标志
转状态2,等等按键释放
}
else
转状态0
break;
case 状态2:
读键端口
if (按键已经释放)
转状态0
break;
}
} 我这个可以判断一个按键时间长短,实现单键多功能。
页:
[1]