【工具使用】Keil工具的使用——常用配置介绍

Keil调试具体教程学习

目录

​​​​​​​Keil调试具体教程学习

常用功能总结

(2)目标设置(Target)

①设置晶振频率

②跨模块优化选项

③微库选项

(3)输出设置(Output)

①输出文件路径和输入文件名称

②调试信息——Debug Infomation

③生成.Hex可执行文件——Create HEX File

④浏览信息——Browse Infomation

⑤生成.Lib封装库文件——Create Library

⑥生成.bat编译执行脚本——Create Batch File

(4)生成列表设置(Listing)

红框中:生成Map文件

(5)用户选项(User)

(6)C/C++设置(C/C++)

①预处理符号——Preprocessor Symbols

②语言/代码规则设置

(9)调试设置配置(Debug)

①在线仿真

②离线仿真


Keil调试具体教程学习

常用功能总结

(2)目标设置(Target)

①设置晶振频率

        在Xtal(MHz)后面可以填写当前使用的开发板上芯片系统使用的晶振频率,一般STM32开发板上的晶振都是8Mhz。这个只会在仿真调试中使用,如果直接用 ST-Link仿真器在开发板上在线调试,这个可以不用管。

②跨模块优化选项

        勾选 "Use Cross-Module Optimization" 选择跨模块优化,此选项可在编译链接后对文件链接再进一步进行优化,从而减少一些开销。选择此功能时,可能会导致编译时间变长,但同样的可以使得编译后所使用的空间减少,但一般不勾选。

③微库选项

        勾选 "Use MicroLIB" 可选择使用标准缺省库,勾选这个会导致很多库函数用不了,但换来的是节省了大量的空间。这个跟串口使用 printf 函数有关联,但一般不勾选。

(3)输出设置(Output)

①输出文件路径和输入文件名称

        在 "Select Folder for Objects" 里可以设置输出文件的路径,一般保存在我们创建的OBJ文件夹下;在 "Name of Executable" 后面可以设置输出的文件名。这个输出文件路径和文件名也是Keil工程烧录和调试获取文件的依据。

        比如这里输出路径设置为 /OBJ,文件名为Template,那烧录时,Keil会去查找当前工程路径下 /OBJ 路径下是否存在 Template.axf 这个文件,有就烧录,没有就报错。如果要使用.Hex文件烧录,则文件名这里填写TestPro.Hex。

        如果使用 ST-Link 仿真器下载调试,若勾选 Create HEX File ,点击Download默认烧录的是.Hex文件,无法进入在线调试;若不勾选 Create HEX File ,点击Download烧录的是.axf文件,是可以进入在线调试。

注:调试只能使用.axf文件,因为.Hex文件不带调试信息,另外若调试结束,点击关闭调试时会出现直接关闭工程文件,是因为你的工程文件包含中文,都改成英文就不会出现此问题。

②调试信息——Debug Infomation

        勾选 "Debug Infomation" 可以选择是否生成调试信息,注意去掉此勾选项时,无法打断点调试。一般勾选。

③生成.Hex可执行文件——Create HEX File

        勾选 "Create HEX File" 即可在编译后生成.hex文件。根据上述自己的需求,点击是否勾选。

④浏览信息——Browse Infomation

        勾选 "Browse Infomation" 可以选择是否生成浏览信息,有这个浏览信息时,可以在Keil里索引函数或变量的定义,调用等,没有这个信息就无法把这些信息关联起来。如果不用Keil作为代码编辑器的小伙伴,去掉这个勾选项,可以减少编译的时间。一般勾选。

⑤生成.Lib封装库文件——Create Library

        当需要封装模块或打包 SDK 包时,可以勾选 "Create Library" 这个选项,该选项与"Create Executable"互斥,选择生成.lib文件而不是完整的可执行.axf文件。这种一般是用于提供二次开发的软件包使用。一般不勾选。

⑥生成.bat编译执行脚本——Create Batch File

        勾选 "Create Batch File" 即可在编译后生成.bat的编译执行脚本,即可以不用打开Keil工程,只需要执行编译执行脚本即可编译工程软件。

(4)生成列表设置(Listing)

红框中:生成Map文件

  • Linker Listing: .\Listings\TestPro.map:主要是用来生成代码详细信息的map文件,用于后面的代码分析。这里面有选项建议全部勾选上。
  • Memory Map:包含一个内存映射,其中包含镜像中每个加载区,执行区和输入节的地址和大小,包括调试和链接器生成的输入节。
  • Callgraph:以HTML格式创建函数的静态调用图文件。调用图给出了镜像中所有函数的定义和参考信息。
  • Symbols:列出本地,全局和链接器生成的符号以及符号值。
  • Cross Reference:列出输入节之间的所有交叉引用。
  • Size Info:给出镜像中每个输入对象和库成员的代码和数据(RO数据,RW数据,ZI数据和调试数据)大小的列表。
  • Totals Info:提供输入对象和库的代码和数据(RO数据,RW数据,ZI数据和调试数据)大小的总和。
  • Unused Sections Info:列出从镜像中删除的所有未使用的部分。
  • Veneers Info:提供链接器生成的Thumb/ARM胶合代码的详细信息。

        Map文件主要用于查看你的代码所占空间的大小,如果你用到芯片内部的Flash的话,就需要查看你从哪里开始擦写Flash。

(5)用户选项(User)

Beep When Complete:编译完成发出声音。勾选时在编译完成时会响一下。

(6)C/C++设置(C/C++)

①预处理符号——Preprocessor Symbols

Define:用于做一些工程全局宏定义

注:在这里修改宏定义时,需要 全编译 才可生效,局部编译是不生效的

②语言/代码规则设置


Optimization:优化等级,这个会比较常用,当项目工程较大,对芯片空间比较吃紧时,可以考虑提升优化等级。ST的芯片这里有0~3,4个等级可选。

-O0应用最小优化大多数优化都被关闭,生成的代码具有最佳的调试视图。
-O1应用受限优化例如,删除未使用的内联函数和未使用的静态函数。在这个优化级别,编译器还应用自动优化,例如删除冗余代码和重新排序指令以避免互锁情况。生成的代码经过合理优化,具有良好的调试视图。
-O2应用高优化(这是默认设置)在此级别应用的优化利用了ARM对处理器体系结构的深入了解,利用给定目标的特定于处理器的行为。它生成优化良好的代码,但有限调试视图。
-O3应用最积极的优化优化符合用户的-Ospace / -Otime选择。默认情况下,多文件编译时启用,这会导致更长的编译时间,但会提供最高级别的优化。

        目前就使用经验来看,优化等级2节省的空间最多,具体原理还没去细究。

注:提升优化等级后,对代码的规范严格度提升,调试的友好程度会降低,请适当使用。

One ELF Section per Function:优化每一段函数ELF段(建议都勾选);每个函数都会产生一个ELF段,勾选该功能允许优化每个ELF,可以减少潜在的共享地址、数据和函数之间的字符串;直白说就是可以减少代码量ROM的大小(内存RAM不会减少),一般勾选。

Strict ANSI C:标准(严格)的ANSI C;即编译时严格按照标准的ANSI C进行检查。为了养成良好的编程习惯,写出更具移植性的代码,建议勾选。

Warnings(建议All Warnings):No Warning:不会有警告提示和输出;All Warnings:所有警告提示和输出。建议选All Warnings,很多告警都不是空穴来风,检查下好点。

C99 Mode(看情况选择):C99模式,勾选选择启用C99标准,如不勾选,则按C89标准来。为了高移植性,不建议勾选。

(9)调试设置配置(Debug)

通过单选 "Use Simulator" 和 "Use XXX" 选择是用模拟仿真还是在线仿真 

①在线仿真

Use ST-Link Debugger:选择烧录器类型,根据自己手头的烧录器,选择对应的品牌

Load Application at Startup:启动位置设置,从启动文件开始加载。不勾选时,在进入调试时,不会重新从启动开始执行,但不勾选时,需要手动添加 .ini 文件,把 .axf 的调试信息放到 Keil 里,不然进入调试时无法打断点,也无法追踪到当前程序位置。这点在网上查 “如何不复位进入调试”很多会提到这个勾选项,但很少有提及这个.ini的事情,有也是一带而过。

Initlalization File:初始化文件,承接上文,只要新建一个XXX.ini文件(文件名随意),点击…按钮,添加该文件,点旁边的 "Edit" 按钮,在文件中添加 “LOAD %L INCREMENTAL” 这一句即可。

Run to main():跑进main函数,进入调试后,会在main里停止,相当于是在main的第一行打了第一个断点。如果不勾选时,一进入调试就全速跑。

Restore Debug Session Settings:复位调试会话设置,使用上一次调试过程对Breakpoints,Watchpoints,Memory Display和Toolbox(如果这些项被选中的话)。

  • Breakpoints:断点
  • Watch Windows:变量调试窗口
  • Memory Display:查看内存的窗口
  • Toolbox:工具栏
  • System Viewer:系统视图

Driver DLL: 驱动动态库文件,后面Parameter是其对应参数。
Dialog DLL:会话框动态库文件,后面Parameter是其对应参数。

Parameter 均为:-pSTM32F103ZE,用于设置支持 STM32F103ZE 的软硬件仿真(即可以通过 Peripherals 选择对应外设的对话框观察仿真结果)。最后点击 OK,完成设置。
这些是仿真的时候需要用到的动态库,一般不用修改,使用默认值就行,这些动态库在Keil的安装路径下了可以找得到。

点击进入Settings——Trace追踪选项栏:

Core Clock:核心时钟频率。设置跟当前板子相同的时钟频率,可以在调试时按实际运行时间进行追踪调试。或者在设置晶振频率处 Xtal(MHz)输入与开发板上的晶振相同的频率。否则调试的时间是不对的。

Flash Download下载选项栏:

1.下载动作设置(Download Function)

Erase Full Chip:擦除整片
Erase Sectors:擦除部分
Do not Erase:不擦除
        勾选Erase Full Chip时,每次下载时,都会对整片Flash进行擦除操作。勾选Erase Sectors时,下载时只会擦除使用到的扇区。勾选Do not Erase时,则下载时不擦除原本代码。
Program:烧录
Verify:校验
Reset and Run:复位并运行
        勾选Program时,下载时才会把代码写入Flash,否则不写入。勾选Verify时,则在烧录代码后,对代码进行校验。某些场合下不能检验,比如代码段跟数据段分开下载,代码里不包含数据部分,而工程里配置的代码段又包含数据段时,此时如果进行校验,可能会因为数据内容不一致导致校验失败。勾选Reset and Run时,则在下载完成后立即复位运行代码,不勾选时则需要手动复位运行。

2.烧录算法(RAM for Algorithm)

        RAM for Algorithm:给烧录算法的 RAM 空间,Start 和 Size 分别设置对应 Ram 空间的起始地址和大小,这个一般选择完芯片后按默认就行,不用修改,如果有需要直接烧写的片外Flash的,可能需要自己写烧写算法的,此时就需要关注这个Ram空间是否容得下自己编写的烧录算法大小,需要做适当的调整。 

3.Programming Algorithm

        Programming Algorithm:烧录算法选择,一般选择完芯片后,这里都会自动选择对应的烧录算法,如果不显示则需要手动添加,不然会导致烧录失败。如果是使用国产芯片,也需要手动添加烧录算法。添加方式很简单,把对应的算法文件(后缀是FLM)放到Keil安装根目录Keil_v5/ARM/Flash路径下,点Add按钮,选择对应的文件即可。

        如果选择好芯片型号,这里自动会更新与之相匹配的烧录算法,比如芯片选择STM32F103ZET6这里有512k的选择,若是选择STM32F103C8T6这里会有128K的选择,该文件是在Keil安装目录底下找不到的,都在芯片包里。

②离线仿真

        基本设置跟在线是一样的,多了一个 "Limit Speed to Real-Time" 的选项,意思是把速度限制到实际时间。但Keil怎么知道实际速度是怎么样的呢?所以这里还需要设置一个运行频率,即前文说到,在 Target 里有个频率设置。勾选此选项后,在离线仿真时,代码执行速度就是按设定的运行频率来跑,接近实际板子的速度。如果不勾选,那就直接起飞了(按电脑频率来跑,有多快跑多快)。

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Keil MDK中使用树可以通过定义树节点结构体和使用指针来实现。下面是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义树节点结构体 typedef struct node { int data; struct node *left; struct node *right; } TreeNode; // 创建节点 TreeNode* create_node(int data) { TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->data = data; node->left = NULL; node->right = NULL; return node; } // 插入节点 TreeNode* insert_node(TreeNode* root, int data) { if (root == NULL) { return create_node(data); } if (data < root->data) { root->left = insert_node(root->left, data); } else { root->right = insert_node(root->right, data); } return root; } // 计算树的深度 int tree_depth(TreeNode* root) { if (root == NULL) { return 0; } int left_depth = tree_depth(root->left); int right_depth = tree_depth(root->right); return (left_depth > right_depth ? left_depth : right_depth) + 1; } int main() { // 创建根节点 TreeNode* root = create_node(5); // 插入节点 root = insert_node(root, 3); root = insert_node(root, 7); root = insert_node(root, 1); root = insert_node(root, 4); root = insert_node(root, 6); root = insert_node(root, 8); // 计算树的深度并输出 int depth = tree_depth(root); printf("Tree Depth: %d\n", depth); return 0; } ``` 在这个示例代码中,我们首先定义了一个树节点结构体,包含了节点数据和左右子节点指针。然后我们定义了创建节点和插入节点的函数,使用递归的方式实现。最后我们定义了计算树深度的函数,并在main函数中使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值