GLSHME 发表于 2021-9-6 10:35:24

接触器启停时,主循环无法执行,定时器中断可以运行,.....

   用51做了一个控制器,控制一个接触器运行,接触器的触头还没有带负载,接触器线圈有阻容吸收回路,现在在接触器启停时,有时会出现主循环无法执行(主循环里有一个计数器,死机时计数器的值已经没有变化了),但是定时器中断还可以正常运行的情况,定时器1ms中断一次,里面有一个呼吸灯等程序,死机时,呼吸灯还在运行,这个是怎么回事
主循环如下
void main(void)
{
        SytemInit();
        while(1)
        {
                CheckLostPower();                          //检测是否掉电,如有掉电,写EEPROM
                AnalogInput();
                OutputCurrent();                        //阀位输出
                key_display();                                //键盘及显示
                CycleCounter++;                                //主程序循环计数器,可删除
                        if(CycleCounter>=65535)        CycleCounter=0;
                if(UartSendFlag==1)       
                {       
                        printf("ADC0_result=%u\r\n",ADC0_result);
                        printf("voltage=%f\r\n",ADC0_voltage);
                        printf("Valve_position=%f\r\n",Valve_position);
                        printf("\n");
                        UartSendFlag=0;
                }
        }          
}


定时器中断如下:
//中断服务程序区
//定时器T0中断服务程序,1ms中断一次
void tm0() interrupt 1 using 1
{
        ET0=0;
    BreathLampCounter++;                           //呼吸灯计数器加一
        UartSendCounter++;                                //串口定时发送计数器加一

        QD10MS++;                                                //10ms读一次IO口
        if( QD10MS>=10 )
        {
                QD10MS=0;;
                m_OpenLimit=OpenLimit;
                m_CloseLimit=CloseLimit;
                m_OpenRemote=OpenRemote;
                m_CloseRemote=CloseRemote;
        }

        if(BreathLampCounter>=1500)                //呼吸灯计数器清零
        {
                BreathLampCounter=0;
        }

        if(BreathLampCounter<=30)                //点亮、熄灭呼吸灯,LED1用作呼吸灯
        {
                LED1_ON       
        }
        else
        {
               LED1_OFF          
        }

        if(UartSendCounter>=1000)               //串口每秒自动发送一次
        {
                UartSendCounter=0;
                UartSendFlag=1;
        }

        if(BuzerFlag==1)
        {
                LED3_ON
                BUZZER_ON
                BuzerCounter++;
                if(BuzerCounter>=5)
                {
                        BuzerCounter=0;
                        BUZZER_OFF
                        LED3_OFF
                        BuzerFlag=0;
                }
        }
        ET0=1;
        return;
}

lyl1070 发表于 2021-9-6 13:56:41

进了假死状态,连个看门狗都没有。直接给零分。
举个例子,IIC编程。
1.clk=1;启动clk拉高;
2.while(sda==0);等待sda为零。
3.XXX继续。

在2这里,sda一直无法拉低,一直为1,程序就好像是死了。

怎么解决呢?
设置一个等待超时就行。
ucha i=0;
1.clk=1;启动clk拉高;
2.while(sda==0)
{
i++;
if(i>250)break;
}等待sda为零。
3.XXX继续。

GLSHME 发表于 2021-9-6 14:50:07

看门狗是故意没有加的,因为想找出程序死机的原因
我检查一下有没有类似你说的IIC的原因

GLSHME 发表于 2021-9-6 17:33:39

把程序多余的地方全部删掉,只留下开关接触器的部分,还是一样的现象,主循环中的串口无法发送,定时器中断可以执行,呼吸灯在闪烁

void SytemInit(void)
{
        ValveStop
        BUZZER_OFF
        GPIO_config();                           //------------外设初始化--------------
        UartInit();                                //所有GPIO初始化
        TimerInit();                        //所有定时器初始化

        ES=0;                                   //串口发送信息,最好先关闭串口中断ES=0,这里没有关
        TI=1;                       
        EA=1;                                        //打开全局中断开关
}


//------------主函数--------------
void main(void)
{
        SytemInit();
        while(1)
        {
                if(P70==0)
                        ValveClose
                if(P70==1)
                        ValveStop
                CycleCounter++;                                //主程序循环计数器,可删除
                        if(CycleCounter>=65535)        CycleCounter=0;
                if(UartSendFlag==1)       
                {       
                        printf("CycleCounter=%u\r\n",CycleCounter);
                        UartSendFlag=0;
                }
        }          
}


