Keil的代码优化产生的问题

本文针对KeilC51编译器对同一端口连续读取时可能出现的问题,提供了三种解决方案,包括调整编译优化级别、使用volatile关键字及硬件修改等方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

阅 读了《单片机与嵌入式系统应用》2005年第10期杂志《经验交流》栏目的一篇文章《Keil C5l对同一端口的连续读取方法》(原文)后,笔者认为该文并未就此问题进行深入准确的分析。文章中提到的两种解决方法并不直接和简单。笔者认为这并非是 Keil C51中不能处理对一个端口进行连续读写的问题,而是对Keil C51的使用不够熟悉和设计不够细致的问题,因此特撰写本文。

本文中对原文提到的问题,提出了三种不同于原文的解决方法。每种方法都比原文中提到的方法更直接和简单,设计也更规范。(无意批评,请原文作者见谅)

1 问题回顾和分析

原文中提到:在实际工作中遇到对同一端口反复连续读取,Keil C5l编译并未达到预期的结果。原文作者对C编译出来的汇编程序进行分析发现,对同一端口的第二次读取语句并未被编译。但可惜原文作者并未分析没有被编译 的原因,而是匆忙地采用一些不太规范的方法试验出了两种解决办法。

对此问题,翻阅Keil C51的手册很容易发现:KellC51的编译器有一个优化设置,不同的优化设置,会产生不同的编译结果。一般情况缺省编译优化设置被设定为8级优化,实际最高可设定为9级优化:

①Dead code elimination。

②Data overlaymg。

③Peephole optimization。

④Register variables。

⑤Common subexpression elimination。

⑥Loop rotation。

⑦Extended Index Access 0ptimizing。

⑧Reuse Common。Entry Code。

⑨Common Block Subroutines。

而以上的问题,正是由于KeiI C5l编译优化产生的。因为在原文程序中将外设地址直接按如下定义:

unsigned char xdata MAXl97_at_Ox8000;

采用_at_将变量MAXl97定义到外部扩展RAM指定地址Ox8OOO。因此,Keil C51优化编译理所当然认为重复读第二次是没有用的,直接用第一次读取的结果就可以了,因此编译器跳过了第二条读取语句。至此,问题就一目了然了。

2 解决方法

由以上分析很容易就能提出很好的解决办法。

2.1 最简单最直接的办法

程序一点都不用修改,将Keil C5l的编译优化选择设置为0(不优化)就可以了。

选择project窗口的Target,然后打开“Options forTarget”设置对话框,选择“C5l”选项卡,将“Code Optimiztaion”中的“Level”选择为“0:Costant folding”。再次编译后,大家会发现编译结果为:

CLR MAXHBEN

MOV DPTR,#M.AXl97

MOVX A,@DPTR

MOV R7.A

MOV down8.R7

SETB MAXHBEN

MOV DPTR,#MAXl97

MOVX A,@DPTR

MOV R7.A

MOV uD4.R7

两次读取操作都被编译出来了。

2.2 最好的方法

告诉Keil C51,这个地址不是一般的扩展RAM,而是连接的设备,具有“挥发”特性,每次读取都是有意义的。

可以修改变量定义,增加“volatile”关键字说明其特征:

unsigned char volatile xdata MAXl97_at_Ox8000;

也可以在程序中包含系统头文件:“#incIude<ab—sacc.h>”,然后在程序中修改变量,定义为直接地址:

#defme MAXl97 XBYTE[Ox8000]

这样,。Keil C51的设置仍然可以保留高级优化,且编译结果中,同样两次读取并不会被优化跳过。

2.3 硬件解决方法

原文中将MAXl97的数据直接连接到数据总线,而对地址总线并未使用,采用一根端口线选择操作高低字节。很简单的修改方法就是使用一根地址线选择操作高 低字节即可。比如:将P2.0(A8)连接到原来P1.O连接的HBEN脚(MAXl97的5脚),在程序中分别定义高低字节的操作地址:

unsigned char volatile xdata MAXl97_L_aI_Ox8000;

unsigned char volatile xdata MAXl97 H at 0.x8100;

将原来的程序:

MAXHBEN=O; //读取低8位

down8=MAXl97:

MAXHBEN=1; //读取高4位

up4=MAXl97:

改为以下两句即可:

down8=MAXl97_L; //读取低8位

up4=MAXl97_H; //读取高4位

3 小结

Keil C51经过长期考验和改进以及大量开发人员的实际使用,已经克服了绝大多数的问题,并且其编译效率也非常高。对于一般的使用,很难再发现什么问题。笔者曾 经粗略研究过一下Keil C51优化编译的结果,非常佩服Keil C51设计者的智慧,一些C程序编译产生的汇编代码,甚至比一般程序员直接用汇编编写的代码还要优秀和简练。通过研读KeilC51编译产生的汇编代码, 对提高汇编语言编写程序的水平都是很有帮助的。

由本文中的问题可以看出:在设计中遇到问题时,一定不要被表面现象蒙蔽,不要急于解决。应该认真分析,找出问题的原因,这样才能从根本上彻底解决问题。上不会出现不必要的干扰,防止了数据不一致的发生。

<think>好的,用户想了解Keil代码优化等级。首先,我需要回忆一下Keil MDK-ARM的相关知识,尤其是编译器优化选项部分。Keil使用的是ARM Compiler,同版本可能有些差异,但优化等级通常类似。 用户可能是在开发嵌入式系统,遇到了性能或代码大小的问题,想通过调整优化等级来改善。他们可能太清楚各个等级的具体区别,或者担心优化带来的副作用,比如调试困难或代码行为变化。 接下来,我需要整理优化等级的分类。通常,Keil优化选项有多个级别,比如-O0到-O3,还有-Os(优化大小)。每个等级的作用需要明确说明,比如-O0是优化,用于调试;-O3是最高优化,可能影响编译时间和代码可读性。 还要考虑用户可能的误解,比如认为更高优化一定更好,但实际上需要权衡速度和空间。此外,特殊优化选项如-Otime和-Ospace的区别,以及它们如何影响代码生成。 另外,用户可能需要知道如何设置这些选项,在Keil的IDE中如何操作,虽然问题没直接问,但简要提及会更有帮助。同时,提醒他们优化可能带来的问题,比如某些代码被优化掉导致功能异常,特别是在中断和硬件操作时需要注意volatile变量。 最后,结构要清晰,分点说明每个优化等级,加上注意事项和总结,确保用户能逐步理解并根据需求选择合适的等级。</think>Keil代码优化等级是编译器在生成机器码时对代码进行优化的强度设置。合理选择优化等级可以显著影响代码的执行效率、内存占用和调试体验。以下是逐步介绍: ### 一、优化等级分类(以ARM Compiler为例) 1. **-O0(无优化)** $$ \text{代码保持原始结构} $$ - 完全禁用优化 - 保留所有调试信息 - 生成代码体积最大,执行速度最慢 - 适用于调试阶段 2. **-O1(基础优化)** $$ \text{优化目标} = \text{平衡代码大小和执行速度} $$ - 删除未使用的代码段 - 简化基础运算 - 保持较好的可调试性 3. **-O2(中级优化)** $$ \text{优化强度} \propto \text{代码重构程度} $$ - 进行循环展开(Loop unrolling) - 函数内联(Function inlining)优化 - 代码执行速度显著提升 - 可能影响变量观察 4. **-O3(最高级优化)** $$ \text{极限优化} = f(\text{执行速度}, \text{代码体积}) $$ - 启用所有优化策略 - 可能改变代码执行顺序 - 最适合发布最终版本 - 可能引入难以追踪的BUG 5. **-Os(空间优化)** $$ \min(\text{代码体积}) $$ - 优先减少代码体积 - 适用于存储空间受限的设备 ### 二、特殊优化选项 - **-Otime**:以速度为优先优化目标 $$ \min(t_{\text{execution}}) $$ - **-Ospace**:以空间为优先优化目标 $$ \min(M_{\text{memory}}) $$ ### 三、设置方法 在Keil IDE中: ``` Project -> Options for Target -> C/C++ -> Optimization Level ``` ### 四、注意事项 1. 调试阶段建议使用-O0,避免优化干扰断点定位 2. 关键硬件操作代码需使用`volatile`关键字,防止被优化 3. 同等级生成的机器码可能产生时序差异(特别是中断服务程序) 4. 最高优化可能导致某些代码被意外删除 ### 五、选择建议 $$ \text{优化策略} = \begin{cases} \text{-O0} & \text{调试阶段} \\ \text{-O2/-O3} & \text{量产版本} \\ \text{-Os} & \text{存储空间紧张场景} \end{cases} $$ 实际应用中建议通过性能测试(Profiling)确定最佳优化等级,在STM32等MCU开发中,-O2通常是性价比最高的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值