#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
//管脚中断入口
void PinInterrupt_ISR (void) interrupt 7
{
if(PIF == 0x10)
{
//其他处理
PIF =0;
}
}
void main(void)
{
Enable_INT_Port0; //用P0端口作为管脚中断,只能由 P00-P07 产生中断
Enable_BIT4_LowLevel_Trig; //P04 低电平中断
P04_Quasi_Mode; //P04 配置为准双向口
P04 = 1; //上拉
set_EPI; //使能管脚中断
set_EA; //使能中断总开关
while(1)
{
}
}
离线
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
#define IO_BEEP P30 //蜂鸣器引脚定义
#define IO_LED P12 //LED引脚定义
#define beep(MS_HOLD) \
{\
IO_BEEP = 0; \
IO_LED = 0; \
Timer0_Delay1ms(MS_HOLD); \
IO_BEEP = 1; \
IO_LED = 1; \
}\
//管脚中断入口
void PinInterrupt_ISR (void) interrupt 7
{
beep(100);
//其他处理
PIF =0;
}
void main(void)
{
Enable_INT_Port0; //用P0端口作为管脚中断,只能由 P00-P07 产生中断
Enable_BIT0_LowLevel_Trig; //P00 低电平中断
Enable_BIT1_LowLevel_Trig; //P01 低电平中断
Enable_BIT2_LowLevel_Trig; //P02 低电平中断
Enable_BIT3_LowLevel_Trig; //P03 低电平中断
Enable_BIT4_LowLevel_Trig; //P04 低电平中断
Enable_BIT5_LowLevel_Trig; //P05 低电平中断
Enable_BIT6_LowLevel_Trig; //P06 低电平中断
Enable_BIT7_LowLevel_Trig; //P07 低电平中断
P30_Quasi_Mode; //P30 配置为准双向口
P12_Quasi_Mode; //P12 配置为准双向口
P00_Quasi_Mode; //P00 配置为准双向口
P01_Quasi_Mode; //P01 配置为准双向口
P02_Quasi_Mode; //P02 配置为准双向口
P03_Quasi_Mode; //P03 配置为准双向口
P04_Quasi_Mode; //P04 配置为准双向口
P05_Quasi_Mode; //P05 配置为准双向口
P06_Quasi_Mode; //P06 配置为准双向口
P07_Quasi_Mode; //P07 配置为准双向口
P00 = 1; //上拉
P01 = 1; //上拉
P02 = 1; //上拉
P03 = 1; //上拉
P04 = 1; //上拉
P05 = 1; //上拉
P06 = 1; //上拉
P07 = 1; //上拉
set_EPI; //使能管脚中断
set_EA; //使能中断总开关
while(1)
{
}
}
P00 - P07 口低电平中断 demo
离线
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
#define IO_BEEP P30 //蜂鸣器引脚定义
#define IO_LED P12 //LED引脚定义
#define beep(MS_HOLD) \
{\
IO_BEEP = 0; \
IO_LED = 0; \
Timer0_Delay1ms(MS_HOLD); \
IO_BEEP = 1; \
IO_LED = 1; \
}\
//管脚中断入口
void PinInterrupt_ISR (void) interrupt 7
{
beep(100);
//其他处理
PIF =0;
}
void main(void)
{
Enable_INT_Port0; //用P0端口作为管脚中断,只能由 P00-P07 产生中断
// Enable_BIT7_FallEdge_Trig; //P00 下降沿中断
// Enable_BIT6_FallEdge_Trig; //P01 下降沿中断
// Enable_BIT5_FallEdge_Trig; //P02 下降沿中断
// Enable_BIT4_FallEdge_Trig; //P03 下降沿中断
// Enable_BIT3_FallEdge_Trig; //P04 下降沿中断
// Enable_BIT2_FallEdge_Trig; //P05 下降沿中断
// Enable_BIT1_FallEdge_Trig; //P06 下降沿中断
// Enable_BIT0_FallEdge_Trig; //P07 下降沿中断
Enable_BIT7_RasingEdge_Trig;//P00 上升沿中断
Enable_BIT6_RasingEdge_Trig;//P01 上升沿中断
Enable_BIT5_RasingEdge_Trig;//P02 上升沿中断
Enable_BIT4_RasingEdge_Trig;//P03 上升沿中断
Enable_BIT3_RasingEdge_Trig;//P04 上升沿中断
Enable_BIT2_RasingEdge_Trig;//P05 上升沿中断
Enable_BIT1_RasingEdge_Trig;//P06 上升沿中断
Enable_BIT0_RasingEdge_Trig;//P07 上升沿中断
// Enable_BIT0_LowLevel_Trig; //P00 低电平中断
// Enable_BIT1_LowLevel_Trig; //P01 低电平中断
// Enable_BIT2_LowLevel_Trig; //P02 低电平中断
// Enable_BIT3_LowLevel_Trig; //P03 低电平中断
// Enable_BIT4_LowLevel_Trig; //P04 低电平中断
// Enable_BIT5_LowLevel_Trig; //P05 低电平中断
// Enable_BIT6_LowLevel_Trig; //P06 低电平中断
// Enable_BIT7_LowLevel_Trig; //P07 低电平中断
P30_Quasi_Mode; //P30 配置为准双向口
P12_Quasi_Mode; //P12 配置为准双向口
P00_Quasi_Mode; //P00 配置为准双向口
P01_Quasi_Mode; //P01 配置为准双向口
P02_Quasi_Mode; //P02 配置为准双向口
P03_Quasi_Mode; //P03 配置为准双向口
P04_Quasi_Mode; //P04 配置为准双向口
P05_Quasi_Mode; //P05 配置为准双向口
P06_Quasi_Mode; //P06 配置为准双向口
P07_Quasi_Mode; //P07 配置为准双向口
P00 = 1; //上拉
P01 = 1; //上拉
P02 = 1; //上拉
P03 = 1; //上拉
P04 = 1; //上拉
P05 = 1; //上拉
P06 = 1; //上拉
P07 = 1; //上拉
set_EPI; //使能管脚中断
set_EA; //使能中断总开关
while(1)
{
}
}
下降沿中断
离线
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
#define IO_BEEP P30 //蜂鸣器引脚定义
#define IO_LED P00 //LED引脚定义
#define beep(MS_HOLD) \
{\
IO_BEEP = 0; \
IO_LED = 0; \
Timer0_Delay1ms(MS_HOLD); \
IO_BEEP = 1; \
IO_LED = 1; \
}\
//管脚中断入口
void PinInterrupt_ISR (void) interrupt 7
{
Timer0_Delay1ms(10);
if(PIF == 0x10)
{
beep(100);
}
else if(PIF == 0x20)
{
beep(400);
}
else if(PIF == 0x40)
{
beep(800);
}
else if(PIF == 0x80)
{
beep(1200);
}
//其他处理
PIF =0;
}
void main(void)
{
Enable_INT_Port1; //用P0端口作为管脚中断,只能由 P00-P07 产生中断
// Enable_BIT7_FallEdge_Trig; //P10 下降沿中断
// Enable_BIT6_FallEdge_Trig; //P11 下降沿中断
// Enable_BIT5_FallEdge_Trig; //P12 下降沿中断
// Enable_BIT4_FallEdge_Trig; //P13 下降沿中断
// Enable_BIT3_FallEdge_Trig; //P14 下降沿中断
// Enable_BIT2_FallEdge_Trig; //P15 下降沿中断
// Enable_BIT1_FallEdge_Trig; //P16 下降沿中断
// Enable_BIT0_FallEdge_Trig; //P17 下降沿中断
// Enable_BIT7_RasingEdge_Trig;//P10 上升沿中断
// Enable_BIT6_RasingEdge_Trig;//P11 上升沿中断
// Enable_BIT5_RasingEdge_Trig;//P12 上升沿中断
// Enable_BIT4_RasingEdge_Trig;//P13 上升沿中断
// Enable_BIT3_RasingEdge_Trig;//P14 上升沿中断
// Enable_BIT2_RasingEdge_Trig;//P15 上升沿中断
// Enable_BIT1_RasingEdge_Trig;//P16 上升沿中断
// Enable_BIT0_RasingEdge_Trig;//P17 上升沿中断
// Enable_BIT0_LowLevel_Trig; //P10 低电平中断
// Enable_BIT1_LowLevel_Trig; //P11 低电平中断
// Enable_BIT2_LowLevel_Trig; //P12 低电平中断
// Enable_BIT3_LowLevel_Trig; //P13 低电平中断
Enable_BIT4_LowLevel_Trig; //P14 低电平中断
Enable_BIT5_LowLevel_Trig; //P15 低电平中断
Enable_BIT6_LowLevel_Trig; //P16 低电平中断
Enable_BIT7_LowLevel_Trig; //P17 低电平中断
P30_Quasi_Mode; //P30 配置为准双向口
P00_Quasi_Mode; //P20 配置为准双向口
P10_Quasi_Mode; //P10 配置为准双向口
P11_Quasi_Mode; //P11 配置为准双向口
P12_Quasi_Mode; //P12 配置为准双向口
P13_Quasi_Mode; //P13 配置为准双向口
P14_Quasi_Mode; //P14 配置为准双向口
P15_Quasi_Mode; //P15 配置为准双向口
P16_Quasi_Mode; //P16 配置为准双向口
P17_Quasi_Mode; //P17 配置为准双向口
P10 = 1; //上拉
P11 = 1; //上拉
P12 = 1; //上拉
P13 = 1; //上拉
P14 = 1; //上拉
P15 = 1; //上拉
P16 = 1; //上拉
P17 = 1; //上拉
set_EPI; //使能管脚中断
set_EA; //使能中断总开关
while(1)
{
P1 &= 0xFE;
P1 &= 0xFD;
P1 &= 0xFB;
P1 &= 0xF7;
}
}
P1口接矩阵键盘
P10
P11
P12
P13
轮流发送低电平。
P14
P15
P16
P17
检测管脚中断
离线
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
//INT0 外部中断,接 P30
void EXT_INT0(void) interrupt 0
{
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
Timer0_Delay1ms(100);
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
}
//管脚中断 P00, P07 接地可以触发
void PinInterrupt_ISR (void) interrupt 7
{
if(PIF == 0x01)
{
PIF = 0x00; //clear interrupt flag
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
Timer1_Delay10ms(10);
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
Timer1_Delay10ms(10);
}
else if (PIF == 0x80)
{
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
Timer1_Delay10ms(10);
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
}
}
void main(void)
{
P12_PushPull_Mode; //LED引脚配置
P07_Quasi_Mode;
set_P0S_7;
P00_Quasi_Mode;
set_P0S_1;
P30_Quasi_Mode;
Enable_INT_Port0;
Enable_BIT7_LowLevel_Trig;
Enable_BIT0_LowLevel_Trig;
P30 = 1; //上拉
P00 = 1; //上拉
P07 = 1; //上拉
set_EPI; // Enable pin interrupt
set_EX0;
set_EA; // global enable bit
while(1)
{
}
}
P30 INT0 外部中断0 OK
P00 & P07 外部管脚中断 OK
离线
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
//INT0 外部中断,接 P30
void EXT_INT0(void) interrupt 0
{
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
Timer0_Delay1ms(100);
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
}
//管脚中断 P00, P07 接地可以触发
void PinInterrupt_ISR (void) interrupt 7
{
if(PIF == 0x01)
{
if (P17 == 1) //编码器顺时钟转一个刻度
{
Timer0_Delay1ms(1);//消抖
if (P17 == 1)
{
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
Timer1_Delay10ms(2);
}
}
else if (P17 == 0) //编码器逆时钟转一个刻度
{
Timer0_Delay1ms(1);//消抖
if (P17 == 0)
{
clr_GPIO1;
Timer1_Delay10ms(20);
set_GPIO1;
}
}
}
else if (PIF == 0x80)
{
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
Timer1_Delay10ms(10);
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
}
PIF = 0x00; //clear interrupt flag
}
void main(void)
{
P12_PushPull_Mode; //LED引脚配置
P17_Quasi_Mode; //读旋转编码器电平
P07_Quasi_Mode;
set_P0S_7;
P00_Quasi_Mode;
set_P0S_1;
P30_Quasi_Mode;
Enable_INT_Port0;
Enable_BIT7_LowLevel_Trig;
//Enable_BIT0_LowLevel_Trig;
Enable_BIT0_FallEdge_Trig;
P30 = 1; //上拉
P00 = 1; //上拉
P07 = 1; //上拉
P17 = 1; //上拉
set_EPI; // Enable pin interrupt
set_EX0;
set_EA; // global enable bit
while(1)
{
}
}
旋转编码器 CLK 引脚接 P00 (下降沿中断)
旋转编码器 DAT 引脚接 P17
蜂鸣器和LED 指示灯接 P12
工作正常了。
离线
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
#define TIMER1_INIT (6663 * 2)
UINT8 u8TH1_Tmp,u8TL1_Tmp;
UINT8 time_10ms_ok;
unsigned char key;
#define IO_KEY_INPUT P10 // 按键输入口
#define IO_BEEP P12 //蜂鸣器 LED
#define N_key 0 //无键
#define S_key 1 //单键
#define D_key 2 //双键
#define L_key 3 //长键
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
unsigned char key_driver(void)
{
static unsigned char key_state = key_state_0, key_time = 0;
unsigned char key_press, key_return = N_key;
key_press = IO_KEY_INPUT; // 读按键I/O电平
switch (key_state)
{
case key_state_0: // 按键初始态
if (!key_press)
key_state = key_state_1; // 键被按下,状态转换到按键消抖和确认状态
break;
case key_state_1: // 按键消抖与确认态
if (!key_press)
{
key_time = 0; //
key_state = key_state_2; // 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件
}
else
key_state = key_state_0; // 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。
break;
case key_state_2:
if(key_press)
{
key_return = S_key; // 此时按键释放,说明是产生一次短操作,回送S_key
key_state = key_state_0; // 转换到按键初始态
}
else if (++key_time >= 100) // 继续按下,计时加10ms(10ms为本函数循环执行间隔)
{
key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长键事件
key_state = key_state_3; // 转换到等待按键释放状态
}
break;
case key_state_3: // 等待按键释放状态,此状态只返回无按键事件
if (key_press)
key_state = key_state_0; //按键已释放,转换到按键初始态
break;
}
return key_return;
}
/*=============
中间层按键处理函数,调用低层函数一次,处理双击事件的判断,返回上层正确的无键、单键、双键、长键4个按键事件。
本函数由上层循环调用,间隔10ms
===============*/
unsigned char key_read(void)
{
static unsigned char key_m = key_state_0, key_time_1 = 0;
unsigned char key_return = N_key,key_temp;
key_temp = key_driver();
switch(key_m)
{
case key_state_0:
if (key_temp == S_key )
{
key_time_1 = 0; // 第1次单击,不返回,到下个状态判断后面是否出现双击
key_m = key_state_1;
}
else
key_return = key_temp; // 对于无键、长键,返回原事件
break;
case key_state_1:
if (key_temp == S_key) // 又一次单击(间隔肯定<500ms)
{
key_return = D_key; // 返回双击键事件,回初始状态
key_m = key_state_0;
}
else
{ // 这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键
if(++key_time_1 >= 50)
{
key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键事件
key_m = key_state_0; // 返回初始状态
}
}
break;
}
return key_return;
}
/*
下面,根据程序分析按键事件的反映时间:
1。对于长键,按下超过1s马上响应,反映最快
2。对于双键,第2次按键释放后马上得到反映。
3。对于单键,释放后延时拖后500ms才能响应,反映最慢。这个与需要判断后面是否有双击操作有关,只能这样。实际应用中,可以调整两次单击间隔时间定义,比如为300ms,这样单击的响应回快一点,单按键操作人员需要加快按键的操作过程。如果产品是针对老年人的,这个时间不易太短,因为年纪大的人,反映和动作都比较慢。
当然,上面两段可以合在一起。我这样做的目的,是为了可以方便的扩展为N击(当然,需要做修改)。可是最底层的就是最基本的操作处理短按和长按,不用改动的。至于双击,还是N击,在中间层处理。这就是程序设计中分层结构的优点。
测试代码环境如下:
*/
void Timer1_ISR (void) interrupt 3 // timer1定时器10ms中断服务
{
TH1 = u8TH1_Tmp;
TL1 = u8TL1_Tmp;
P06 = ~P06; //P0.3 toggle when interrupt
time_10ms_ok = 1;
}
//INT0 外部中断,接 P30
void EXT_INT0(void) interrupt 0
{
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
Timer0_Delay1ms(100);
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
}
//管脚中断 P00, P07 接地可以触发
void PinInterrupt_ISR (void) interrupt 7
{
if(PIF == 0x01)
{
if (P17 == 1) //编码器顺时钟转一个刻度
{
Timer0_Delay1ms(5);//消抖
if (P17 == 1)
{
clr_GPIO1;
Timer1_Delay10ms(5);
set_GPIO1;
Timer1_Delay10ms(2);
}
}
else if (P17 == 0) //编码器逆时钟转一个刻度
{
Timer0_Delay1ms(5);//消抖
if (P17 == 0)
{
clr_GPIO1;
Timer1_Delay10ms(20);
set_GPIO1;
}
}
}
else if (PIF == 0x80)
{
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
Timer1_Delay10ms(10);
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
}
PIF = 0x00; //clear interrupt flag
}
void main(void)
{
P12_PushPull_Mode; //LED引脚配置
P17_Quasi_Mode; //读旋转编码器电平
P07_Quasi_Mode;
set_P0S_7;
P00_Quasi_Mode;
set_P0S_1;
P30_Quasi_Mode;
Enable_INT_Port0;
Enable_BIT7_LowLevel_Trig;
//Enable_BIT0_LowLevel_Trig;
Enable_BIT0_FallEdge_Trig;
P30 = 1; //上拉
P00 = 1; //上拉
P07 = 1; //上拉
P17 = 1; //上拉
set_EPI; // Enable pin interrupt
set_EX0;
TIMER1_MODE1_ENABLE; //定时器1, 模式1, 16bit定时器, 定时器值满 0xFFFF -> 0x0000 产生中断。
clr_T1M; //T1M = 0,兼容传统 8051, TIMER1时钟 = Fsys/12 = 16M /12
//set_T1M; //T1M = 1, TIMER1时钟 = Fsys = 16M
u8TH1_Tmp = (65536 - TIMER1_INIT)/256;
u8TL1_Tmp = (65536 - TIMER1_INIT)%256;
TH1 = u8TH1_Tmp;
TL1 = u8TL1_Tmp;
set_ET1; //enable Timer1 interrupt
set_EA; //enable interrupts
set_TR1; //Timer1 run
while (1)
{
if (time_10ms_ok) //每10ms执行一次,
{
time_10ms_ok =0;
key = key_read(); //《====== 10ms一次调用按键中间层函数,根据返回键值,点亮不同的LED灯,全面测试按键操作是否正常
if(key == S_key) //短按
{
IO_BEEP = 0;
Timer0_Delay1ms(10);
IO_BEEP = 1;
}
else if(key == D_key) //双击
{
IO_BEEP = 0;
Timer0_Delay1ms(50);
IO_BEEP = 1;
}
else if (key == L_key) //长按
{
IO_BEEP = 0;
Timer0_Delay1ms(150);
IO_BEEP = 1;
}
}
}
}
旋转编码器 CLK 引脚接 P00 (下降沿中断)
旋转编码器 DAT 引脚接 P17
中间按键接 P10,支持短按,长按,双击
蜂鸣器和LED 指示灯接 P12
工作正常。
离线
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
#define TIMER1_INIT (6663 * 2)
UINT8 u8TH1_Tmp,u8TL1_Tmp;
UINT8 time_10ms_ok;
unsigned char key;
#define IO_KEY_INPUT P10 // 按键输入口
#define IO_BEEP P12 //蜂鸣器 LED
#define N_key 0 //无键
#define S_key 1 //单键
#define D_key 2 //双键
#define L_key 3 //长键
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
unsigned char key_driver(void)
{
static unsigned char key_state = key_state_0, key_time = 0;
unsigned char key_press, key_return = N_key;
key_press = IO_KEY_INPUT; // 读按键I/O电平
switch (key_state)
{
case key_state_0: // 按键初始态
if (!key_press)
key_state = key_state_1; // 键被按下,状态转换到按键消抖和确认状态
break;
case key_state_1: // 按键消抖与确认态
if (!key_press)
{
key_time = 0; //
key_state = key_state_2; // 按键仍然处于按下,消抖完成,状态转换到按下键时间的计时状态,但返回的还是无键事件
}
else
key_state = key_state_0; // 按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的。
break;
case key_state_2:
if(key_press)
{
key_return = S_key; // 此时按键释放,说明是产生一次短操作,回送S_key
key_state = key_state_0; // 转换到按键初始态
}
else if (++key_time >= 100) // 继续按下,计时加10ms(10ms为本函数循环执行间隔)
{
key_return = L_key; // 按下时间>1000ms,此按键为长按操作,返回长键事件
key_state = key_state_3; // 转换到等待按键释放状态
}
break;
case key_state_3: // 等待按键释放状态,此状态只返回无按键事件
if (key_press)
key_state = key_state_0; //按键已释放,转换到按键初始态
break;
}
return key_return;
}
/*=============
中间层按键处理函数,调用低层函数一次,处理双击事件的判断,返回上层正确的无键、单键、双键、长键4个按键事件。
本函数由上层循环调用,间隔10ms
===============*/
unsigned char key_read(void)
{
static unsigned char key_m = key_state_0, key_time_1 = 0;
unsigned char key_return = N_key,key_temp;
key_temp = key_driver();
switch(key_m)
{
case key_state_0:
if (key_temp == S_key )
{
key_time_1 = 0; // 第1次单击,不返回,到下个状态判断后面是否出现双击
key_m = key_state_1;
}
else
key_return = key_temp; // 对于无键、长键,返回原事件
break;
case key_state_1:
if (key_temp == S_key) // 又一次单击(间隔肯定<500ms)
{
key_return = D_key; // 返回双击键事件,回初始状态
key_m = key_state_0;
}
else
{ // 这里500ms内肯定读到的都是无键事件,因为长键>1000ms,在1s前低层返回的都是无键
if(++key_time_1 >= 50)
{
key_return = S_key; // 500ms内没有再次出现单键事件,返回上一次的单键事件
key_m = key_state_0; // 返回初始状态
}
}
break;
}
return key_return;
}
/*
下面,根据程序分析按键事件的反映时间:
1。对于长键,按下超过1s马上响应,反映最快
2。对于双键,第2次按键释放后马上得到反映。
3。对于单键,释放后延时拖后500ms才能响应,反映最慢。这个与需要判断后面是否有双击操作有关,只能这样。实际应用中,可以调整两次单击间隔时间定义,比如为300ms,这样单击的响应回快一点,单按键操作人员需要加快按键的操作过程。如果产品是针对老年人的,这个时间不易太短,因为年纪大的人,反映和动作都比较慢。
当然,上面两段可以合在一起。我这样做的目的,是为了可以方便的扩展为N击(当然,需要做修改)。可是最底层的就是最基本的操作处理短按和长按,不用改动的。至于双击,还是N击,在中间层处理。这就是程序设计中分层结构的优点。
测试代码环境如下:
*/
void Timer1_ISR (void) interrupt 3 // timer1定时器10ms中断服务
{
TH1 = u8TH1_Tmp;
TL1 = u8TL1_Tmp;
// P06 = ~P06; //P0.3 toggle when interrupt
time_10ms_ok = 1;
}
//INT0 外部中断,接 P30
void EXT_INT0(void) interrupt 0
{
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
Timer0_Delay1ms(100);
clr_GPIO1;
Timer0_Delay1ms(100);
set_GPIO1;
}
//管脚中断 P00, P07 接地可以触发
void PinInterrupt_ISR (void) interrupt 7
{
if(PIF == 0x01)
{
if (P17 == 1) //编码器顺时钟转一个刻度
{
Timer0_Delay1ms(5);//消抖
if (P17 == 1)
{
clr_GPIO1;
Timer1_Delay10ms(5);
set_GPIO1;
Timer1_Delay10ms(2);
}
}
else if (P17 == 0) //编码器逆时钟转一个刻度
{
Timer0_Delay1ms(5);//消抖
if (P17 == 0)
{
clr_GPIO1;
Timer1_Delay10ms(20);
set_GPIO1;
}
}
}
else if (PIF == 0x80)
{
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
Timer1_Delay10ms(10);
clr_GPIO1;
Timer1_Delay10ms(10);
set_GPIO1;
}
PIF = 0x00; //clear interrupt flag
}
void main(void)
{
P12_PushPull_Mode; //LED引脚配置
P17_Quasi_Mode; //读旋转编码器电平
P07_Quasi_Mode;
set_P0S_7; //P0.7 施密特触发
P00_Input_Mode;
set_P0S_0; //P0.0 施密特触发
P30_Quasi_Mode; //P3.0 INT0 外部中断
//set_P3S_0; //P3.0 施密特触发
Enable_INT_Port0; //允许 P0 组管脚中断
Enable_BIT7_LowLevel_Trig; //P0.7 低电平中断
Enable_BIT0_FallEdge_Trig; //P0.0 下降沿中断
P30 = 1; //上拉
P00 = 1; //上拉
P07 = 1; //上拉
P17 = 1; //上拉
set_EPI; // Enable pin interrupt
set_EX0;
TIMER1_MODE1_ENABLE; //定时器1, 模式1, 16bit定时器, 定时器值满 0xFFFF -> 0x0000 产生中断。
clr_T1M; //T1M = 0,兼容传统 8051, TIMER1时钟 = Fsys/12 = 16M /12
//set_T1M; //T1M = 1, TIMER1时钟 = Fsys = 16M
u8TH1_Tmp = (65536 - TIMER1_INIT)/256;
u8TL1_Tmp = (65536 - TIMER1_INIT)%256;
TH1 = u8TH1_Tmp;
TL1 = u8TL1_Tmp;
set_ET1; //enable Timer1 interrupt
set_EA; //enable interrupts
set_TR1; //Timer1 run
while (1)
{
if (time_10ms_ok) //每10ms执行一次,
{
time_10ms_ok =0;
key = key_read(); //《====== 10ms一次调用按键中间层函数,根据返回键值,点亮不同的LED灯,全面测试按键操作是否正常
if(key == S_key) //短按
{
IO_BEEP = 0;
Timer0_Delay1ms(10);
IO_BEEP = 1;
}
else if(key == D_key) //双击
{
IO_BEEP = 0;
Timer0_Delay1ms(50);
IO_BEEP = 1;
}
else if (key == L_key) //长按
{
IO_BEEP = 0;
Timer0_Delay1ms(150);
IO_BEEP = 1;
}
}
}
}
在楼上的基础上,添加P0.0 管脚中断设置了施密特触发。
离线