打印
[应用方案]

keilC51编译常见错误和警告说明

[复制链接]
1798|38
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hearstnorman323|  楼主 | 2024-7-18 23:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
( 1 )L15 重复调用
***WARNING L15: MULTIPLE CALL TO SEGMENT
SEGMENT: ?PR?SPI_RECEIVE_WORD?D_SPI
CALLER1: ?PR?VSYNC_INTERRUPT?MAIN
CALLER2: ?C_C51STARTUP

该警告表示连接器发现有一个函数可能会被主函数和一个中断服务程序 ( 或者调用中断服务程序的函数 ) 同时调用 , 或者同时被多个中断服务程序调用。
出现这种问题的原因之一是这个函数是不可重入性函数 , 当该函数运行时它可能会被一个中断打断 , 从
而使得结果发生变化并可能会引起一些变量形式的冲突 ( 即引起函数内一些数据的丢失 , 可重入性函数在任何时候都可以被 ISR 打断 , 一段时间后又可以运行 , 但是相应数据不会丢失 ) 。
原因之二是用于局部变量和变量 ( 暂且这样翻译 ,arguments,[ 自变量 , 变元一数值 , 用于确定程序或子程序的值 ]) 的内存区被其他函数的内存区所覆盖 , 如果该函数被中断 , 则它的内存区就会被使用 , 这将导致其他函数
的内存冲突。

例如 , 第一个警告中函数 WRITE_GMVLX1_REG 在 D_GMVLX1.C 或者 D_GMVLX1.A51 被定义 , 它被一个中断
服务程序或者一个调用了中断服务程序的函数调用了 , 调用它的函数是 VSYNC_INTERRUPT, 在 MAIN.C 中。

解决方法:
如果你确定两个函数决不会在同一时间执行 ( 该函数被主程序调用并且中断被禁止 ), 并且该函数不占用内存 ( 假设只使用寄存器 ), 则你可以完全忽略这种警告。
如果该函数占用了内存 , 则应该使用连接器 (linker)OVERLAY 指令将函数从覆盖分析 (overlay
analysis) 中除去 , 例如:
OVERLAY (?PR?_WRITE_GMVLX1_REG?D_GMVLX1 ! *)
上面的指令防止了该函数使用的内存区被其他函数覆盖 。 如果该函数中调用了其他函数 , 而这些被调用在
程序中其他地方也被调用 , 你可能会需要也将这些函数排除在覆盖分析 (overlay analysis) 之外。这种 OVERLAY 指
令能使编译器除去上述警告信息。
如果函数可以在其执行时被调用 , 则情况会变得更复杂一些。这时可以采用以下几种方法:
1. 主程序调用该函数时禁止中断 , 可以在该函数被调用时用 #pragma disable 语句来实现禁止中断的目的。必
须使用 OVERLAY 指令将该函数从覆盖分析中除去。
2. 复制两份该函数的代码 , 一份到主程序中 , 另一份复制到中断服务程序中。
3. 将该函数设为重入型。例如:void myfunc(void) reentrant {
...
}
这种设置将会产生一个可重入堆栈 , 该堆栈被被用于存储函数值和局部变量 , 用这种方法时重入堆栈必须在 STARTUP.A51 文件中配置。这种方法消耗更多的 RAM 并会降低重入函数的执行速度。

( 2 ) 提示无 M51 文件
编译时候提示:
F:\...\XX.M51
File has been changed outside the editor, reload ?
------

解决方法:
重新生成项目,产生 STARTUP.A51 即可。

(3)L16 无调用
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?_COMPARE?TESTLCD

说明 : 程序中有些函数例如 COMPARE ( 或片段 ) 以前 ( 调试过程中 ) 从未被调用过 , 或者根本没
有调用它的语句。
这条警告信息前应该还有一条信息指示出是哪个函数导致了这一问题。只要做点简单的调整就
可以。不理它也没什么大不了的。
解决方法 : 去掉 COMPARE() 函数或利用条件编译 #if … ..#endif, 可保留该函数并不编译。

(4)L10 和 L16" 主程序名字写错 ( 或无主程序 )"
程序中 :
void mian (void)
编译提示 :
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?MIAN?MAIN
*** WARNING L10: CANNOT DETERMINE ROOT SEGMENTProgram Size: data=8.0 xdata=0 code=9
---

修改 :
缺少主程序 ( 其实是笔误 ), 将 mian 改为 main

(5)L16 主程序没用到前面定义的函数
主程序里没用到前面定义的函数,编译时显示:
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?DELAY?MAIN


