目录
编译工程
工程项目中有很多文件,简单的分为3类:工程文件、源文件、目标文件
工程文件就是Keil软件工作需要的文件,和我们写程序没关系
源文件就是我们写的源代码,就是我们编程编出来的
目标文件是Keil中的编译器等工具把我们源文件编译后生成的文件,最终向单片机中烧录时需要目标文件来烧录进去。
我们工程刚创建好(空工程)时只有工程文件,此时我们要去编写添加源代码,代码写好后就有了工程文件和源文件,此时点编译操作就可以得到目标文件。更多文件类型介绍详见:Keil系列教程10_文件类型及相关描述 | EmbeddedDevelop
编译的时候有可能会报错(Errors)和报警告(Warnnings),错误就是有很严重的问题,此时编译无效并不能生成最终需要的可烧录的程序文件,必须去排除错误重新编译才可以;警告是轻微问题,有时候可以忽略有时候不行,具体要凭经验。建议编译时直接点快捷图标栏里面的Rebuild进行编译。
注意:keil中找不到STC系列的51单片机,所以通常选择AT系列的51单片机,二者是兼容的,不过也可以看出国外软件对国内单片机的不友好。
Keil在打开或者新建一个新工程时,最好先点击关闭当前的工程。
如果不想要当前的工程,那么直接将所在文件夹全部删除即可。
调试
使用keil时,发现一个问题,在基础学习时,都是用printf来查看输出,用以判断程序结果是否正确。但是到了keil中,没有输出界面,不能通过输出语句来查看变量。
那么,怎么知道自己的程序对不对呢?
调试基础知识
箭头和断点:
蓝色箭头表示光标所在的行(只在有程序指令的行范围内);
黄色箭头表示当前正在执行的行;
红色表示断点,只有高亮显示的块内是可以打断点的,在非高亮显示行打不了断点,比如变量定义的行就不能打断点。
已经运行过的代码行,显示为绿色,还没有执行的代码行,显示为灰色。
仿真器和调试器
为了方便地调试程序,我们往往会使用仿真器或者调试器。
在keil中,可以使用调试功能来调试程序,但是,也只能通过keil平台来调程序,无法实际看到开发板上的现象。像这样的调试,叫做仿真调试。
那什么是调试器(一般统称为仿真器)呢?
我们把程序烧录到开发板中的时候,看到的就是最终结果。那么,我怎么能让已经烧录到开发板中的程序可以一步一步地走呢?这样的调试,再结合keil中的正确配置,就可以让开发板中的程序一步一步地走,还能看到实际的现象。
这就是调试器起到的作用。
为了方便嵌入式调试,就定义了一种JTAG接口,是一种国际标准测试协议(IEEE 1149.1兼容),主要用于芯片内部测试。现在多数的高级器件都支持JTAG协议。标准的JTAG接口是4线:TMS、TCK、TDI、TDO,分别为模式选择、时钟、数据输入和数据输出线。
只要器件支持JTAG,就可以使用该接口来调试嵌入式程序。
STM32就提供了JTAG接口。
参考:什么是JTAG?_贾167的博客-CSDN博客_jtag
另外,还有其他的接口协议,比如SWD(Serial Wire Debug),SWD是一种串行调试接口,与JTAG相比,SWD只需要SWCLK和SWDIO两根线,减少了对单片机GPIO口的占用。
参考:SWD接口说明_weixin_42204437的博客-CSDN博客_swd接口
STM32 STLink驱动下载方式:
STM32烧写程序:ST-link驱动下载和安装_根号五的博客-CSDN博客_stlink驱动下载
官网下载:STSW-LINK004 - STM32 ST-LINK utility (replaced by STM32CubeProgrammer) - STMicroelectronics
SWD 模式比 JTAG 在高速模式下面更加可靠。 在大数据量的情况下面 JTAG 下载程序会失败, 但是 SWD 发生的几率会小很多。基本使用 JTAG 仿真模式的情况下是可以直接使用 SWD 模式的,只要你的仿真器支持。
现在市场上,已经有了很多实现了该接口的调试器,常见的有下面三种:
- JLINK V8 V9
- STLINK
- 普中ARM仿真器
市面上的常用仿真器对 SWD 模式支持情况
- JLINKV6 支持 SWD 仿真模式, 速度较慢。
- JLINKV7 比较好的支持 SWD 仿真模式, 速度有了明显的提高,速度是 JLINKV6 的 6 倍。
- JLINKV8 非常好的支持 SWD 仿真模式, 速度可以到 10M。
- ULINK1 不支持 SWD 模式。
- 盗版 ULINK2 非常好的支持 SWD 模式, 速度可以达到 10M。
- 正版 ULINK2 非常好的支持 SWD 模式, 速度可以达到 10M。
JLink仿真器
德国SEGGER公司推出基于JTAG的仿真器。简单地说,是给一个JTAG协议转换盒,即一个小型USB到JTAG的转换盒,其连接到计算机用的是USB接口,而到目标板内部用的还是jtag协议。它完成了一个从软件到硬件转换的工作。
ULINK仿真器
现在普遍用到的是ULINK2,它是ARM公司最新推出的配套RealView MDK使用的仿真器,是ULink仿真器的升级版本。ULINK2不仅具有ULINK仿真器的所有功能,还增加了串行调试(SWD)支持,返回时钟支持和实时代理等功能。开发工程师通过结合使用RealView MDK的调试器和ULINK2,可以方便的在目标硬件上进行片上调试(使用on-chip JTAG,SWD和OCDS)、Flash编程。并且仅可以在Keil软件上使用。
ST-LINK
ST公司推出的专门针对意法半导体STM8和STM32系列芯片的仿真器。买的STlink在STM8和STM32的下载接口旁边分别刻有SWIM和SWD,所以,推测STM8基于SWIM协议,STM32基于SWD协议。
小结
JLINK是通用的,支持常见的ARM。
Ulink是MDK专用的,也基本上支持所有的ARM,价格比较JLINK贵。
ST-Link是ST公司的基本只支持ST的芯片。
JLINK使用步骤
首先要知道JLINK的两种用法:下载程序 + 单步调试;
使用步骤:
1、连上单片机的JTAG接口,绿灯闪烁;
现在多数的高级器件都支持JTAG协议,如ARM、DSP、FPGA等。
JTAG有10pin的、14pin的和20pin的,尽管引脚数和引脚的排列顺序不同,但是其中有一些引脚是一样的,分别为TDI,TDO,TMS和TCK。
◇TCK(time cycle clock):时钟信号,为TAP(Test Access Port )的操作提供了一个独立的、基本的时钟信号。
◇TMS:模式选择信号,用于控制TAP状态机的转换, 测试模式选择。TMS用来设置JTAG口处于某种特定的测试模式,用于控制TAP状态机。必须上拉。。
◇TDI——测试数据输入。输入到指令寄存器(IR)或数据寄存器(DR)的数据出现在TDI输入端,在TCK的上升沿被采样。建议上拉,上拉电阻阻值不能小于1K。
◇TDO:数据输出信号。TDO是数据输出的接口。所有要从特定的寄存器中输出的数据都是通过TDO接口一位一位串行输出的(由TCK驱动)。
可选择的引脚:
Test Reset Input (TRST) 这个信号接口在IEEE 1149.1标准里是可选的,并不是强制要求的。TRST可以用来对TAPController进行复位(初始化)。因为通过TMS也可以对TAP Controll进行复位(初始化)。所以有四线JTAG与五线JTAG之分。
Return Test Clock ( RTCK) 可选项,由目标端反馈给仿真器的时钟信号,用来同步TCK信号的产生,不使用时直接接地。
System Reset ( nSRST) 可选项,与目标板上的系统复位信号相连,可以直接对目标系统复位。同时可以检测目标系统的复位情况,为了防止误触发应在目标端加上适当的上拉电阻。
2、安装JLINK驱动(segger上或者百度),如果驱动安装成功,则绿灯转为常亮;
3、Keil配置Debug
选择右边的对应调试器,其他默认即可
接着点击仿真器选择后的按钮Settings
如果连接正常,则弹出的界面会出现相关信息,否则全是空白
SN是对应调试器的识别码。
HW是硬件版本号;dll是驱动版本;FW是固件(固定在仿真器中的软件)版本;
Port可选JTAG或者SWD接口。
可点击JLink Info来查看对应调试器的信息。
以上是调试选项的设置。
接下来设置程序下载选项:
点击Utilities页:
选中对应的设备后,点击Settings按钮:
点击Add添加对应的单片机:
其他默认即可。
要注意的是,程序下载后,要点击复位后才能从flash启动执行。JLINK是可以让单片机自动复位的,如果选择了这里的Reset and Run,就能实现这个功能(硬件上,单片机的NRST连接了单片机的NRST)
如果自动复位生效,则会出现这个提示,否则没生效,需要手动复位程序。
到此,设置结束,可以进行程序调试了。
用普中调试器,出现一大堆问题(垃圾,肯定是盗版的,用STLINK有用,用它就各种报错,还是买正规的常用的吧,垃圾货)。
一开始根本就识别不到调试器,百度说是当前的工程占用了JTAG引脚,改变了JTAG引脚的状态。可以按住复位键,通过复位引脚,可以识别到。按住复位键后下载新的程序,之后就可以正常下载了。
虽然解决了识别的问题,但是一按下载按钮,接连弹出三个错误弹窗。
Error: Not a genuine ST Device! Abort connection.CMSIS-DAP - Cortex-M error:PDSC:Sequence Excution failed
Error: Flash Download failed - Target DLL has been cancelled01
第一个问题,大家说是因为芯片是盗版的,虽然有这个提示,但实际上,代码已经烧录进去了(要你手动重启才能生效)。可以通过下载示例代码来测试。
网上找到两种解决方法:
STM32编译报错 “ Not a genuine ST Device! ”_Drive World的博客-CSDN博客
实测,第二个注释的方法没有用,虽然没有了这个提示,但是又引进了其它问题。
02
第二个问题,参考:
stm32cubemax配置造成芯片错误,无法下载程序该怎么办?PDSC: Sequence Execution failed error - Ablerry - 博客园
03
第三个问题,参考:
解决Error: Flash Download failed - Target DLL has been cancelled_韩同学叫园园的博客-CSDN博客
除了配置,也有可能是硬件的问题。
待验证。
另外,还有个奇葩的问题,在选择芯片相关的烧录算法时,就是找不到对应的FLM文件
我用的是STM32f103C8,F1系列的有各种各样内存的,但是,就是没有64k内存的。
根据百度下载了旧版的库,也没有用。多了好多,但就是没有这一款。
奇葩。无语。。。
待解决。
falsh算法文件在支持包的flash文件夹中:
F:\czpBuiltin\keil5 mdk\Arm\Packs\Keil\STM32F1xx_DFP\2.4.0\Flash
工程
在建立工程时,不知道工程面向的是哪一个层级。
比如我做led控制,led控制下又会有很多功能,比如简单的点亮,还有闪烁,还有流水灯等等。
这种情况下,是给led控制整个建个工程,还是说给每个功能都建个工程呢?
我猜测,工程面向的是最后要烧录到单片机中的HEX文件的。
所以,应该是按照功能来建立工程文件的吧?
我就先这么做,后面有新的发现再补充。
继续补充:
实际中,就是以功能为单位来创建工程的,具体的层级管理通过创建文件夹来实现。
中文显示
keil无法显示中文,输入中文时,出现的是问号。
将设置中的编码改成GB2312
设置TAB四个空格
常用技巧
1、在变量或者函数名上右键,跳转到定义处或者引用处
2、头文件上右键,可以打开文档
3、本来想设置代码自动补全功能,
但是我打开之后,发现左边是空白的,网上说,是汉化导致的,可是,我本来就是英文版本的,也出现了这个问题,之后按照网上的办法做了个英文复原,结果还是一样。不知道是什么原因,后面再说吧。
一段时间后~~~~~~~~~~~~~~~~~
为了解决这个问题,我直接去官网(之前用的是其他地方下载的)下了个最新版本,然后安装。之前的安装包只有300多M,官网下的有800多M。可见,有些内容是被简化掉了。
~~~~~~~~~~~~~~~~~~~~安装完成,然而,并没有起作用。~~~~~~~~~~~~~~
于是,我想,不应该呀。如果官方原版的都没有,那么其他的更不可能会有了。
怎么回事呢?于是我猜测是不是原来的没有完全卸载。于是我不仅将软件卸载了,还将其注册表全部删除,已完成完全卸载。完全卸载参考:
彻底卸载Keil4和Keil5_unique-R的博客-CSDN博客_keil卸载
完全删除之后,再安装官方版本,就OK了。
4、keil怎么改成深色主题?好像没有很直接的方法。
5、每次新建工程,都要重新设置生成Hex文件。
6、
c语言中的头文件默认是不会出现在工程列表中(实际在文件夹中是存在的),不要着急,只要编译之后,就会在对应的c文件下面出现该文件的所有依赖头文件:
但是要注意在工程设置里包含头文件所在目录,要不然找不到。
7、程序要编译后才能调试,修改后也要重新编译后再调试,要不然修改的部分不会生效。
8,查看程序运行所用时间
可以通过keil中的系统变量sec来查看程序运行所用时间,将两个地方的所用时间相减,即可得到所间隔的时长。
要注意的是,这里的时长跟工程设置中的晶振频率相关。
注意,工程文件上如果有一个钥匙,说明带文件被锁定,是只读的。
![]()
文件上有雪花标志,好像是因为该文件的配置有过修改。
一种方法是直接右键移除该文件,再添加进来。
另一个是右键打开option,C/C++界面点击默认。
但是经过测试,第二种方式不一定好用。
keil添加文件时不考虑头文件,会自动找到。 但是要注意在工程设置里包含头文件所在目录,要不然找不到。
文件上右键选择“Open Containing Folder”可以打开所在目录。
KEIL5打开KEIL4工程
在用KEIL5打开KEIL4工程时,有如下错误提示:
此时,我已经安装了对应的安装包,可还是这样的提示,所以大概率确定是版本的问题。
打开设备选择界面时,无法选择:
如何解决?
KEIL5保存的工程名的后缀是:.uvprojx,而keil工程名则是:uvproj,比KEIL5少了个x。
手动方式就是将后缀后加个x,可以正确打开:
这种方式可以,但是,如果文件过多,一个一个地去改后缀名,稍显麻烦。
可以先将文件导入。
错误提示后,又会弹出提示:
keil提供了两个解决方案:
Migrate to Device Pack(迁移到设备包) 和 Install Legacy Support(安装遗留支持),用第二种方法解决比较方便,但是要另外下载支持包。
迁移的思路是,将现有的文件自动更改成KEIL5的,不容易成功;第二种的思路是安装兼容包,让在keil中也能运行keil4工程文件。
先试下第一种:
点击迁移至设备包,提示迁移失败。
找了半天也没找到这个问题的解决方法,好像都没有人遇到过一样。
不纠结了,直接修改后缀名吧。
不过这个跟旧工程的具体环境有关,我换了个其他旧工程导入,就迁移成功了。
第二种:安装遗留支持包
去官网下载:MDK v4 Legacy Support
然后双击安装即可。
编译器的问题
解决了工程兼容的问题,接下来又出现了编译器兼容的问题:
提示工程之前使用的编译器版本不存在:
到工程设置的target下:
选择其他可用的编译器,不过,可能会因此带来一些语法问题:
但至少能编译成功。
关于编译器的版本选择,遇到了一个跟这个有关的问题。
别人给了一套工程代码,应该是没有问题的, 我这边在编译后,产生了上千个问题。
一般这种情况,基本就不是语法之类的问题了,要么是配置问题,要么是支持包、软件版本、编译器版本等的问题了。
百度一番过后,发现有人提出了解决方法。
我安装的是新版的keil5,自带了编译器6,原来的编译器5已经不支持了。
想到我这个拿到的是之前的代码,极有可能是基于编译器5来写的,里面的相关配置都是编译器5来生成的,所以编译器6可能不适配。
但是新版keil已经没有编译器5了,就只能自己去装了。
参考:KEIL5MDK最新版(3.37)安装以及旧编译器(V5)安装_v5编译器下载_二氧化碳的日常生活的博客-CSDN博客
下载好的编译器5文件夹名称叫ARMCC
按照操作安装好之后,发现又出现了新的问题
提示检查许可证失败。
啥情况,我就按照提示加上百度的说法,将keil重新破解了一遍,发现没啥用。
这时候,我的ARMCC是放在随意的一个位置的,我在想,是不是得先复制到keil安装目录下,然后再添加呢?于是我操作了一遍。
注意:上图中的ARMCLANG目录就是最新版本的编译器6。
之后在keil里选择编译器5
再执行编译操作,就没错误了。
可见,基于不同的编译器来编程,是完全不一样的。
新版启动文件
新版KEIL5不会直接自动生成启动文件(旧版比如MDK3会自动生成),新版在创建工程时,会弹出一个运行时环境管理窗口,需要在这个界面进行选择。
如果一开始没有选择,那么可以再次配置。
打开Manage Run,使用快捷图标或从菜单里选择。
勾选Startup和关联项CORE,点击[ok]。
然后可以看到启动文件就出来了。
无法跳转定义
直接参考这个解决。
上述链接里第二种换成version 5编译器的方式有缺陷,那就是根本就没有默认的version5
在其他地方看到一个方法:
在没有中文路径情况下,进入 Option for target->ouput->Browse Information取消勾选,点击Rebuild all target files重新编译下所有文件,Browse Information重新勾选,再重新编译下所有文件,完美解决,可以愉快的go to define!!!没有效果。
优化
在Keil里有个优化等级设置,建议最好不要优化,至少在调试的时候不要优化,因为不优化才能让运行过程和写的代码保持完全一致,否则可能会因为优化让有些地方调试不了。
具体参考:
ARMCC
关于ARM使用的编译器,参考下文:
ARMCC(Keil) 编译器_bingquan3333的博客-CSDN博客
keil5中使用的是ARMCLANG编译工具链
中断的调试
中断可以直接打点调试。
中断内打点后,直接点击全速运行,让程序运行起来,然后可以触发中断。
One ELF Section per Function
可以对比下勾选ELF和不勾选ELF的区别
勾选了
没勾选
可以看到,代码没优化,code占用空间变大了。