求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
要资料
 
追随技术信仰

随时听讲座
每天看新闻
 
 
STM32单片机自学教程
0.前言
1.STM32单片机入门
2.STM32开发C语言
3.STM32F1x系统架构
4.STM32单片机系统电路
5.STM32F1x的寄存器
6.STM32开发环境介绍
7.嵌入式开发常见概念简介
8.STM32开发方式(库函数)介绍
9. Keil5-MDK软件简介
10.创建MDK工程-寄存器版
11.创建MDK工程-基于自建库函数
12.STM32标准库简介
13.创建MDK工程-基于标准库版
14.GPIO简介
15.GPIO输入-按键检测
16.GPIO位带操作
17.RCC-STM32时钟配置
18.STM32中断系统概述
19.基本定时器
 

 
目录
 
第10章.创建MDK工程-寄存器版
来源:CSDN,作者:村里大明白
40 次浏览
3次  

本章介绍如何创建寄存器版本的MDK工程。

10.1 新建本地工程文件夹

图10.1-1 新建文件夹

我们首先建立一个文件夹(取名:Led_RegVersion)用于后续建立MDK工程。正常项目我们这个时候是需要再建立一些文件夹,用来分别存放启动文件,外设以及内核等支持文件的,这章我们就省掉这一步,后续正式建工程的时候再正规讲解,也是为了有一个对比,效果会更好。

10.2 新建工程

打开MDK,新建一个工程,工程名根据个人喜好,最好取一个一眼就能知道含义的名字,我这里取LED_RegVersionTest,直接保存在上一步骤建立的Led_RegVersion文件中。

图10.2-1 新建工程

10.2.1 选择MCU 型号

新建工程后会弹出MCU型号选择对话框,这个根据我们自己所用的型号选择即可,我们用的F103C8T6,所以我们选择STM32F103C8。注意如果这里没有你找到的型号,说明前面安装的时候没有安装对应的器件支持包,安装一下即可。

图10.2-2 选择MCU型号

10.2.2 在线添加库文件

点击 OK后MDK 会弹出 Manage Run-Time Environment 对话框,如图 10.2-3 所示.在这个界面,我们可以添加自己需要的组件,从而方便构建开发环境,这里我们暂时用不到就直接跳过,我们直接点击 Cancel,即可。

图10.2-3 Manage Run-Time Environment 界面

 

10.2.3 生成工程文件结构介绍

此时我们打开我们创建的文件夹,会看到 MDK 在该文件夹下自动创建了 3 个文件夹:

DebugConfig,Listings 和 Objects),如图 10.2-4所示. 这三个文件夹是随着.uvprojx文件创建时自动生成的。

图10.2-4 MDK新建工程时自动创建的文件夹

这三个文件夹的作用如下图10.2-5所示:

图10.2-5 MDK自动生成的文件夹的作用

10.2.4 添加分组及文件

在Project→Target 上右键,选择 Manage Project Items…或在菜单栏点击品字形红绿白图标进入工程管理界面,如图10.2-6所示:

图10.2-6 进入工程管理界面

在工程管理界面,我们可以执行设置工程名字(Project Targets)、分组名字(Groups)以

及添加每个分组的文件(Files)等操作。我们设置工程名字为:Target 1,并设置2个分组:

Startup(存放启动文件)、User(存放 main.c 等用户代码)如图 10.2-7所示:

图10.2-7 工程管理配置

在实际使用过程中,我们也经常会在新建的组里右键添加文件,如图10.2-8。

图10.2-8 组新建文件

添加启动文件

启动文件就是,系统上电后第一个运行的程序,由汇编编写。这个文件从标准固件库里面复制过来即可,由官方提供。这个文件我们添加到前面建立的Startup组里去。文件在下面目录,如图10.2-6。 STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS \ CM3\DeviceSupport\ST\STM32F10x\startup\arm

图10.2-6 启动文件

从上图我们可以看到,启动文件有很多,哪个是我们需要的呢?我们可以根据下表10.2-1查找。我们所用的STM32F103C8T6是64K的ROM因此,对应的启动文件是后缀为MD的,即启动文件为:startup_stm32f10x_md.s。我们把这个文件copy到我们新建的文件夹Led_RegVersion之下。

表10.2-1 不同型号STM32缩写

添加Main.c文件

用户手动新建,用于存放main 函数,暂时为空。建成后文件夹如图10.2-7所示。这个我们添加到User组里。

图10.2-7 添加文件后的文件夹

10.3 硬件连接

