sclx00 发表于 2026-6-10 23:21:11

清帮我看看为什么中断会运行2次

这个流水灯一个是P3.2外部中断,一个是P1.1 I/O上升沿中断,外接的是一个红外模块,不论哪个中断都会让程序运行2次(灯亮灭2次)。 代码如下



#include "config.h"
#include "ai8051u.h"

void PORT1_Init(void)                                          
{
    SetP1nInitLevelHigh(PIN_ALL);       //设置P1初始化电平
    SetP1nQuasiMode(PIN_ALL);         //设置P1为准双向口模式
    SetP1nManualMode(PIN_ALL);          //设置P1手动配置端口模式

    DisableP1nPullUp(PIN_ALL);          //关闭P1内部上拉电阻
    DisableP1nPullDown(PIN_ALL);      //关闭P1内部下拉电阻
    EnableP1nSchmitt(PIN_ALL);          //使能P1施密特触发
    SetP1nSlewRateNormal(PIN_ALL);      //设置P1一般翻转速度
    SetP1nDrivingNormal(PIN_ALL);       //设置P1一般驱动能力
    SetP1nDigitalInput(PIN_ALL);      //使能P1数字信号输入功能

    SetP1nRisingInt(PIN_2 | PIN_1);   //设置P1.2,P1.1为上升沿中断

    EnableP1nInt(PIN_2 | PIN_1);      //使能P1.2,P1.1口中断

    SetP1IntPriority(0);                //设置中断为最低优先级

    //<<AICUBE_USER_PORT1_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_PORT1_INITIAL_END>>
}

void SYS_Init(void)
{
    EnableAccessXFR();
    AccessCodeFastest();
    AccessIXramFastest();
    IAP_SetTimeBase();
    PORT1_Init();                     //P1口初始化

    P2M0 = 0x00; P2M1 = 0x00;
}

////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
    // 在此添加用户主函数初始化代码
    WTST = 0;          // 设置程序指令延时参数
    EAXFR = 1;         // 使能访问扩展寄存器区(XFR)
    CKCON = 0;         // 提高访问 XRAM速度      
      
      P3M0 = 0x00;       // P3 准双向口模式(包含输入功能)                        //新改
    P3M1 = 0x00;
      IT0 = 0;   // INT0 下降沿触发(IT0=0 为低电平触发)
      EX0 = 1;   // 使能 INT0 中断
      EA= 1;

      
    SYS_Init();
    // 在此添加主函数中运行一次的用户代码
                P2 = 0x00;                                        //对P0端口置0,点亮整组LED
                delay_ms(2000);
                P2 = 0xFF;                                        //对P0端口置0,点亮整组LED
                delay_ms(100);

    while (1)
    {
   // 在此添加主函数中用户主循环代码
      }
}

////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
    uint16_t i;

    do
    {
      i = MAIN_Fosc / 6000;
      while (--i);
    } while (--ms);
}

void EXTI0_ISR(void) interrupt 0
{
    // 在此添加中断函数用户代码
                        P21 = 0;
                        delay_ms(800);
                        P22 = 0;
                        delay_ms(800);
                        P23 = 0;
                        delay_ms(2000);
                        P21 = 1;
                        delay_ms(800);
                        P22 = 1;
                        delay_ms(800);
                        P23 = 1;
                        delay_ms(800);
}
////////////////////////////////////////
// 外部中断INT1中断服务程序
void EXTI1_ISR(void) interrupt INT1_VECTOR
{
    //<<AICUBE_USER_EXTI1_ISR_CODE1_BEGIN>>
                P22 = ~P22;               
      delay_ms(1000);
    // 在此添加中断函数用户代码
    //<<AICUBE_USER_EXTI1_ISR_CODE1_END>>
}

void P1_ISR(void) interrupt 38
{
    u8 intf;                // ← 用 u8,不是 uint8_t!

    intf = P1INTF;          // 读取P1口中断标志
    if(intf)
    {
      P1INTF = 0x00;      // 软件清空中断标志

      if(intf & 0x02)   // P1.1 产生了上升沿中断
      {
                        P21 = 0;
                        delay_ms(800);
                        P22 = 0;
                        delay_ms(800);
                        P23 = 0;
                        delay_ms(2000);
                        P21 = 1;
                        delay_ms(800);
                        P22 = 1;
                        delay_ms(800);
                        P23 = 1;
                        delay_ms(800);
      }
    }
}


狂热主宰 发表于 2026-6-11 10:00:44

有人说中断得快进快出
其中使用delay_ms(x)延时少见
{:4_164:}

狂热主宰 发表于 2026-6-11 10:14:35

可能需要
看看教学视频
补充学习单片机知识

Ai8051U深度入门到32位51大型实战教学视频

https://www.stcaimcu.com/forum.php?mod=viewthread&tid=11902




梁工 发表于 2026-6-11 10:26:27

建议使用一个方波信号触发P3.2看看,会不会是你的红外信号有抖动?

lcwswust 发表于 2026-6-11 10:28:16

有示波器没?看下中断脚的波形是不是有多个边沿。
“两次”,大概率是因为处理第一次中断耗时较长,后面的中断未及时响应,等第一次中断处理完,发现中断标志置位了(虽然早已没有外部信号,但标志还在、未被清除),所以再次进中断。
如果你的中断响应够快,可能会发现,实际中断次数(边沿)不止两次。

jwd 发表于 2026-6-11 10:40:46

中断里面还是不要使用delay函数了吧

狂热主宰 发表于 2026-6-11 11:21:49

该函数
选中的部分

可放在main的while(1)
耗时操作放主循环

if里intf还要清零
防重复操作

sclx00 发表于 2026-6-11 21:47:55

lcwswust 发表于 2026-6-11 10:28
有示波器没?看下中断脚的波形是不是有多个边沿。
“两次”,大概率是因为处理第一次中断耗时较长,后面的 ...

没有示波器,我认为也是这个原因,我试试高电平能不能避免这个问题

sclx00 发表于 2026-6-11 21:51:31

狂热主宰 发表于 2026-6-11 11:21
该函数
选中的部分



试过了 仍然还是跑2次灯不知道什么原因第一次亮灯的间隔时间明显延长很多大约3秒左右第二次正常0.8秒间隔我试试高电平触发
页: [1]
查看完整版本: 清帮我看看为什么中断会运行2次