//中断服务程序区
//定时器T0中断服务程序,1ms中断一次
void tm0() interrupt 1 using 1
{
        ET0=0;
    BreathLampCounter++;                           //呼吸灯计数器加一
        UartSendCounter++;                                //串口定时发送计数器加一

        if(BreathLampCounter>=1500)                //呼吸灯计数器清零
                BreathLampCounter=0;

        if(BreathLampCounter<=30)                //点亮、熄灭呼吸灯,LED1用作呼吸灯
                LED1_ON       
        else
               LED1_OFF          

        if(UartSendCounter>=1000)               //串口每秒自动发送一次
        {
                UartSendCounter=0;
                UartSendFlag=1;
        }
        ET0=1;
        return;
}

lingdianhao 发表于 2021-9-6 17:35:37

有没有可能一直在中断里面跑。

GLSHME 发表于 2021-9-6 17:39:14

lingdianhao 发表于 2021-9-6 17:35
有没有可能一直在中断里面跑。

但是中断程序里面的代码执行完后,应该会返回到主程序中呀

GLSHME 发表于 2021-9-6 17:39:38

lingdianhao 发表于 2021-9-6 17:35
有没有可能一直在中断里面跑。

因为中断程序里面没有任何的循环

GLSHME 发表于 2021-9-6 17:40:43

看程序运行的结果,不像是死机,只是不能返回到主循环而已

鲜衣怒马 发表于 2021-9-6 18:11:39

传说中的程序跑飞了?

小李非刀 发表于 2021-9-7 15:05:54

任何地方不要出现无超时的死等,一旦等待的事件没发生,就会一直等下去,而MCU并没有死。

boycn 发表于 2021-9-7 17:26:15

可能就是串口死了,判断不到发送完成标志

饭桶 发表于 2021-9-7 20:53:01

中断服务子程序里面的代码太多了,新手常见大错误之一。

GLSHME 发表于 2021-9-8 08:22:09

小李非刀 发表于 2021-9-7 15:05
任何地方不要出现无超时的死等,一旦等待的事件没发生,就会一直等下去,而MCU并没有死。 ...

已经把程序简化了,没有等待的语句

GLSHME 发表于 2021-9-8 08:23:11

boycn 发表于 2021-9-7 17:26
可能就是串口死了,判断不到发送完成标志

串口发送用的是printf函数,正常不会死机吧,我试试把这句取消看

GLSHME 发表于 2021-9-8 08:24:59

饭桶 发表于 2021-9-7 20:53
中断服务子程序里面的代码太多了,新手常见大错误之一。

中断里面13行的c语句,其实不算多,也没有循环和函数调用

hemingjing 发表于 2021-9-8 12:06:48

GLSHME 发表于 2021-9-8 08:24
中断里面13行的c语句,其实不算多,也没有循环和函数调用

也有可能是一直进了其它的中断,把串口接收中断和发送中断都关闭试试

rube 发表于 2021-9-9 13:14:42

GLSHME 发表于 2021-9-8 08:23
串口发送用的是printf函数,正常不会死机吧,我试试把这句取消看

去掉printf函数,大概率好了{:lol:}

wangzex 发表于 2021-9-9 16:30:59

检查硬件。大概率板子没布好。

GLSHME 发表于 2021-9-10 08:22:32

rube 发表于 2021-9-9 13:14
去掉printf函数,大概率好了

删掉了printf语句,还是会出现IO口不受控制,有时蜂鸣器会乱响。

GLSHME 发表于 2021-9-10 08:24:00

wangzex 发表于 2021-9-9 16:30
检查硬件。大概率板子没布好。

大概率是线路板布局的原因,用另外一块开发板,把IO口引到这块板子的继电器控制线路上,没有在出现死机等现象。

GLSHME 发表于 2021-9-10 08:31:37

这块板子是为了验证电路功能,所以没有考虑太多的抗干扰措施,但是没有想到干扰这么大,接触器频繁启停时,一旁的戴尔显示器也被搞得频繁重启复位。

lnso 发表于 2021-9-10 12:52:29

单片机加隔离吧,很爽的。那种隔离电源模块也不贵

小李非刀 发表于 2021-9-10 15:01:03

GLSHME 发表于 2021-9-10 08:24
大概率是线路板布局的原因,用另外一块开发板,把IO口引到这块板子的继电器控制线路上,没有在出现死机等 ...

那就是布板的问题,只考虑连通,不考虑干扰。

modbus 发表于 2021-9-10 16:31:20

具体用的哪个型号?

GLSHME 发表于 2021-9-13 16:49:52

modbus 发表于 2021-9-10 16:31
具体用的哪个型号?

STC8A8K64S4

bluerain 发表于 2021-9-15 17:02:02

线路板排版很关键,板子没布好再好的抗干扰单片机也没有用。要不然,应届毕业生跟多年经验的老工程师就没工资区别了。
页: [1]
查看完整版本: 接触器启停时,主循环无法执行,定时器中断可以运行,.....