标题: C语言函数编译时一直报重复?WARNING L15: MULTIPLE CALL TO SEGMENT [打印本页]

作者: SHANWAZI    时间: 2021-9-5 12:21
标题: C语言函数编译时一直报重复?WARNING L15: MULTIPLE CALL TO SEGMENT
上代码:void Timer1Init(void)                //20毫秒@12.000MHz
{
        TMOD &= 0x0F;        //设置定时器模式
        TMOD |= 0x10;        //设置定时器模式
        TL1 = 0xE0;                //设置定时初值
        TH1 = 0xB1;                //设置定时初值
        TF1 = 0;                //清除TF1标志
        TR1 = 1;                //定时器1开始计时
        ET1=1;                        //允许定时器申请中断
        EA=1;                        //打开总中断
}





bit Teset()
{
        bit ack;
        
        ack=0;
        
        return ack;
}

bit Teset2()
{
        bit ack;
        
        ack=Teset();
        if(ack==0)
        {
               
        }
        return ack;
}


void Drive()
{
        static xdata uint16 Count=0;
        
        bit ack;
        
        Count++;
        if(Count>=100)
        {
                Count=0;
                ack=Teset();
                if(ack==1)
                {
                        
                }
                Teset2();
        }
}


void main(void)
{        
        Timer1Init();                                        //20毫秒@12.000MHz        
        delay(100);
        Teset2();
        while(1)
        {
                 //Drive();//在这里调用又没事??????这是什么逻辑????
        }
}


void Timer1(void) interrupt 3//20毫秒@12.000MHz
{
        TR1=0;
        Drive();//在这里中断这里调用就报错????
        TL1 = 0xE0;                //设置定时初值
        TH1 = 0xB1;                //设置定时初值
        TR1=1;
}




编译器报错为    *** WARNING L15: MULTIPLE CALL TO SEGMENT


请教论坛师傅

作者: lkc8210    时间: 2021-9-5 14:45
因为你的两个函数中会同时呼叫Teset()                               (PS: 不是Test吗?从上一个贴子已出现这个错字了,还没改过来?)
有机会在运行Teset2()中的Teset()时刚好进入中断
于是又呼叫Teset()

如果放进while(1)里就不会有这种情况

当然,这只是有机会发生,
所以他只是一个警告(Waring)而不是错误(Error)
不影响编译,不理会也可以运行
但编程时最好不要有太多嵌套


作者: SHANWAZI    时间: 2021-9-5 14:50
lkc8210 发表于 2021-9-5 14:45
因为你的两个函数中会同时呼叫Teset()                               (PS: 不是Test吗?从上一个贴子已出 ...

真的是太感谢您了!!!!!我前面一直在想是不是我程序框架搭错了想了很久   没想到给您一语道破!!!!太感谢了
作者: SHANWAZI    时间: 2021-9-5 14:53
lkc8210 发表于 2021-9-5 14:45
因为你的两个函数中会同时呼叫Teset()                               (PS: 不是Test吗?从上一个贴子已出 ...

不好意思敲错错了我一直没发现呢!!!!尴尬
作者: SHANWAZI    时间: 2021-9-5 15:03
lkc8210 发表于 2021-9-5 14:45
因为你的两个函数中会同时呼叫Teset()                               (PS: 不是Test吗?从上一个贴子已出 ...

还是要感谢您耐心指出我的问题并作出修改
作者: 188610329    时间: 2021-9-5 16:54
中断要调用的子函数,必须单独写,不然别的程序调用中,中断时又调用,会有 重入错误。
你要是实在要用一样的子函数,就原封不动照抄一编,重新命名一个名字给中断单独用。
建议养成习惯,中断不调用任何子函数。要么直接写中断里,要么精简中断,中断只作标志,让主程序周期执行。
作者: seuww    时间: 2021-9-5 23:11
主程序和中断服务程序通常不允许同时调用同一个函数,除非函数为可重入函数。你的程序思路没有错,但是编译系统逻辑上会混乱,想象一下,主程序正在执行函数A,突然中断了,再次调用这个函数,当中断返回时无法回到断点了。建议你单独写主程序中的Teset2(),因为初始化只需要执行一次。
作者: Hephaestus    时间: 2021-9-5 23:30
楼主的写法在正规的c语言编译器里面是正确无误的,不管是主循环还是中断调用Teset()都是在堆栈上临时生成局部变量空间,退出后堆栈上面的局部变量失效,可以参阅用c语言写的《数据结构》关于递归那一章。

但是在大多数8位单片机上面使用标准c语言做法,因为8位单片机设计之初就没想过用什么高级语言,相关指令都没有,所以代码会变得很长,运行时间也会变长,时间和空间都要付出相当大的代价。所以Keil C51之类的编译器就违反了标准c语言的做法,在RAM内部静态分配变量,比如Teset()局部变量地址0x20(随手举个栗子),主函数调用Teset(),发生中断,中断调用Teset(),0x20局部变量的值就被修改了,中断返回后继续执行主函数调用的Teset(),就会因为局部变量被修改而发生异常。
作者: SHANWAZI    时间: 2021-9-6 07:23
Hephaestus 发表于 2021-9-5 23:30
楼主的写法在正规的c语言编译器里面是正确无误的,不管是主循环还是中断调用Teset()都是在堆栈上临时生成局 ...

原来如此!感谢您回复个耐心回答。




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1