创建工程目录文件
首先,创建好工程文件目录,比如task4_exit;
然后在里面创建一个proj目录,创建工程选择的文件夹就选择proj,这样创建Keil工程文件都是放在proj里面;
接着在task4_exit的根目录创建一个main.c(空文件即可);
最后在task4_exit的根目录放入如下固件库文件:
1)startup_stm32f10x_md.s,程序运行启动汇编文件;
2)stm32f10x.h,微控制器专用头文件;
3)stm32f10x_conf.h,固件库配置文件;
4)system_stm32f10x.c, system_stm32f10x.h,微控制专用的系统文件,其中SystemInit就是定义在这个源文件里面;
配置小魔方
配置targets
配置target,group以及files;target基本保持和工程名称一致即可;group里面添加两个,一个user,用于存放源文件,一个是lib用于存放stm32等固件库;
添加文件
然后在lib目录里面添加core以及STM32F10x_StdPeriph_Driver\src下面的.c的固件库源文件; 在user目录里面添加main.c,startup_stm32f10x_md.s以及system_stm32f10x.c三个源文件
关于target,groups以及files
在Keil里面,可以创建多个target;比如把LED点亮最一个target;后面按键中断作为一个target;target含义就是独立编译的单元;
然后可以在Keil的targets下拉框列表中选择需要编译/ 烧写的编译单元:
对于Groups,则是一个逻辑文件夹,因为并没有在磁盘上面真正的创建文件夹,这里逻辑文件夹只是按照意义进行文件分割而已。
Files则是添加物理磁盘上面的文件;
需要注意的是配置Targets/ Groups/ Files,都是逻辑层面的,并没有创建文件夹和文件,只是创建逻辑文件夹,引用已经存在的文件,这个配置过程其实是用来生成编译配置文件,即类似于make文件,这个编译配置文件里面定义好了都要编译那些文件。
配置小魔法棒
“Device”标签页
里面确认设备选择的是你自己要烧写的板子型号(这里是选择的是我的板子:STM32f103C8,STM32命名规则请见上次番外篇的介绍);
“Target”标签页
a. 确认ARM compile选择的version5(version6会有语法编译问题);
b. Use MicroLIB勾选上;MicroLib是一个微型的C库,提供了嵌入式常见的c的函数库,但是因为是对嵌入式函数的支持,所以相比于linux的gcclib很不完整;之所以需要勾选,是因为有的时候需要使用一些诸如在"stdio.h"来实现printf的时候,是需要c库支持的,这些底层c库的API接口以及实现stm32固件库是不提供的,注意stm提供是固件库,是直接操作(硬件)寄存器的,而c是操作系统层面的,属于软件层面的,所以有需要的时候勾选上;
“c/c++”标签页
添加宏USE_STDPERIPH_DRIVER
为什么需要整个宏呢?这里添加这个宏相当于是全局定义了:
#define USE_STDPERIPH_DRIVER
其实你在stm32f10x.h里面可以看到对于这个这个判断:
#ifdef USE_STDPERIPH_DRIVER
#include "stm32f10x_conf.h"
#endif
只有定义了这个宏才会导入stm32f10x_conf.h;引入这个conf.h,就是为了引入外围设备操作,比如GPIO就是一个外围设备,只有导入stm32f10x_conf.h才能够操作外设;
如果不添加这个宏,在编译的时候将会长篇累牍的报告警,其实不仅仅是告警,在运行时还会报错,因为没有.h的引用,是无法调用到函数的:
warning: #223-D: function "assert_param" declared implicitly;assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
勾选"C99 Mode"
大大减小语法编译报错的概率;C99相比于默认的C89,不仅带来很多新特性,而且更加人性化,比如上一个小节中我们提到变量定义要在第一行可执行代码之前,否则编译报错:
int main(void)
{
GPIO_InitTypeDef led;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
... ...
}
但是,如果勾选了C99,就没有这个限制了;
确认编译优化选项
Debug状态Level0,Level0在生成的二进制文件中,会添加很多调试相关信息,在调试的时候可以准确的走位,其他Level因为做了很多CPU指令级别优化,会导致(单步)调试过程中会出现不可预知的走位; 如果编译是为了最终部署的时候需要修改为Level3以减小编译文件大小,同时提高执行性能;
添加Include Path
include path就是添加包含有.h头文件的路径,这样在编译的时候.c文件,里面包含了#include,可以到定义的include path下面去找.h文件;需要添加三个路径分别是 a. 工程的根目录,下面有三个.h文件 b. core根目录,系统内核的头文件; c. STM32F10x_StdPeriph_Drive\inc,标准外设相关的头文件;
小贴士
.h文件是做什么的呢?就是用来做引用和实现分离的;为什么要分离?好处有两个:
-
调用方和实现方彼此独立,这样无论是调用方,还是是实现方有变化不需要再编译对方;比如调用方是在exe里面,调用方在编译到时候只要有头文件存在即可,而实现方是在也dll里面,彼此独立,无论是exe修改,还是dll修改,都不影响; -
方便交叉编译,比如可以实现在windows上面编译Linux代码,只要配置了include路径,找到.h的定义,就可以完成编译;
这两点优点其实本质都是将调用的过程推迟到了运行时,编译的时候只要有头文件,有函数的声明信息即可(不需要函数定义信息),函数定义信息要求放在了运行的时候。
“Debug”标签页
选择使用指定的调试器,我的是ST-Link,所以下拉框选择“ST-Link Debuger”;
Utilities
取消勾选“User Debug Driver”,选择“ST-Link Debuger”:
点击“Setting”
Trace标签页
可以配置调试的时钟,注意,只是debug的时候才有效,烧写到板子之后,时钟走的是板子自己的时钟:
“Flash Download”标签页
勾选上“Reset And Run”,这样在烧写到STM32完成后,将会自动重启系统;
”Pack“标签页
里面确认取消勾选"Enable",如果勾选部分功能回合MicroLib冲突,将会导致一些功能异常,比如printf失效:
运行main
配置完成后,在main.c里面添加一个空的main函数,run一下;如果0waring,0 error就是OK咯。
|