【解析新特性】300W单路输出工业电源>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » keilC51编程常见错误

共1条 1/1 1 跳转至

keilC51编程常见错误

助工
2014-11-13 23:00:36    评分
( 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 /* Read P1 into pval */
P3 = pval; /* Write pval to P3 */
}
编译提示出错 :
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, 可保留该函数并不
编译。

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]