(6)L210 程序前生成 SRC 语句
Build target 'Target 1'
assembling STARTUP.A51...
compiling test.C...
linking...
BL51 BANKED LINKER/LOCATER V6.00 - SN: K1JXC-94Z4V9
COPYRIGHT KEIL ELEKTRONIK GmbH 1987 - 2005
"STARTUP.obj",
"test.obj"
TO "test"
*** FATAL ERROR L210: I/O ERROR ON INPUT FILE:
EXCEPTION 0021H: PATH OR FILE NOT FOUND
FILE: test.obj
Target not created

---------
设置上的问题,在程序里屏蔽掉 #pragma src 即可

(7)C206 函数未定义
该函数没定义
MAIN.C(15): warning C206: 'delay1': missing function-prototype(8)C141 少分号
部分程序 :
{
pval = P1
P3 = pval;
}
编译提示出错 :
MAIN.C(22): error C141: syntax error near 'P3'
改正 : P1 后加 ";"

(9)C129 汇编与 C 后缀问题
例如写这么一段小程序,保存为 c0.c ,编译时出现 error c129 , miss ; before 0000 ;
如果保存为: c0.asm 就不会出现这个错误,保存为 c 的话,先调用 c51 编译器,按 c 语言的要求编译,所以
出现错误;可以参考一些书,专门介绍 keilc 这个编译器的;

(10)C101 和 C141 关于数组引号问题
定义了如下的数组:
unsigned char
a[36]={'0xfe','0xfd','0xfb','0xf7','0xef','0xdf','0xbf','0x7f','0x7e','0x7d','0x7b','0x77','0x6f','
0x5f','0x3f','0x3e','0x3d','0x3b','0x37','0x2f','0x1f','0x1e','0x1d','0x1b','0x17','0x0f','0x0e','0
x0d','0x0b','0x07','0x06','0x05','0x03','0x02','0x01','0x00'};
可是编译的时候总通不过,错误提示如下:
Build target 'Target 1'
compiling shaomiao.c...
SHAOMIAO.C(3): error C101: ''0': invalid character constant
SHAOMIAO.C(3): error C141: syntax error near 'xfe'
SHAOMIAO.C(3): error C101: ''}': invalid character constant
Target not created

解决方法:去掉 '...' 引号

(11)C100 和 C141 和 C129 程序有中文标点
用 keil 编译时出现错误,如下: D:\KEIL\C51\INC\REG52.H(1): error C100: unprintable character 0xA1
skipped同上错误有很多个,还有 D:\KEIL\C51\INC\REG52.H(2): error C141: syntax error near '#'
D:\KEIL\C51\INC\REG52.H(2): error C129: missing ';' before'<'

但是 reg52.h 头文件是 keil 自带的(见下),为何会报错呀。
----
回答: 程序里有带中文标点,用英文重新写一遍即可

(12)A45 汇编出现数字、字母混淆
MOV PO,A ;put on next 11
...
MOV RO,#0FFH ; 14
MOV R1,#OFFH ; 15
...
DJNZ RO,DLY_LP ;19
MOV R0,#OFFH ; 20
...
编译后:
ledtest.asm(11): error A45: UNDEFINED SYMBOL (PASS-2)
ledtest.asm(14): error A45: UNDEFINED SYMBOL (PASS-2)
ledtest.asm(15): error A45: UNDEFINED SYMBOL (PASS-2)
ledtest.asm(19): error A45: UNDEFINED SYMBOL (PASS-2)
ledtest.asm(20): error A45: UNDEFINED SYMBOL (PASS-2)
Target not created

---------
注意:
字母 “ O ” 和 数字 “ 0 ” 。主要错在这里。
应该输入数字 “ 0 ” ,而你输入字母 “ O ” 了。

(13) Warning 280: ’ i ’ :unreferenced local variable
说明局部变量 i 在函数中未作任何的存取操作解决方法消除函数中 i 变量的宣告2 Warning 206: ’ Music3 ’ :missing function-prototype
说明 Music3( ) 函数未作宣告或未作外部宣告所以无法给其他函数调用
解决方法将叙述 void Music3(void) 写在程序的最前端作宣告如果是其他文件的函数则要写
成 extern void Music3(void), 即作外部宣告

3 Compling :C:\8051\MANN.C
Error:318:can ’ t open file ‘ beep.h ’
说明在编译 C:\8051\MANN.C 程序过程中由于 main.c 用了指令# i nclude “ beep.h ” , 但
却找不到所致解决方法编写一个 beep.h 的包含档并存入到 c:\8051 的工作目录中

(14)Compling:C:\8051\LED.C
Error 237: ’ LedOn ’ :function already has a body