如图10.3-1,我们把LED 灯的阳极连接到3.3V 电源,阴极各经过1 个限流电阻接到我们使用的STM32最小系统板的PB0口,我们只要控制这PB0引脚输出高/低电平,即可控制所连接LED 灯的亮灭。我们的目标是把GPIO-PB0口的引脚设置成推挽输出模式并且默认下拉,输出低电平,这样就能让LED灯亮起来了。(关于GPIO的模式等问题后面再讲,这里不用管)

图10.3-1 硬件连接图

10.4 代码编写

10.4.1 启动文件解释

前面名为“startup_stm32f10x_md.s”的文件,它里边使用汇编语言写好了基本程序,当STM32芯片上电启动的时候,首先会执行这里的汇编程序,从而建立起C语言的运行环境,所以我们把这个文件称为启动文件。该文件使用的汇编指令是Cortex-M3内核支持的指令。startup_stm32f10x_md.s文件由官方提供,一般不需要修改。启动文件这部分的主要功能如下:

•初始化堆栈指针SP;

•初始化程序计数器指针PC;

•设置堆、栈的大小;

•初始化中断向量表;

•调用SystemIni()函数配置STM32的系统时钟。

•设置C库的分支入口“__main”(最终用来调用main函数);

这里面对我们来说最重要的是,在启动文件中有一段复位后立即执行的程序,搜索Reset_Handler 即可找到,代码如下:

图10.4-1 启动文件中Reset_Handler代码

下面对这段代码进行解析:

  1. ; Reset handler
  2. 代码含义:程序注释,在汇编里面注释用的是“;”,相当于C 语言的“//”注释符。

  1. Reset_Handler PROC
  2. 代码含义:
  3. 定义了一个子程序:Reset_Handler。PROC 是子程序定义伪指令。这里就相当于C 语言
  4. 里定义了一个函数,函数名为Reset_Handler。

  1. EXPORT Reset_Handler [WEAK]
  2. 代码含义:
  3. EXPORT 表示Reset_Handler 这个子程序可供其他模块调用。相当于C 语言的函数声明。
  4. 关键字[WEAK] 表示弱定义,如果编译器发现在别处定义了同名的函数,则在链接时用别处的地
  5. 址进行链接,如果其它地方没有定义,编译器也不报错,以此处地址进行链接。

  1. IMPORT __main
  2. IMPORT SystemInit
  3. 代码含义:
  4. IMPORT 说明SystemInit 和__main 这两个标号在其他文件,在链接的时候需要到
  5. 其他文件去寻找。相当于C 语言中,从其它文件引入函数声明。以便下面对外部函数进行调
  6. 用。

__main其实不是我们定义的(不要与C语言中的main函数混淆),这是一个C库函数,当编译器编译时,只要遇到这个标号就会定义这个函数,该函数的主要功能是:负责初始化栈、堆,配置系统环境,并在函数的最后调用用户编写的main函数,从此来到C的世界。SystemInit是用来配置系统时钟的,这个是官方写好的。

  1. LDR R0, =SystemInit
  2. 代码含义:
  3. 把SystemInit 的地址加载到寄存器R0
  4. BLX R0
  5. 代码含义:
  6. 程序跳转到R0 中的地址执行程序,即执行SystemInit 函数的内容。
  7. LDR R0, =__main
  8. 代码含义:
  9. 把__main 的地址加载到寄存器R0
  10. BX R0
  11. 代码含义:
  12. 程序跳转到R0 中的地址执行程序,即执行__main 函数,执行完毕之后就去到我们熟知的
  13. C 世界,进入main 函数。
  14. ENDP
  15. 代码含义:
  16. 表示子程序的结束

因为我们目前体验的是寄存器版本的MDK工程,我们是假定没有官方支持的,所以我们的函数里是没有SystemInit这个函数的,为了程序不报错,我们有2种处理方法:

1.修改一下启动代码,把SystemInit相关的注释掉。修改后如下:

  1. ; Reset handler
  2. Reset_Handler PROC
  3. EXPORT Reset_Handler [WEAK]
  4. IMPORT __main
  5. ;IMPORT SystemInit
  6. ;LDR R0, =SystemInit
  7. ;BLX R0
  8. LDR R0, =__main
  9. BX R0
  10. ENDP

2.在我们的C文件函数里编写一个 SystemInit的空函数。

因为启动文件是只读的,改起来麻烦,我们就直接采用写个SystemInit的空函数的方式。

10.4.2 main.c编写

现在我们开始编写我们的程序。除了前面提到的SystemInit的空函数, 我们主要是要配置GPIO-PB0端口,使其输出低电平。这里主要需要配置3个寄存器,分别是:

①开启APB2时钟控制寄存器

②CRL输入输出方式寄存器

③ODR端口输出数据寄存器

这里不太懂没关系,后面我们还会针对GPIO开专题讲解。下面是配置方式:

