找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3041|回复: 8
打印 上一主题 下一主题
收起左侧

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


请教论坛师傅
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

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

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

回复

使用道具 举报

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

真的是太感谢您了!!!!!我前面一直在想是不是我程序框架搭错了想了很久   没想到给您一语道破!!!!太感谢了
回复

使用道具 举报

地板
ID:232366 发表于 2021-9-5 14:53 | 只看该作者
lkc8210 发表于 2021-9-5 14:45
因为你的两个函数中会同时呼叫Teset()                               (PS: 不是Test吗?从上一个贴子已出 ...

不好意思敲错错了我一直没发现呢!!!!尴尬
回复

使用道具 举报

5#
ID:232366 发表于 2021-9-5 15:03 | 只看该作者
lkc8210 发表于 2021-9-5 14:45
因为你的两个函数中会同时呼叫Teset()                               (PS: 不是Test吗?从上一个贴子已出 ...

还是要感谢您耐心指出我的问题并作出修改
回复

使用道具 举报

6#
ID:624769 发表于 2021-9-5 16:54 | 只看该作者
中断要调用的子函数,必须单独写,不然别的程序调用中,中断时又调用,会有 重入错误。
你要是实在要用一样的子函数,就原封不动照抄一编,重新命名一个名字给中断单独用。
建议养成习惯,中断不调用任何子函数。要么直接写中断里,要么精简中断,中断只作标志,让主程序周期执行。
回复

使用道具 举报

7#
ID:960726 发表于 2021-9-5 23:11 | 只看该作者
主程序和中断服务程序通常不允许同时调用同一个函数,除非函数为可重入函数。你的程序思路没有错,但是编译系统逻辑上会混乱,想象一下,主程序正在执行函数A,突然中断了,再次调用这个函数,当中断返回时无法回到断点了。建议你单独写主程序中的Teset2(),因为初始化只需要执行一次。
回复

使用道具 举报

8#
ID:883242 发表于 2021-9-5 23:30 | 只看该作者
楼主的写法在正规的c语言编译器里面是正确无误的,不管是主循环还是中断调用Teset()都是在堆栈上临时生成局部变量空间,退出后堆栈上面的局部变量失效,可以参阅用c语言写的《数据结构》关于递归那一章。

但是在大多数8位单片机上面使用标准c语言做法,因为8位单片机设计之初就没想过用什么高级语言,相关指令都没有,所以代码会变得很长,运行时间也会变长,时间和空间都要付出相当大的代价。所以Keil C51之类的编译器就违反了标准c语言的做法,在RAM内部静态分配变量,比如Teset()局部变量地址0x20(随手举个栗子),主函数调用Teset(),发生中断,中断调用Teset(),0x20局部变量的值就被修改了,中断返回后继续执行主函数调用的Teset(),就会因为局部变量被修改而发生异常。
回复

使用道具 举报

9#
ID:232366 发表于 2021-9-6 07:23 来自触屏版 | 只看该作者
Hephaestus 发表于 2021-9-5 23:30
楼主的写法在正规的c语言编译器里面是正确无误的,不管是主循环还是中断调用Teset()都是在堆栈上临时生成局 ...

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

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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