说明 LedOn( ) 函数名称重复定义即有两个以上一样的函数名称
解决方法修正其中的一个函数名称使得函数名称都是独立的

15)***WARNING 16:UNCALLED SEGMENT,IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?_DELAYX1MS?DELAY

说明 DelayX1ms( ) 函数未被其它函数调用也会占用程序**体空间解决方法去掉DelayX1ms( ) 函数或利用条件编译 #if … ..#endif, 可保留该函数并不编译

(16) ***WARNING 6 :XDATA SPACE MEMORY OVERLAP
FROM : 0025H
TO: 0025H

说明外部资料 ROM 的 0025H 重复定义地址
解决方法外部资料 ROM 的定义如下 Pdata unsigned char XFR_ADC _at_0x25 其中 XFR_ADC
变量的名称为 0x25, 请检查是否有其它的变量名称也是定义在 0x25 处并修正它

(17) WARNING 206: ’ DelayX1ms ’ : missing function-prototype
C:\8051\INPUT.C
Error 267 : ’ DelayX1ms ‘ :requires ANSI-style prototype C:\8051\INPUT.C

说明程序中有调用 DelayX1ms 函数但该函数没定义即未编写程序内容或函数已定义但未作宣告
解决方法编写 DelayX1ms 的内容编写完后也要作宣告或作外部宣告可在 delay.h 的包含档宣告成外部以便其它函数调用

(18) ***WARNING 1:UNRESOLVED EXTERNAL SYMBOL
SYMBOL:MUSIC3
MODULE:C:\8051\MUSIC.OBJ(MUSIC)
***WARNING 2:REFERENCE MADE TO UNRESOLVED EXTERNAL
SYMBOL:MUSIC3
MODULE:C:\8051\MUSIC.OBJ(MUSIC)
ADDRESS:0018H

说明程序中有调用 MUSIC 函数但未将该函数的含扩档 C 加入到工程档 Prj 作编译和连接
解决方法设 MUSIC3 函数在 MUSIC C 里将 MUSIC C 添加到工程文件中去

(19) ***ERROR 107:ADDESS SPACE OVERFLOW
SPACE: DATA
SEGMENT: _DATA_GOUP_
LENGTH: 0018H
***ERROR 118: REFERENCE MADE TO ERRONEOUS EXTERNAL
SYMBOL: VOLUME
MODULE: C:\8051\OSDM.OBJ (OSDM)
ADDRESS: 4036H

说明 data 存储空间的地址范围为 0~0x7f, 当公用变量数目和函数里的局部变量如果存储模式设为 SMALL 则局部变量先使用工作寄存器 R2~R7 作暂存当存储器不够用时则会
以 data 型别的空间作暂存的个数超过 0x7f 时就会出现地址不够的现象
解决方法将以 data 型别定义的公共变量修改为 idata 型别的定义


(20).***WARNING L15: MULTIPLE CALL TO SEGMENT
SEGMENT: ?PR?_WRITE_GMVLX1_REG?D_GMVLX1
CALLER1: ?PR?VSYNC_INTERRUPT?MAIN
CALLER2: ?C_C51STARTUP
***WARNING L15: MULTIPLE CALL TO SEGMENT
SEGMENT: ?PR?_SPI_SEND_WORD?D_SPI
CALLER1: ?PR?VSYNC_INTERRUPT?MAIN
CALLER2: ?C_C51STARTUP
***WARNING L15: MULTIPLE CALL TO SEGMENT
SEGMENT: ?PR?SPI_RECEIVE_WORD?D_SPI
CALLER1: ?PR?VSYNC_INTERRUPT?MAIN
CALLER2: ?C_C51STARTUP

该警告表示连接器发现有一个函数可能会被主函数和一个中断服务程序 ( 或者调用中断服务程序的函数 ) 同时调用 ,或者同时被多个中断服务程序调用。

出现这种问题的原因之一是这个函数是不可重入性函数 , 当该函数运行时它可能会被一
个中断打断 , 从而使得结果发生变化并可能会引起一些变量形式的冲突 ( 即引起函数内一些数据的丢失 , 可重入性函数在任何时候都可以被 ISR 打断 , 一段时间后又可以运行 , 但是相应数据不会丢失 ) 。

原因之二是用于局部变量和变量 ( 暂且这样翻译 ,arguments,[ 自变量 , 变元一数值 , 用于确定程序或子程序的值 ]) 的内存区被其他函数的内存区所覆盖 , 如果该函数被中断 , 则它的内存区就会被使用 , 这将导致其他函数的内存冲突。
例如 , 第一个警告中函数 WRITE_GMVLX1_REG 在 D_GMVLX1.C 或者 D_GMVLX1.A51 被定义 ,
它被一个中断服务程序或者一个调用了中断
服务程序的函数调用了 , 调用它的函数是 VSYNC_INTERRUPT, 在 MAIN.C 中。

