找回密码
 立即注册
查看: 60|回复: 5

stc32g12k128实验箱红外遥控程序卡死问题

[复制链接]
已绑定手机

9

主题

231

回帖

366

积分

中级会员

积分
366
发表于 2026-10-30 18:39:43 | 显示全部楼层 |阅读模式
stc32g12k128实验箱红外遥控程序,按下遥控器程序卡住不动了,请大神们帮忙看看是什么问题,先把代码发上来:


#include "MAIN_ALL.H"

sbit Ir_Input = P3^5;                //红外接收引脚
                                                        //
bit Ir_Flag = 0;            //红外接收完成标志
u8 Ir_Code[4];              //红外接收缓冲区
u16 Ir_TimeCount;

/*----------------P35口中断初始化------------------*/
void Port35_Init()
{
       
        P3IM0 &= ~0x20;                //P3.5口下降沿中断
        P3IM1 &= ~0x20;
        P3INTE |= 0x20;                //使能P3.5口中断
        P3INTF = 0x00;                //清中断标志位
       
}
/*----------------获取当前高电平持续时间-----------------*/
u16 GetHighTime()
{
        u16 dat = 0;
        TR1 = 1;
//        ET1 = 1;                        //启动计数
        while(Ir_Input)                //红外输入引脚为1时循环检测等待
        {                                        //变为0时则结束循环
                if(Ir_TimeCount >= 180)        // 当T1计数值大于0x1800,即高电平持续时间超过约18ms时,
                {
                        dat = Ir_TimeCount;
                        break;                //强制退出循环,是为了避免信号异常时,程序假死在这里。
                }
               
        }
        TR1 = 0;
//        ET1 = 0;
        Ir_TimeCount = 0;
       
        return dat;//T1计数值合成为16bit整型数,并返回该数
}
/*----------------获取当前低电平持续时间-----------------*/
u16 GetLowTime()
{
        u16 dat = 0;
        TR1 = 1;
        while(!Ir_Input)                        //红外输入引脚为0时循环检测等待
        {
                if(Ir_TimeCount >= 180)// 当T1计数值大于0x1800,即低电平持续时间超过约18ms时,
                {
                        dat = Ir_TimeCount;
                        break;
                }
       
        }
        TR1 = 0;
        Ir_TimeCount = 0;
        return dat;
}

void Timer1_Isr() interrupt 3
{
        Ir_TimeCount ++;
}

void P3INT_Isr() interrupt 13
{
        u8 i,j;
        u8 byt = 0;
        u8 intf;
        u16 time;
       
        intf = P3INTF;                                //选读中断标志
        if(intf == 0)return;
        P3INTF = 0x00;
        if((intf & 0x20)==0)return;
       
        //接收并判定引导码的9ms低电平
        time = GetLowTime();
        if((time < 850)||(time>950))        //时间判定范围为8.5~9.5ms,
        {                               //超过此范围则说明为误码,直接退出
                              //退出前清零中断标志
                return;
        }
        //接收并判定引导码的4.5ms高电平
        time = GetHighTime();
        if((time < 400)||(time>500))        //时间判定范围为4~5ms,
        {                               //超过此范围则说明为误码,直接退出
               
                return;
        }
         //接收并判定后续的4字节数据
        for(i=0;i<4;i++)                                //循环接收4个字节
        {
                byt = 0;
                for(j=0;j<8;j++)                        //循环接收8个bit
                {
                         //接收判定每bit的560us低电平
                        time = GetLowTime();
                        if((time<35)||(time>75))        //时间判定范围为350~750us,
                        {                           //超过此范围则说明为误码,直接退出
                                 
                                return;
                        }
                        time = GetHighTime();                //接收每bit高电平时间,判定该bit 的值
                        if((time > 35)&&(time<75))        //时间判定范围为350~750us,
                        {                            //在此范围内说明该bit值为0
                                byt >>= 1;                 //因低位在先,所以数据右移,高位为0
                        }
                        else if((time >140)&&(time<190))        //在此范围内说明该bit值为1
                        {
                                byt >>= 1;
                                byt |= 0x80;
                        }
                        else                              //不在上述范围内则说明为误码,直接退出
                        {
                               
                                return;
                        }
                }
                Ir_Code = byt;                 //接收完一个字节后保存到缓冲区
               
        }
        Ir_Flag = 1;
       
}
程序中有定时器0中断,串口中断,定时器1中断开与不开都会卡住



回复

使用道具 举报 送花

已绑定手机

9

主题

231

回帖

366

积分

中级会员

积分
366
 楼主| 发表于 2026-10-30 18:44:07 | 显示全部楼层
红外遥控用定时器1定时10us计数,P3.5口中断计算脉冲数解码,按下遥控器数码管显示三橫,直接卡住不动,其它功能都不能用了
回复

使用道具 举报 送花

已绑定手机

2

主题

154

回帖

470

积分

中级会员

积分
470
发表于 2026-10-30 21:30:36 | 显示全部楼层
卡住有可能是死循环了。
而最可能死循环的是GetLowTime和GetHighTime,
当Ir_TimeCount不计数时,就死循环。
而Ir_TimeCount不计数的原因,是定时器1没启动或没使能中断。
所以检查一下定时1。

