您尚未登录。

楼主 # 2021-07-13 15:34:27

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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)
    {
    }
}

离线

楼主 #1 2021-07-13 16:09:36

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

Re: 发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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

离线

楼主 #2 2021-07-13 16:56:42

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

Re: 发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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)
    {
    }
}

下降沿中断

离线

楼主 #3 2021-07-13 18:00:59

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

Re: 发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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

检测管脚中断

离线

楼主 #4 2021-07-20 17:16:05

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

Re: 发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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

离线

楼主 #5 2021-07-20 17:52:54

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

Re: 发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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

工作正常了。

离线

楼主 #6 2021-07-20 18:04:26

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

Re: 发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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

工作正常。

离线

楼主 #7 2021-07-21 09:30:38

tigger
会员
注册时间: 2021-06-18
已发帖子: 73
积分: 37

Re: 发一个 N76E003 能用的管脚中断例程,新唐BSP里面那个太垃圾了

#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 管脚中断设置了施密特触发。

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn