Keil软件配置

一、Keil5 背景主题安装

  keil5背景主题在网上有很多,直接从网上下载,安装方法如下:

  1. 找到安装Keil路径(X:\Keil_v5\UV4);
  2. 在UV4目录下的global.prop文件;
  3. 将网上下载的.prop文件覆盖原有文件,建议覆盖前备份原文件。

当然也可以细点配制出自己想要的风格(我比较懒),详细的配色方法可以参照这位博主:Keil软件配置

二、Configuration配置

  在工具栏中找到小扳手图标或者在菜单栏中打开 Edit-Configuration,大多数功能都在这改。

2.1 缩进和编码设置

  如下图设置将编码格式设置为国标,Tab固定缩进为4格

  1. ASCII编码:一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。
  2. UTF-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。
  3. Unicode编码:一个英文等于两个字节,一个中文(含繁体)等于两个字节。
    符号:英文标点占一个字节,中文标点占两个字节。举例:英文句号“.”占1个字节的大小,中文句号“。”占2个字节的大小。
  4. GBK编码:方式是中文占两个字节,英文占1个字节。

  从上面可知,假如是做嵌入式前端界面时,不要采用我们编程通用的 UTF-8格式,因为它的中文储存字节相对更大。前端界面要储存较多的汉字字库等,因此界面不会采用UTF-8编码格式。

2.2 代码自动补全

  进入Text Completion,勾选如下图并填入你需要在输入第几个字符后开启补全提示。

2.3 快捷键的设置

  查询某句代码时候,往往会使用ctrl+F跳到Find选项进行查询,如下图所示

Look in:有两个选项:
  1)Current Document 只查询当前文档
  2)Current Project 查询整个工程
Find选项,查询到的时候,是要一直点击next查看下一个的;而Find in Files则是可以在下面列出一个所有能查询到的列表,实际上更常用的是这个(每次都要动下鼠标改成Find in Files)。

因此,在Configuration找到Shortcut Keys选项

1)将Edit:Find快捷键去掉,将Edit:Find in Files快捷键补上ctrl+F
2)顺便加一下注释的快捷键 Edit:Advanced :Comment SelectionEdit:Advanced :Uncomment Selectionctrl+shift+ c|v(个人喜好);
3)顺便将Edit:Advanceed:Go toDefinition of current Word设置为ctrl+d,这样后面进入具体参数位置就ctrl+dF12都可以用。

2.4 快速浏览 .c文件的函数位置

  先在view选项把基本没用的booksTemplates功能给隐藏掉。如下图所示

然后进入在Configuration找到Scan funtion names in project files 给关掉

关掉它有什么好处呢?我们可以在Project旁边的{}Functions只会显示你在右边的框打开的.c文件,然后 你就可以.c文件打开查看函数,假如没有关掉它的话,它会把项目所有的 .c和.h文件都放出来,到时候别说找函数了,你可能连 .c文件都找不到。

三、Options for Target配置

  这里讲下Options for Target配置里面需要注意的内容

3.1 Target选项

  Target界面主要分为两块

3.1.1 FPU浮点处理器

  基于Cortex-m4(例如:STM32F407)最大的特色就是加入了一个FPU浮点处理器,能支持DSP运算。更高版本的甚至能够支持double类型处理(例如:STMH7)。

  如果只是写裸机程序的话,就无需在意;
  假如是写实时操作系统(例如UCOSIII)需要注意的是:UCOS III官方的移植版本竟然不支持FPU浮点运算;如果在MDK的设置选项中,使能FPU, 运行的时候会出现奇怪的错误,有时候直接跑飞(例如:程序如果进行打印浮点型数据就会进入硬件错误;甚至有时候程序量大的时候,一编译,你根本不知道bug在哪?而且还会报错)。逐步调试会发现:只要运行打印浮点数就会程序跳转到硬件fault;
1)可能是字节对齐问题,修改字节对齐即可解决问题;
2)或者你移植的RTOS本来就不支持,需要修改底层配置函数;
解决方法:ucosii中调用Printf打印浮点型数据就进入硬件错误,STM32F4
  个人建议:移植UcosIII的时候,程序运行暂时先不启用FPU,等到程序跑得稳定、需要优化的时候,再启用FPU,明确不是原有程序版本带有的bug。

3.1.2 IROM

  如果不涉及bootloader在线升级的情况下,采用一般的例程的配置IROM即可;倘若涉及到,可详细看这篇博文:STM32开发

3.2 Output

Browse Information选项是可以查看函数具体内容和位置;但是这里有点经验,就是当你编译类似stm32H7系列那种大容量RAM的芯片的时候,往往它自带的库也是很大,里面有很多函数要编译;当你编译工程的时候,那速度你会怀疑人生,这个时候你可以关闭这个选项,可以大大减少你需要的编译时间,但是缺点是不能跳转函数,可以用ctrl+F替代找到你要的函数位置。

Create HEX File选项,是生成hex文件
  烧录程序方式分为两种:
1) .bin文件进行烧录
2) .hex文件进行烧录
我们常用的串口、J-link(SW模式,直接在项目工程)烧录程序进芯片,均是采用hex文件;.bin文件只会在脱机烧录和在线升级的时候才会用到。

更多相关.bin文件和.hex文件知识,可详细看这篇博文的bootloader章节:STM32开发

3.3 User

  这里是运行keil脚本的地方,是要在编译前调用执行脚本,还是编译后调用执行脚本。如 *3.2 Output *所示,Output选项中只有生成.hex文件,没有生成.bin文件的选项;一般情况下,就有人在 编译后选项 里调用keil自带的脚本fromelf.exe,用于生成.bin文件。
  由于每个人的电脑的Keil安装路径不同,因此别人安装的脚本位置也就不同;有时候你编译别人的代码,会出现非代码的Error:显示你找不到对应路径的fromelf.exe;这个就是找(错)不到脚本位置而报错,这个时候可以将上图红色地方选项,勾选给取消掉就可以用了,当需要对应的bin文件再进行更改具体路径即可。

3.4 C/C++

3.4.1 芯片库选择

Stm32芯片型号移植的时候,最重要的就是这个位置;在这里举例一下F10x系列

  至于要使用哪个宏,则需要根据具体的芯片来进行选择。如果是STM32F105xx和STM32F107xx,是Connectivity Line Devices,则宏定义选择的是STM32F10X_CL;如果是别的型号,则根据FLASH的容量来进行选择。可能文字写的有点不太清楚,还是以表格来说明:

  宏定义更换的时候,也好同时把启动文件给换掉,例如:startup_stm32f10x_hd.s修改为startup_stm32f10x_md.s
Ps:其实到这里基本移植完了,不过有时候会出现程序跑的非常慢,有些工程在汇编底层启动文件调用Systeminit();再跳转到main(),有些则无配置时钟树,这个时候在系统初始化时调用 SystemInit();,后面就正常了

3.4.2 优化等级

  在上图所示,中间有一个Optimization选项,是对程序优化的等级;一般我们调试的时候,采用最低的Level 0,因为如果我们进行仿真调试,优化等级太高,程序无法跳转运行到设置的断点;当程序调试稳定后,再根据需求提高其代码优化等级即可。

四、技巧用法

  这里讲一些自己在用的实用小技巧

4.1 仿真精确测量代码运行时间

  为什么需要精确测量代码运行时间?其实往往之所以需要其精确的运行时间,主要分为两种情况:

  1. 上电初始化,某些芯片模块本身的器件性质,导致MCU不能上电立马 初始化(通信进行软件配置)该芯片;根据初始化函数放的位置,MCU初始化的指令执行够快,上电快速与其芯片立马通讯后,导致会出现不可预知且随机的bug;并且这种bug是隐性的,如果你其他的功能所需的初始化时间够长,这个bug就会(偶然)消失掉。因此需要测出时间,并在该芯片初始化通讯前增加延时(死循环)
  2. 需要知道整个程序循环一遍需要多长时间。往往串口通讯、开关扫描、AD采样等的数据处理往往是通过 轮询 的方式实现的。例如,AD采样频率是 960次/秒 ,如果你的程序的循环次数 达不到至少(冗余) 1000次/秒 ,那么就算是使用 ADC采样(外部)中断 及时获取到数据,但是由于程序循环速度太慢,AD采样数据无法及时进行处理换算,实际上 AD采样频率 < 程序循环次数 < 960次/秒 。因此 程序循环所需时间大小,也决定了轮询处理响应速度的慢快。

Ps:获取数据的方式有两种:轮询 和 中断 。一般情况下,最好是使用中断方式,能够及时获取到数据;采用轮询方式来获取数据,当没有数据来临时,也会进入轮询。当你的程序量比较少的时候,你的程序循环速度会很快,这样的话,轮询将会占用较多的CPU(内存)资源,而中断如果不触发,则不会进入,单位时间内程序循环将会相对来讲会优化一些。

  实际上有很多种方法可以实现测量运行时间

4.1.1 采用Keil仿真的 Trace 功能

  首先要先配置好仿真的时钟:在Target进入Debug,然后设置成J-link(或者ST-link,大同小异),进入setting,再选择Trace选项

SW模式:先勾选Enable,调成对应时钟(例:72MHz),再使能Autodetect max SWO Clk
JTAG模式(不常用):设置时钟,然后不勾选Enable(JTAG不支持Trace,会报错,容易出现SW切换JTAG时忘记关掉Trace

仿真的时候找下有个时间窗口

上面两个是复位“t1”和“t2”的,下面3个是选择在状态栏上显示哪个时间。

t0”表示程序开始运行到现在的时间,是不能复位的。另外两个可以随便复位,就可以用来测具体某一个函数或某一行程序的运行时间。

  具体操作为:在要测试的代码前加一个断点,当程序运行到目标行时会停下,然后复位“t1”或“t2”,并在下一行代码前加断点,然后继续运行程序,程序会停在下一行代码前,这个时候“t1”的值就是目标行程序的运行时间。

Ps:Keil仿真 全速运行时 观察窗口变量没刷新;解决方法:在仿真时点击工具栏里的view选择下面的periodict window update,勾选完后数据开始动态更新。

Ps:Cortex-M0不支持Trace功能,因为是ARM V6结构,比较旧,所以无论你用J-link,还是ST-Link,都不能用到Trace。Keil会提示TRACE HW not present

4.1.2 采用定时器计时

  配置好一个定时器,具体计算配置操作可以看STM32开发
思路:获取 进入程序段的当前时间,退出程序段后再获取当前时间,两个时间之差就是其运行时间(* 定时器计时基数)。

4.2 程序跑飞跳转

  有时候你会在工程看到这段汇编的函数.

1
2
3
4
5
6
7
8
9
__asm void wait()
{
  BX lr
}
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  wait();
}

  HardFault_Handler栈溢出检查机制,适用于所有CM3芯片,造成主栈(MSP)溢出的原因有很多,如过多的定义局部变量,递归调用,中断嵌套等都有可能会导致主栈溢出,stm32不具备MPU,没有对内存进行保护的硬件机制,而软件检测栈溢出又有其局限性。

STM32出现HardFault_Handler故障的原因主要有两个方面:

  1. 内存溢出或者访问越界。这个需要自己写程序的时候规范代码,遇到了需要慢慢排查。
  2. 堆栈溢出。增加堆栈的大小。大多数是因为中断嵌套寄存器均是32位,且STM32是小端模式(参考Cortex-M3权威)

1)出现问题时排查的方法:DEBUG,下断点单步看程序停在哪
2)另一种方法:默认的HardFault_Handler处理方法为:内部是一个 汇编 或者 C语言 形式的死循环;
将它改成如上面代码的 BX LR直接返回的形式。然后在这条语句打个断点,一旦在断点中停下来,说明出错了,然后再返回,就可以找到程序跑飞出错的位置的语句在哪。

4.3 自动生成版本号(编译时间和编译日期)

  经常都需要手动添加版本号或者生成时间会很繁琐。这个时候,C语言中的两个宏__DATE____TIME__可以帮到我们。
__DATE__用于获取系统日期,而__TIME__用于获取系统时间,我们可以根据该两个宏获取到的信息将其保存于程序变量中,在程序运行过程中直接调用。

我们在程序中可以按以下所示使用:

1
2
3
4
const  unsigned char cRevisionDate[12] = __DATE__;
const unsigned char cRevisionTime[16] = __TIME__;

printf("Rev Info: %s %s\r\n", cRevisionDate, cRevisionTime);

运行结果如下所示:

1
Rev Info: Sep  8 2018 17 51 26

更复杂的使用方法可以看这篇:Keil版本号生成

4.4 仿真动态显示

  点击仿真后,如果Watch窗口数据不能动态显示,可在仿真状态下点击tool栏的view,观察periodict window update是否勾选,确保勾选即可。此时数据动态更新。
Ps:退出仿真状态下,工具栏的view没有periodict window update选项。

4.5 如何上传github

  首先新建一个批处理,用于清除掉keil工程的编译文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
::删除Keil编译产生的一些垃圾文件
::删除Code Warrior编译产生的一些垃圾文件
del *.bak /s
del *.ddk /s
del *.edk /s
del *.lst /s
del *.lnp /s
del *.mpf /s
del *.mpj /s
del *.obj /s
del *.omf /s
::del *.opt /s ::不允许删除JTAG的设置
del *.plg /s
del *.rpt /s
del *.tmp /s
del *.__i /s
del *.crf /s
del *.o /s
del *.d /s
del *.axf /s
del *.tra /s
del *.dep /s
del JLinkLog.txt /s
del *.iex /s
del *.htm /s
del *.sct /s
del *.map /s
del *._2i /s
del *.L2P /s
del *.FED /s

del *.elf /s
del *.args /s
del *.mk /s
del *.local /s

exit

  具体的批处理操作解读,可以看另外一篇文章Window的简易bat处理

4.6 搭配推荐

  推荐一些自己在用的实用搭配

4.6.1 Astyle

  Astyle是keil的一个插件,关于Astyle看另外一篇博客:Keil格式化工具_Astyle

4.6.2 Snipatse

  Snipatse是一个超级方便的截图软件

4.6.3 Compare

  Compare是一个比较代码的软件,特别好用。你可以比较现在版本和之前版本的区别;或者是你的版本和别人的版本,能很快找到差别

-------------本文结束感谢您的阅读-------------