解决方法:
如果你确定两个函数决不会在同一时间执行 ( 该函数被主程序调用并且中断被禁止 ), 并
且该函数不占用内存 ( 假设只使用寄存器 ),
则你可以完全忽略这种警告。
如果该函数占用了内存 , 则应该使用连接器 (linker)OVERLAY 指令将函数从覆盖分析
(overlay analysis) 中除去 , 例如:
OVERLAY (?PR?_WRITE_GMVLX1_REG?D_GMVLX1 ! *)
上面的指令防止了该函数使用的内存区被其他函数覆盖。如果该函数中调用了其他函数 ,
而这些被调用在程序中其他地方也被调用 ,
你可能会需要也将这些函数排除在覆盖分析 (overlay analysis) 之外。这种 OVERLAY 指令能
使编译器除去上述警告信息。

如果函数可以在其执行时被调用 , 则情况会变得更复杂一些。这时可以采用以下几种方
法:
1. 主程序调用该函数时禁止中断 , 可以在该函数被调用时用 #pragma disable 语句来实现禁
止中断的目的。必须使用 OVERLAY 指令将该函数
从覆盖分析中除去。
2. 复制两份该函数的代码 , 一份到主程序中 , 另一份复制到中断服务程序中。3. 将该函数设为重入型。例如:
void myfunc(void) reentrant {
...
}
这种设置将会产生一个可重入堆栈 , 该堆栈被被用于存储函数值和局部变量 , 用这种
方法时重入堆栈必须在 STARTUP.A51 文件中配置。
这种方法消耗更多的 RAM 并会降低重入函数的执行速度。

(21). *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?_COMPARE?TESTLCD

说明:程序中有些函数(或片段)以前(调试过程中)从未被调用过 , 或者根本没有
调用它的语句。
这条警告信息前应该还有一条信息指示出是哪个函数导致了这一问题。只要做点简
单的调整就可以。不理它也没什么大不了的。
解决方法 : 去掉 COMPARE() 函数或利用条件编译 #if … ..#endif, 可保留该函数并不
编译。

使用特权

评论回复
沙发
jonas222| | 2024-8-5 11:11 | 只看该作者
常见错误和警告说明
Error C100: unprintable character:这个错误表明源代码中存在不可打印的字符,可能是由于编码问题或者复制粘贴时引入的特殊字符。
Error C141: syntax error near '#'‌:这个错误通常表示在预处理指令附近有语法错误,比如宏定义不正确或者注释格式错误。
Warning L6: UNUSED SEGMENT:这个警告表示有代码段未被使用,可能是因为定义了函数但没有调用,或者代码段被错误地包含在项目中。
Warning L16: UNUSED PARAMETER:这个警告表示函数中有未使用的参数,建议去除未使用的参数以避免混淆。

使用特权

评论回复
板凳
wangdezhi| | 2024-8-6 11:49 | 只看该作者
代码优化警告 (optimizer warning):
无法优化 (cannot optimize): 编译器无法优化某些代码段。
注意事项:检查相关代码,看是否可以重写以提高可优化性。
潜在的错误 (possible error):
赋值前后类型不匹配 (assignment of different types): 赋值操作两边的类型不一致。
注意事项:检查赋值语句,确保类型匹配。
未使用的变量 (unused variable): 声明了变量但没有在代码中使用。
注意事项:删除未使用的变量,或者如果将来可能使用,可以暂时保留。
未初始化的变量 (uninitialized variable): 变量在使用前没有被初始化。
注意事项:确保所有变量在使用前都已初始化。

使用特权

评论回复
地板
yeates333| | 2024-8-8 14:34 | 只看该作者
定期检查并更新项目设置,确保所有的路径、文件名和选项配置都是正确的。错误的配置可能是许多难以捕捉的错误的根源。

使用特权

评论回复
5
zerorobert| | 2024-8-8 16:52 | 只看该作者
warning C280: 'xxx' : unreferenced local function has been removed:本地函数 xxx 未被引用,已被删除。如果该函数确实需要保留,确保在代码中调用它。
warning C591: variable was not declared in the proper scope:变量未在正确的作用域中声明。检查变量的声明位置是否符合预期。
warning C276: constant in condition expression:条件表达式中使用了常量。这可能暗示逻辑上的错误或者可以进行优化的地方。

使用特权

评论回复
6
biechedan| | 2024-8-10 13:00 | 只看该作者
嵌入式系统开发是一个不断进步的领域,通过阅读相关的技术文档、参加培训和与他人交流经验,可以不断提高解决复杂问题的能力。

使用特权

评论回复
7
tifmill| | 2024-8-10 13:19 | 只看该作者
避免在中断服务程序中使用过长时间占用的处理,如复杂的数**算或长时间的I/O操作。可以考虑将复杂操作拆分,或在主循环中处理。

使用特权

评论回复
8
updownq| | 2024-8-12 10:36 | 只看该作者
中断服务程序应尽可能短小精悍,避免在中断中进行复杂的计算或长时间的操作。

使用特权

评论回复
9
hearstnorman323|  楼主 | 2024-8-12 15:15 | 只看该作者
函数在使用前必须声明,且声明和定义之间要保持一致。

使用特权

评论回复
10
burgessmaggie| | 2024-8-12 15:53 | 只看该作者
使用清晰的注释来解释复杂的逻辑或算法。

使用特权

评论回复
11
janewood| | 2024-8-13 04:00 | 只看该作者
合理组织代码结构,使用模块化编程方法可以减少许多潜在的错误和警告。同时,这也有助于代码的维护和扩展。

使用特权

评论回复
12
jkl21| | 2024-8-13 15:24 | 只看该作者
Keil C51的错误和警告信息通常可以在Keil安装目录下的errors.chm帮助文件中查阅。

使用特权

评论回复
13
louliana| | 2024-8-13 22:39 | 只看该作者
仔细阅读编译器的输出信息,包括错误和警告,它们通常提供了问题所在的重要线索。

使用特权

评论回复
14
elsaflower| | 2024-8-17 16:25 | 只看该作者
8051的堆栈空间有限,确保函数调用和中断服务程序不会导致堆栈溢出。

使用特权

评论回复
15
earlmax| | 2024-8-18 12:18 | 只看该作者
使用 -W 标志来启用更多的警告。
使用 -O 标志来控制优化级别。

使用特权

评论回复
16
iyoum| | 2024-8-18 15:38 | 只看该作者
未使用的变量(Unused Variable):声明了变量但未在程序中使用。
未使用的函数(Unused Function):声明了函数但未在程序中调用。
隐式整数到浮点转换(Implicit Integer to Float Conversion):在进行数**算时,整数被隐式转换为浮点数。
可能的除零错误(Possible Division by Zero):程序中存在除以零的操作。
未初始化的变量(Uninitialized Variable):变量在使用前未初始化。

使用特权

评论回复
17
mmbs| | 2024-8-19 10:13 | 只看该作者
错误示例:如C141: syntax error near 'P3',通常是因为缺少分号、括号不匹配、拼写错误等。

使用特权

评论回复
18
sesefadou| | 2024-8-19 19:17 | 只看该作者
error C129: missing ';' before 'xxx':表示在指定的标识符 xxx 之前缺少分号。检查相应位置的语法,确保语句以分号结束。
error C141: syntax error near 'xxx':在 xxx 附近存在语法错误。可能是关键字使用错误、括号不匹配、操作符错误等。
error C202: 'xxx' undefined identifier:标识符 xxx 未定义。可能是变量、函数或宏未声明或拼写错误。
error C247: non-address/-constant initializer in initializer list:初始化列表中存在非法的初始化值,不是地址或常量。
error C267: 'xxx' : requires ANSI-style prototype:函数 xxx 需要符合 ANSI 风格的原型声明。

使用特权

评论回复
19
minzisc| | 2024-8-19 21:12 | 只看该作者
使用内存定位关键字(如 data, xdata)来明确指定变量的存储位置。

使用特权

评论回复
20
jtracy3| | 2024-8-20 09:34 | 只看该作者
未使用的变量:
Warning: variable 'var' is unused
解释:编译器发现了一个未使用的变量。
注意事项:移除未使用的变量以减少代码体积。
未使用的函数:
Warning: function 'func' is never used
解释:编译器发现了一个未使用的函数。
注意事项:考虑移除未使用的函数以减少代码体积。
宏定义冲突:
Warning: macro redefined
解释:宏被重新定义。
注意事项:确保宏定义在项目中唯一。
未初始化的变量:
Warning: variable 'var' may be used uninitialized
解释:编译器发现变量可能在未初始化的情况下就被使用了。
注意事项:确保所有变量在使用前都已经被初始化。
潜在的除零错误:
Warning: division by zero
解释:编译器发现了可能发生的除零错误。
注意事项:添加条件检查以避免除零错误。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

1238

帖子

1

粉丝