C51单片机中reentrant关键字的使用,关于MULTIPLE CALL TO FUNCTION警告的问题

📅 2026/7/16 20:52:00
C51单片机中reentrant关键字的使用,关于MULTIPLE CALL TO FUNCTION警告的问题
关于可重入关键字reentrant的使用现象在一个项目中警告信息如下提示该函数多次调用因为该函数在串口中断和主循环中都有被调用。影响如果在使用该函数期间被中断打断而中断也调用了该函数那么该函数的局部变量会被覆盖。当中断结束返回则此时的变量已经被中断修改了此时的数据不对会出现意想不到的结果。这就是不可重入non-reentrant原因Keil C51 为了省 RAM、提速普通函数的参数和局部变量往往不放在硬件栈上而是放在固定的静态内存里类似全局变量。51单片机资源有限为了提高运行效率C51采用静态分配局部变量的方式所以不可递归。而标准C语言的堆栈是动态分配的。解决方案给需要重复调用的函数加上reentrant关键字使用方式如下图编译器会改成参数/局部变量放到专用的可重入栈上每次调用都有自己的一份不再共用固定地址。这样中断里可以安全再调这个函数。另外递归调用也可以8051 上很少这么干且很吃 RAM最后再编译发现警告消失。注意使用reentrant要另外需要在启动文件中根据内存模型打开对应栈3.IBPSTACK / XBPSTACK / PBPSTACK分别是什么它们对应三种内存模型下的可重入栈指针初始化开关名字含义可重入栈放哪典型场景IBPSTACKIdataBasePointer Stack内部 RAMidataSmall 模型 reentrantPBPSTACKPdataBasePointer Stackpdata一页 256 字节外存Compact 模型 reentrantXBPSTACKXdataBasePointer Stackxdata外部 RAMLarge 模型 reentrant建议什么时候才需要reentrant典型需求中断服务程序里要调用某个也会在主循环调用的函数且该函数有局部变量/参数需要递归某些第三方库明确要求reentrant并说明要开哪一种栈更常见、更稳妥的做法同个函数再复制一份功能完全一样但函数名不一样中断里只置标志、收数据复杂处理放到主循环这样就不需要reentrant参考文章1、C51的再入函数 reentrant RECURSIVE CALL TO SEGMENT2、51单片机与递归的问题