①开启外设时钟:

由于STM32 的外设很多,为了降低功耗,每个外设都对应着一个时钟,在芯片刚上电的时候这些时钟都是被关闭的,如果想要外设工作,必须把相应的时钟打开。STM32 的所有外设的时钟由一个专门的外设来管理,叫RCC(Reset and ClockControl),RCC 在《STM32 中文参考手册》的第六章。

通过前面章节,我们知道所有的GPIO 都挂载到APB2 总线上,具体的时钟由APB2外设时钟使能寄存器(RCC_ APB2ENR)来控制。

首先我们需要配置RCC_ APB2ENR的地址。关于地址的配置,可以参考本专栏的第5章。

在《STM32 中文参考手册》中RCC寄存器的地址范围,如图10.4-2:

10.4-2 参考手册中RCC寄存器地址范围

由此我们看到,RCC时钟控制寄存器的基地址是0x4002 1000。APB2外设时钟使能寄存器(RCC_ APB2ENR)的描述如下图,我们只用把该寄存器的bit3置1即可开启GPIO-B的时钟。

图10.4-3 APB2外设时钟使能寄存器

根据以上信息,相关代码如下,代码中“|=”的目的是不改变其他bit的设置。

  1. /*RCC基地址*/
  2. #define RCC_BASE ((unsigned int) 0x40021000)
  3. /*GPIO_B地址*/
  4. #define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)
  5. RCC_APB2ENR |= 0x00000008;// 开启 GPIOB 端口 时钟

②配置输入输出方式:

首先我们把连接到LED灯的GPIO引脚PB0配置成输出模式,即配置GPIO的端口配置低寄存器CRL,见图GPIO端口控制低寄存器CRL。CRL中包含0-7号引脚,每个引脚占用4个寄存器位。MODE位用来配置输出的速度,CNF位用来配置各种输入输出模式。在这里我们把PB0配置为通用推挽输出,输出的速度为10M。

图10.4-4 CRL寄存器配置图

对应代码如下:

  1. /*GPIO-B基地址*/
  2. #define GPIOB_BASE ((unsigned int) 0X40010C00)//可查看参考手册
  3. /*GPIO_B-CRL地址*/
  4. #define GPIOB_CRL *(unsigned int*)(GPIOB_BASE+0x00)
  5. GPIOB_CRL &= ~((unsigned int)0x0000000F);// 清空控制 PB0 的端口位
  6. GPIOB_CRL |= (unsigned int)0x00000001;// 配置 PB0 为通用推挽输出,速度为 10M

③配置端口输出寄存器:

我们在这里直接操作ODR 寄存器来控制GPIO的电平,如图10.4-5.ODR寄存器的配置图。

图10.4-6 ODR寄存器配置图

对应代码如下:

  1. Reset_Handler PROC
  2. 代码含义:
  3. 定义了一个子程序:Reset_Handler。PROC 是子程序定义伪指令。这里就相当于C 语言
  4. 里定义了一个函数,函数名为Reset_Handler。

至此代码全部写完,完整的代码如下:

  1. ; Reset handler
  2. 代码含义:程序注释,在汇编里面注释用的是“;”,相当于C 语言的“//”注释符。

10.5 魔术棒配置

10.5.1 Output 选项卡

图10.5-1 Output选项卡配置

Output 选项卡主要是选择把输出文件放到哪个文件夹,如果不选择就是系统默认的前面建立工程时自动生成的“Objects”文件夹,也可以自己选择指定文件夹存放。如果想在编译的过程中生成hex 文件,那么那Create HEX File 选项勾上。

10.5.2 Listing选项卡配置

在Listing 选项卡和前面Output类似,如果不选择就是系统默认的前面建立工程时自动生成的“Listings”文件夹,也可以选择自己习惯的文件夹。

10.5.2 下载器配置

在debug选项卡中,我们选择我们使用的下载器STLINK。右边蓝色框点开Debug Settings 选项配置,弹出对话框的“Flash Download”选项卡,把“Reset and Run 也勾选上,这样程序下载完之后就会自动运行,否则需要手动复位”。

图10.5-2 下载配置

10.6 下载程序

前面步骤都成功后,接下来就是编译,连接最小系统板到电脑,然后下载程序到最小系统板上运行。下载程序不需要其他额外的软件,直接点击KEIL中的LOAD 按钮即可,如图10.6-1。消息栏,出现“Application running…”,则表示代码下载成功,且开始运行 就可以观察实验现象了。

图10.6-1 编译下载

如图10.6-2我们终于点亮了我们第一个LED灯。。。

图10.6-2 实验现象


您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



40 次浏览
3次