%7B%22xs%22%3A800%2C%22sm%22%3A600%2C%22md%22%3A400%2C%22float%22%3A0.5%7D
33203
%7B%22isLastPage%22%3Atrue%2C%22notes%22%3A%5B%7B%22type%22%3A%22post%22%2C%22targetId%22%3A%22t33203%22%2C%22notes%22%3A%5B%5D%7D%2C%7B%22type%22%3A%22post%22%2C%22targetId%22%3A%22735836%22%2C%22notes%22%3A%5B%5D%7D%5D%2C%22pid%22%3A%22t33203%22%2C%22tid%22%3A%2233203%22%2C%22mainForumsId%22%3A%5B%2237%22%5D%2C%22categoriesId%22%3A%5B%2250%22%5D%2C%22tcId%22%3A%5B%5D%7D
%7B%22isEditMode%22%3Afalse%7D
[原创]伟福与Keil的比较--51汇编提高篇
hefanghua 2011/04/23 电子技术 IP:广西
[写在前面] 本文适合有一定汇编水平的人(了解大半的汇编语句,能区分全角与半角符号,能够独立编写流水灯、数码管等程序),传授51单片机的汇编语言经验。如果您发现不少指令不知道意思,请从网上搜索入门教程学习。本人编程有几年了,虽然不是高手,只以老手自居,写点经验分享,希望对编程有帮助。 [优缺点比较] Keil是德国人开发出来的一款集成开发环境,与它同类的软件还有IAR等等。Keil自带有简单的调试工具ISD5与较复杂RTX51 OS,可以与proteus联合调试,能够不接硬件进行调试。虽然拥有强大的功能,但是软件是要钱的,用HX版总归不好,且全英文界面不适合新手。由于keil用得少,它的毛病没找出多少。以下是Keil μvision3(以下简称keil)的一些问题归纳: 1. 对汇编文件进行编译时使允许用C语言的语法,不规范,在标准汇编器上会报错。比如引用符号/* */,以及表格部分。 2. Keil必须把源文件放入工程文件中才可标记语法。 3. Keil的标题“礦ision3”(可参考网上的修改方法) 4. Keil的某些版本光标定位不准。出现字符与实际错位的现象(解决办法:在字体的ASM、C编译列表里,改text字体为fixedsys,大小为10) 5. Keil的汉字问题。对部分汉字的ASCII码引用出错误,导致液晶上看到的不对。(也请参考网上的修改办法)--偶暂时没遇到额。 6. 可以整段拖动,是优点也是缺点,有可能打瞌睡不小心移动了都不知道。 7. keil无法使用PSW寄存器里面留给用户使用的f0, f1位地址,不知道什么原因,这点比较郁闷。 8. "Go To Definiton Of 'xxx'"在汇编里是废的 伟福WAVE6000不出名,主要特点是免费,软件体积小等等。它也有不少问题: 1.长时间使用wave可能导致一些莫明其妙的错误,比如:编译得不到正确结果,进不了中断现象,软件仿真时指针不前进等怪问题。关掉软件重新打开即可。另外,请备份一个设置好的wave.ini文件,如果遇到打字的速度变得贼慢,覆盖掉它就解决了。 2. WAVE的窗口比较残疾。刚打开的时候不是最大化的,一不小心就挪走了(偶的鼠标比较龊)。点击任务栏不能最小化,而是“恢复窗口”。不能记忆编写的位置,这点比不上keil。 3. 比较跳转之类的指令,如果编写有错,WAVE经常不能指向错误所在行。(解决办法见提高部分的“跳转范围”) 4. 伟福编译器的位地址BIT显示到了0FFH,过了7F以后都无法在RAM里看到修改结果,即为无效。--BUG之一 5. WAVE仿真首次运行时时间不对,运行时间超过分钟级别也会不正确(运行数分钟以上的程序会出现时间不停、回0的现象),是编译器问题。 6. 原版WAVE不支持鼠标滚轮翻页,已找到解决方案,见参考资料。 在51单片机汇编下,WAVE与Keil两者的比较: 1. keil只能用EQU语句定义,不能直接用=号定义, 而WAVE可以用=定义(定义数值、口线、特殊寄存器地址等),但不等同于字符串替换。 2. keil包含文件采用#include "filename.xxx"的形式,不能有中文符号;WAVE少个#号,可以有中文符号。(具体用法见提高部分) 3. Keil设置中文字体后,可以整个字符操作(需在注释里面才能显示);WAVE却把一个汉字当两个字符处理了。(<伟福软件的另类用法>我们可以利用这特点快速显示网页部分内容的乱码:把乱码部分拷到伟福里,然后用鼠标从乱码的开头开始算的半个字开始拖动,原来的乱码一下就全正常了。原因是网页里的文字是以两字节存储的,由于传输等问题导致正好多了或少了一个字节,则该行全部内容不能正常识别显示。) 4. 在表格部分,keil不允许每行最后一个数据后面有逗号, WAVE可以。 5. 在END结束后面如果有中文字符, keil会乱报错,WAVE则无视之。 [一些经验] 1. WAVE出现"错误 346: ORG 错",并指向ORG 0(一般犯错是在多文件包含模式),说明主文件中在包含ORG 0的语句前出现指令。 2. 不能同时开多个不关联文件调试, 容易调错文件。如果同时打开多个源程序就不能使用“全部编译”功能。 3. 对于超出的数,编译器将超出位(高位)去掉。如果用的是keil,还会看到警告提示。 4. WAVE与keil都不能正确显示所谓1T的STC指令执行时间,自己手算吧。哪位有计算一段指令执行时间的好软件,不妨推荐下。 5. 我自己建立的keil工程编译总是出错,不知道哪里没设置对。我采取从正确的程序里拷*.uv2过来,添加源文件就可以用了。 [提高部分] 为什么有些汇编文件看了头大,主要还是编写没有规范,纯粹代码的堆叠。编程应该统一规范,可借鉴C语言规范的特点。文件开头先写明程序的注释,分几块写口线定义、位定义、寄存器定义、数值定义等,然后是51单片机的中断入口,接着到主程序和主循环,往下为子程序、中断处理程序,最后到表格(如果表格很短也可放到对应子程序下方)。子程序名顶头写,里面每一级判断嵌套都缩进2个空格,算法完成一步可空一行,RET返回也顶头写,这样排版就不会让人想晕。注释应当合适,不要所有指令都写上,子程序的功能、入口、出口要注明,关键语句也加上注释。 将两个及以上变量定义到同一个寄存器属于寄存器地址重复使用,汇编器是不会报错的。用的时候千万小心,只能分时使用,或者当一个用,否则查错会让人抓狂。 有些书上没讲到的补充一下:打JMP等效于LJMP, CALL等效于LCALL,$为跳转到当前语句所在行。A5指令,也就是DB 0A5H这个数据表,51运行时当几个NOP处理,加蜜用。一些指令需配合其它指令才能发挥正确的作用,比如SUBB A,#Num, 该句会把进位/借位C一起计算,如果不需要应该CLR C;再比如MOVC A,@A+DPTR,根据需要CLR A或者把A作为偏移量一起用。 有了以上的认识,我们可以扬长避短,两个软件一起使用!首先确保源文件不要同时被打开,然后是使用两者都支持的语句,将C版的表格用WORD替换成汇编版(见C转汇编部分),最后再用条件编译选择其一汇编器。 一、条件汇编(条件编译) 汇编器(编译器)根据条件是否成立,决定是否对里面的代码进行汇编,不合条件的不参与汇编,被忽视掉。支持ELSEIF,支持嵌套。可用于软件调试过程中直接跳过死循环等。条件是否成立的判断,我测试可用的只有等于,可以等于许多数值。比如先定义: WAVE_Keil equ 1 然后在需要分开不同汇编器的地方加入以下条件汇编: if WAVE_Keil =1 ;包含STC的定义 #include "STCdefine.inc" ;for Keil uv3 compiler else include "STCdefine.inc" ;for WAVE6000 assembler endif 二、include包含文件 汇编的包含文件不同于C语言的,它是源文件的一部分,放到主文件中顺序自然有讲究。它可以在被包含的文件里又包含其它文件(不同汇编器支持的层数不同,不宜多)。要求: (1)后缀不限,但应为ASCII码.(建议用INC后缀) (2)尽量与主文件在同一目录中。 (3)包含文件中不能有END语句。 它有3种用法(依此类推, 换一个目录可由它们复合而成): ⑴在同级目录,最常用,不容易修改错一个文件。 ⑵包含文件在下一级目录中,写为:include"folder\hefanghua.inc" ⑶包含文件在上一级目录中,写为:include "..\hefanghua.inc" 三、汇编宏定义 我只了解皮毛而已,什么macro在WAVE上没能捣腾出来,keil上虽能通过编译,但不知道具体有什么用。 我们可以对数值用另一数值定义,数值可以加减乘除计算,最终结果是固定的数值就行。不过算式不能太复杂,具体由编译器决定(可参考伟福6000使用帮助)。宏定义的好处是可以对改动频繁的数据做快速修改,原本不能位寻址的一些位,可以被拆开分别赋值。举个例子,STC 5A系列的第2串口是新增加的功能,给AUXR赋初值的数据里揉了些串口以外的位,以前专门为串口写的初值计算设置程序又得重写了,这里我们只需用宏定义实现: ;---第2串口的宏定义--- T0x12 equ 0 ;=0: T0为普通12T, =1: T0为1T T1x12 equ 0 ;=0: T1为普通12T, =1: T1为1T UART_M0x6 equ 0 ;=0: UART1为普通12T, =1: UART为6T(6倍) BRTR equ 1 ;=1: 启动独立波特率发生器BRT, =0: 停止BRT S2SMOD equ 1 ;=1: UART2的波特率 x2. (=0: BRT的溢出率/32, =1: 溢出率/16) BRTx12 equ 0 ;=0: BRT为普通12T, =1: BRT为1T EXTRAM equ 0 ;=0: 使用内部扩展的XRAM, =1: 只使用外部数据存储器(XRAM) S1BRS equ 1 ;=1: 用BRT作波特率发生器, =0: UART用T1作波特率发生器 AUXR_Dat equ T0x12*80h +T1x12*40h +UART_M0x6*20h +BRTR*10h +S2SMOD*8 +BRTx12*4 +EXTRAM*2 +S1BRS S2SM equ 1 ;=0: 方式0, 同步移位串行方式, Fosc/12, =1: 方式1, 8位可变波特率, ;=2: 方式2, 9位固定波特率, =3: 方式3, 9位可变波特率 S2SM2 equ 0 ;? S2REN equ 1 ;允许第2串口接收 S2TB8 equ 0 ;方式2、3时为第9位数据位 S2RB8 equ 0 ;方式1时为接收到的停止位 S2TI equ 0 ;第2串口发送完成标志 S2RI equ 0 ;第2串口接收完成标志 S2CON_Dat equ S2SM*40h +S2SM2*20h +S2REN*10h +S2TB8*8 +S2RB8*4 +S2TI*2 +S2RI ;---第2串口的宏定义 by HeFanghua--- AUXR_Dat跟S2CON_Dat就是我们要赋的值,修改串口方式只需改S2CON_Dat上面几个单独的位即可。S2SM可以等于0、1、2、3,正好与方式0~3一一对应。在程序中赋值,用以下语句: MOV S2CON, #S2CON_Dat 简单吧?。 接着举个数据表格宏定义的例子: DB S2CON_Dat*1, AUXR_Dat, (S2CON_Dat + AUXR_Dat)/2 ,00h ;这样都行 DB "Good" ;ASCII码的字符串数据 DW 0D0Ah ;ASCII码的回车符, 大端存储模式 四、跳转范围 比较跳转之类的指令包括CJNE, DJNZ, JB等,这类指令如果编写有错,WAVE会指向65536行(不存在),到了反汇编窗口。可采取从最远的条件跳转开始搜索排错。如果跳转超出范围,则应该给它加一个长跳转。比如JZ rel指令,rel是个- +127的数(偏移量),该数由编译器计算标号的实际位置自动得到。如果JZ指令与标号中间隔了许多代码,导致标号离得太远就会超出范围。 解决办法是在没超出的地方,一般是在JMP语句下面写跳转到的中间标号,然后再JMP到需要跳转之处(JMP的范围是64KB,大于64K的特殊51单片机没玩过,有兴趣可以试下)。如果遇到一段很长又没有JMP的代码,只能用JMP把代码打断一行再放入了。举例: DS 300 ;假设是一段很长的代码 JZ run NOP DS 256 ;假设也是一段很长的代码 run: NOP 打断长代码后改写为: DS 300 JZ run_1 NOP DS 120 jmp code_next1 ;打断出来的空隙 run_1: jmp run code_next1: DS 136 run: NOP 五、C转汇编 8位以上的数据计算会比较麻烦,我们可以找段现成的C代码,用keil反汇编来参考编写。反汇编尽量少用,keil反汇编出来的代码超难理解。转换的步骤是:1.归纳C程序的流程,2.转换简单的部分(寄存器定义等) 3.逐个读懂各子函数,4.参考keil提供的反汇编 5.其它整理、检查、调试工作。其实就是把自己当成编译器编译C的过程,还是少转为妙,费时费力效果不好。有些软件只能生成C的表格(比如Image2Lcd),用WORD替换的速度比别的快, 不过偶尔有几行回车漏掉替换。下面讲下C语言版的表格转汇编版过程。 在WORD里选择:替换->查找内容:(即->高级->特殊字符->段落标记)。然后按以下步骤依次替换内容: 步骤⑴ ,^p 替换为: h^pDB□ 其中□表示空格 步骤⑵ ,0x替换成h,0 步骤⑶ 0x替换成0 步骤⑷ 手动检查下错漏,在步骤⑴时WORD经常漏替换 [打包输出] 其实除了源文件外,一些大些的程序最好有流程图、状态机,方便日后查阅维护。 WAVE的输出除了ASM和inc包含文件之外,还有个Hex文件或者BIN文件。BIN文件与HEX都可烧录,BIN打包后体积更小。 keil编译出来的文件,除了以上几个,最好保留*.uv2工程文件,其它的用不到。Keil也可得到BIN文件,请参考下面的贴《用keil直接生成BIN文件》。 [参考资料] 其他人的相关帖子请参考: <南京伟福仿真器IDE鼠标滚轮外挂> https://www.kechuang.org/t/31254 <用keil直接生成BIN文件> 用keil直接生成BIN文件 1.下载hex2bin到keil的任意目录,下载地址:http://www.keil.com/download/docs/7.asp 或者 http://www.hex2bin.com/files/hex2bin.zip 2.然后"option for target ......"选项里面的output标签,下面有after make框架,选中"Run User Program #1" 。然后填入HEX2BIN.exe所在目录,同时加上生成的HEX文件名(在name of executable里设置的名字),比如“D:\Keil\UV2\HEX2BIN.EXE 12232.hex” 这样编译完成后,会自动产生bin文件。
+2000 科创币 科创网 2011/04/24 原创分享。对本帖内容,版主进行过详细讨论,对于这种商品级系统,希望站在商业应用的角度看待问题。
请详细描述文章存在的问题,明确指出修改的要点。
该操作不影响文章的正常显示,修改建议将通过系统通知发送给文章作者。
提交
加载专业列表中...
已选择的专业:无
{{forum.displayName}}:{{forum.selectedThreadType.name}}
多维分类:
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
编辑
删除
{{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的
200字以内,仅用于支线交流,主线讨论请采用回复功能。