定时器1和p3的中断默认优先级一样,
p3中断后,在返回前,定时器1的中断无法得到执行,
所以Ir_TimeCount不计数。
要改定时器1优先级高于p3,或把原p3中断中的逻辑代码移到main中。
回复

使用道具 举报 送花

已绑定手机

9

主题

231

回帖

366

积分

中级会员

积分
366
 楼主| 发表于 6 天前 | 显示全部楼层
jrc*** 发表于 2026-10-30 21:30
卡住有可能是死循环了。
而最可能死循环的是GetLowTime和GetHighTime,
当Ir_TimeCount不计数时,就死循环。 ...

//将下面的代码保存为 ISR.ASM,然后将文件加入到项目中即可
        CSEG                AT0143H
        JMP                        P3INT_ISR
P3INT_ISR:
        JMP                        006BH
        END
//借用13号中断的入口地址
谢谢回复,我把这个加入到文件中,忘了把这个加入工程了
回复

使用道具 举报 送花

已绑定手机

9

主题

231

回帖

366

积分

中级会员

积分
366
 楼主| 发表于 6 天前 | 显示全部楼层
上面的代码有问题,下面这个可以正常解码;

#include "MAIN_ALL.H"
               
bit Ir_OK_Flag = 0;            //红外接收完成标志
u8  Ir_Code[6];                      //红外接收缓冲区
u8 xdata Ir_Byte_Count;                        //接收的次数(字节数),32字节+引导码共33
u8 xdata Ir_Byte_Timer;                        //100us计数时间
u8 xdata Ir_Byte_TimeBuffer[33];// [0]=引导码间隔, [1..32]=数据位间隔
/*----------------P35口中断初始化------------------*/
void Port35_Init()
{
       
        P3IM0 &= ~0x20;                //P3.5口下降沿中断
        P3IM1 &= ~0x20;
        P3INTE |= 0x20;                //使能P3.5口中断

        PINIPL &= ~0x08;        //中断低优先级
        PINIPH &= ~0x08;
}
/*----------------红外解码函数------------------*/
void Ir_Decode()
{
        u8 i,j,Value=0;
        u8 k = 1;
        if(Ir_OK_Flag)                //接收完成,将接收完成标志清零
        {
                Ir_OK_Flag=0;
                TR1 = 0;
                for(i=0;i<4;i++)        //循环判断4个字节
                {
                        Value=0;
                        for(j=0;j<8;j++)        //循环判断每个字节中的8位
                        {
                                Value >>= 1;
                                if(Ir_Byte_TimeBuffer[k] > 17)
                                {
                                        Value = Value|0x80;
                                }
                                else
                                {
                                        Value = Value&0x7F;
                                }
                                k++;
                        }
                        if(i==3)
                        {
                                if(Value != Ir_Code[3])                //长按判断,如果新解码的值与上次的值不相等让数组的第4位清零
                                {
                                        Ir_Code[4] = 0;
                                        Ir_Code[5] = 0;
                                }
                                if(Value == Ir_Code[3])                //连按判断,如果新解码的值与上次的值相等让数组的第5位加1
                                {
                                        Ir_Code[5] ++;
                                        Ir_Code[4]  = 0;
                                }
                        }
                       
                        Ir_Code[i] = Value;
                }
        }
}
//-------------P35口下降沿中断服务函数-----------------
//========================================================================
// 函数: P35口下降沿中断服务函数
// 描述: 利用P35口下降沿中断判断Ir_Byte_Timer的计时时间,大于110(以100us计时即11ms)则认为是引导码
//                (9ms载波+4.5ms高电平),将引导码存入数组的第0号字节,以次存入33个字节,
//               
// 参数:
// 返回:
// 备注:
//========================================================================

void P3INT_Isr() interrupt 13
{
        static bit Ir_Flag=0;
        u8 intf;       
       
        intf = P3INTF;                                                //        P3INTF,P35口中断的溢出标志位
        if(intf)
        {
                P3INTF = 0x00;
                if((intf & 0x20))
                {
                        TR1 = 1;
                       
                        if(Ir_Byte_Timer >= 110)        //计时大于110认为是引导码
                        {
                                Ir_Flag=1;                                //引导码完成标志置1
                                Ir_Byte_Count=0;                //将bit计数值清零,确保把引导码存入第0位
                                Ir_Code[4] ++;                        //长按判断
                        }
                        if(Ir_Flag)
                        {
                               
                                Ir_Byte_TimeBuffer[Ir_Byte_Count] = Ir_Byte_Timer ;        //依次存入33位bit数据
                                Ir_Byte_Timer = 0;
                                Ir_Byte_Count ++;
                                if(Ir_Byte_Count >= 33)               
                                {
                                        Ir_Byte_Count=0;
                                        Ir_Byte_Timer = 0;
                                        Ir_OK_Flag = 1;
                                        Ir_Flag=0;
                                }
                        }
                }
        }

}
/*---------------- 定时器1中断服务函数-----------------*/

void Timer1_Isr(void) interrupt 3
{
       
        Ir_Byte_Timer ++ ;
}
回复

使用道具 举报 送花

已绑定手机

9

主题

231

回帖

366

积分

中级会员

积分
366
 楼主| 发表于 6 天前 | 显示全部楼层
红外解码加长按和连按功能
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-7 14:49 , Processed in 0.070346 second(s), 65 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表