# 1 单片机简介

# 单片机是什么

1. 单片机与电脑对比

Single-Chip Microcomputer,单片微型计算机,是一种集成电路芯片。

电脑与单片机 STM32F1 对比

对比项 电脑 单片机
CPU 主频 x86,2~5Ghz 51/arm/risc-v, 72MHz@STM32F1
内存 GB级,40G/s kb级 约300Mb/s
硬盘容量 TB级 500Mb/s @SATA3 kb级 约 100Mb/s
功耗 数百 w < 0.5W

64 位电脑,每次访问 8 位,64 / 8 = 8(字节), 访存速度 8 * 5 = 40 Gb/s。

2. 单片机特点

  1. 体积小
  2. 功耗低
  3. 集成度高
  4. 使用方便
  5. 扩展灵活

3. 单片机作用

  1. 仪器仪表
  2. 家用电器
  3. 工业控制
  4. 汽车电子

4. 单片机发展历程

SCM 单片微型计算机 -> MCU 微控制器 -> SoC 嵌入式片上系统。

5. 单片机发展趋势

CPU:主频高,64位,双 CPU,流水线

存储器:Mb 级,片内 ROM FLash 化,程序加密化

IO:提高并行口驱动能力,增加 I/O功能

外围电路内置化:高集成度,DMA/DA等集成到片内。

6. CISC VS RISC

复杂指令集便于编程和提高存储器访问效率,如 8051,x86架构。

  1. 指令多,模式多,格式可变。
  2. 指令执行需要的时钟周期差距大。
  3. 无流水线或者流水程度低。
  4. 指令由微代码翻译执行。

精简指令集能提高处理器运行速度,如 ARM/MIPS/RISC-V。

  1. 指令少,模式少,格式固定。
  2. 大多数指令只需要一个时钟周期。
  3. 流水线结构。
  4. 指令直接由硬件执行。

7. 冯诺依曼结构和哈佛结构

冯诺依曼结构:

冯·诺依曼结构(von Neumann architecture)又称作普林斯顿体系结构(Princetion architecture)。冯·诺依曼结构的处理器使用同一个存储器,经由同一个总线传输。

是一种将程序指令存储器和数据存储器合并在一起的计算机设计概念结构。

指令和数据统一编址,使用同一条总线传输。

  1. 必须有一个存储器。
  2. 必须有一个控制器。
  3. 必须有一个运算器,用于完成算术运算和逻辑运算。
  4. 必须有输入和输出设备,用于进行人机通信。

哈佛结构:

中央处理器首先到程序指令储存器中读取程序指令内容,解码后得到数据地址,再到相应的数据储存器中读取数据,并进行下一步的操作(通常是执行)。程序指令储存和数据储存分开,数据和指令的储存可以同时进行,可以使指令和数据有不同的数据宽度

哈佛结构的微处理器通常具有较高的执行效率。其程序指令和数据指令分开组织和储存的,执行时可以预先读取下一条指令

利弊:

冯诺依曼结构主要用于通用计算机领域,需要对存储器中的代码和数据频繁的进行修改,统一编址有利于节约资源。

哈佛结构主要用于嵌入式计算机,程序固化在硬件中,有较高的可靠性、运算速度和较大的吞吐量。

# 2 Cortex-M 系列介绍

# 2.1 ARM 公司

只做内核设计与 IP 授权,不参与芯片设计。

  1. 低功耗、低成本、高性能。
  2. 支持 16 位/32 位双指令集。

# 2.2 Coterx 内核分类及特征

对比项 Cortex-A Cortex-R Cortex-M
特点 高时钟频率,长流水线、高性能 较高时钟频率,较长流水线 实时性强 始终频率低,流水线短,超级功耗
应用场景 移动计算、智能手机、平板电脑、数字电视 军工、汽车电子、无线基带 工控、传感器、消费电子、家用电器、医疗器械

Cortex-M3/4/7 介绍

# 3 STM32 是什么

ST:意法半导体

M:MCU/MPU

32:32位

# 3.1 系列

共五大类:MPU/高性能 MCU/主流 MCU/超低功耗 MCU/无线系列 MCU

选型手册。

# 4 数据手册

获取方式

  1. ST 官网
  2. stcu 中文社区

# 4.1 查看数据手册

目录:

  1. 介绍
  2. 规格说明
  3. 引脚定义
  4. 存储器映像
  5. 电气特性
  6. 封装特性
  7. 订货代码
  8. 版本历史

stm32f103rct6,是通用增强型,64 位引脚,48kb RAM,256k 闪存存储器, LQFP 封装,工作在 -40 摄氏度 至 85 摄氏度的芯片。 数据手册内容概要:

查询数据手册可知:

SRAM: 高速缓存。

stm32f103rct6 的基本参数为:

  1. 主频/FLASH/SRAM:72MHz/256Kb/48kb
  2. 工作电压/最大电流:2.0~3.6V/150mA
  3. I/O 引脚接入电压范围:COMS 端口:-0.3V ~ 3.6V,兼容 5V 端口:-0.3V ~ 5.5V
  4. 单个 I/O 引脚最大电流:25mA

flash起始地址为0x8000000,大小为0x4000(16进制)—>262144字节(10进制)—>256KB

RAM起始地址为0x2000000,大小为0xC000(16进制)—>49125字节(10进制)—>48KB

引脚定义

引脚类型:(LQFP64 为例)

  1. 电源引脚,如 VSSA,VBAT,VDD 等以 V 开头的。
  2. 晶振引脚,如 PC14-OSC32_IN,PD1 OSC_OUT 等带 IN/OUT 的引脚。
  3. 复位引脚,如 NRST
  4. 下载引脚
    1. JTAG,可以下载、仿真、调试,占用 5 个 I/O。
    2. SWD,下载、仿真、调试,占用 2 个 I/O ,建议使用。(SWDIO/SWCLK/GND/VCC/RESET(可选))
    3. 串口,下载,占用两个引脚。
  5. BOOT 引脚(BOOT0/PB2(BOOT1))
  6. GPIO 引脚(P 开头的引脚)

# 5 最小系统和 I/O 分配

保证 MCU 正常工作的最小电路组成单元。

  • 主控芯片
  • 电源电路
  • 晶振电路
  • 下载调试电路
  • BOOT 启动电路
  • 复位电路

# 5.1 复位电路

STM32 复位引脚 NRST 保持低电平状态实践 1~4.5ms 即可复位。

  1. 上电复位
  2. 复位按键复位

上电的瞬间,电容充电,NRST 是低电平,电容充满电后,NRST 变为高电平。

控制电容大小,控制电容充满电的时间满足复位要求。

# 5.2 启动电路

ISP Mode(2、3)

Run Mode(1、2)

# 5.3 晶振电路

如果使用内部RC振荡器而不使用外部晶振,请按照下面方法处理:

  1. 对于100脚或144脚的产品,OSC_IN 应接地,OSC_OUT 应悬空。
  2. 对于少于100脚的产品,有2种接法:
    1. OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能。
    2. 分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面2.1)节省2个外部电阻。

外部低速晶振(32.768KHz)

外部高速晶振(8MHz)

# 5.4 下载调试电路

SWD:

USB-0DG:

# 5.5 I/O 分配

优先分配特定外设 I/O,然后分配通用 I/O,最后微调。

# 6 搭建开发环境

# 6.1 常用开发工具

开发环境:MDK,仿真器:ST-LINK/J-LINK/DAP,串口调试助手:sscom/putty

# 6.2 MDK 安装和 器件支持包

均可在 arm keil 官网直接下载。

想要在国内如何快速下载 keil 的 pack 文件包,可以先在 keil 的 pack 官网查找自己想要的 pack, 然后添加到 http://keilpack.azureedge.net/pack/ 末尾,如: http://keilpack.azureedge.net/pack/ARM.V2M_MPS3_SSE_300_BSP.1.1.0.pack

注意:安装路径不要有中文,路径越短越好。

KEIL5 默认使用 armclang6 编译器,最好使用 HAL 库。

# 6.3 安装仿真器驱动

DAP 仿真器不需要驱动。

ST-LINK 需要安装驱动。

# 6.4 安装 CH340 USB 虚拟串口驱动

CH340作为一种电平转换芯片,用于TTL电平标准转USB电平标准,最终实现USB转串口(一般用于电脑和设备之间的通信)

CH340驱动就是USB转串口的驱动的一种,芯片是CH340的均可以使用。安装CH340驱动之后,板子连接串口就可以正常发挥其功能了。

USB虚拟串口作用

  1. USB口当串口使用。
  2. USB连接串口 1,USB 还能当作串口来下载程序。
  3. 当 USB 供电口。

查询数据手册,串口1为 PA9,PA10

# 7 MDK 编译例程

部分编译:只编译更新过的代码。

全局编译:全部编译。

FLASH 大小:code + RO-Data + RW-data

SRAM 大小:RW -data + ZI-data

还可以看 .map 文件查看。

下载到开发板执行的文件是 .hex 文件。

编译后双击项目名查看 .map 文件,最后可以查看 FLASH 和 ROM 大小。

# 7.1 串口下载程序

M3 和 M4 开发板支持串口下载程序,M7 不支持串口下载。

STM32 的 ISP 下载,常用串口1 下载程序。

使用 usb 虚拟串口,需 CH340 USB 虚拟串口驱动。

ISP 方式

ISP(在系统编程)是通过ST在芯片生产线上写入内嵌的自举程序到芯片系统存储器中,启动时从系统存储器中运行这个自举程序,它通过USART1串口来将我们的程序写入闪存存储器中。 注意下载时要将开发板上的boot开关打到ISP模式,ISP模式下载完成后可以立即执行程序。而如果要单独启动程序,则必须将boot开关打到RUN运行模式。

ISP下载需要借助第三方工具,如mcuisp.exe或FlyMcu.exe。

F4 系列波特率最大:76800,F1 系列最大波特率:460800。

# 7.2 STM32 启动模式(M3/M4)

stm32f103rct6。

查询参考手册 2.4 小结,可得知 stm32f10xxx 的启动配置:

根据选定的启动模式,主闪存存储器、系统存储器或SRAM可以按照以下方式访问:

  • 从主闪存存储器启动:主闪存存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的地址(0x0800 0000)访问它,即闪存存储器的内容可以在两个地址区域访问,0x00000000或0x0800 0000。用于存储用户程序。
  • 从系统存储器启动:系统存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的地址(0x1FFF F000)访问它。存储有预烧录的启动程序。
  • 从内置SRAM启动:只能在0x2000 0000开始的地址区访问SRAM,掉电消失,不能永久存储。

ISP 下载即选择系统存储器启动。

内嵌的自举程序用于通过USART1串行接口对闪存存储器进行重新编程。这个程序位于系统存 储器中,由ST在生产线上写入。

ISP 下载程序步骤

  1. BOOT0 接高电平,BOOT1 接低电平
  2. 按复位键

程序下载到 主闪存存储器中。(0x08000000 - 0x0807FFFF)

程序执行一般步骤

  1. BOOT0 接低电平,BOOT1 任意
  2. 按复位键

ST-LINK/J-LINK 下载程序

使用 st-link 可以进行程序的调试。

keil 里设置 debug 选择 ST-LINK Debugger。

点击工具栏 load 即可将程序下载到 mcu 中。

使用 ST-LINK 调试程序

Debug 设置,use ST-LINK debugger,然后点击 settings,Debug 页面里,ort 选择为 SW,Flash Download 里勾选上 reset and run。

Flash Download 页面配置下载算法,根据芯片 flash 大小配置,大于 512kb 手动配置。

keil 仿真

debug 选择 use simulator,并勾选 Run to main()

首先查看芯片数据库

将对应内容填写到下面:

编译成功后设置断点后就可以进行仿真了。

  1. Register:寄存器窗口,一般用于查看程序运行时间。
  2. Disassembly:反汇编窗口,将 C 语言代码和汇编对比显示。
  3. 代码窗口,黄色的三角形表示将要执行的代码,绿色的三角形表示当前光标所在代码。
  4. Call Stack + Locals:调用关系&局部变量窗口,通过该窗口可以查看函数调用关系,以及函数的局部变量。

  • 复位:其功能等同于硬件上按复位按钮。相当于实现了一次硬复位。按下该按钮之后,代码会重新从头开始执行。
  • 执行到断点处:该按钮用来快速执行到断点处,有时候你并不需要观看每步是怎么执行的,而是想快速的执行到程序的某个地方看结果,这个按钮就可以实现这样的功能,前提是你在查看的地方设置了断点。
  • 停止运行:此按钮在程序一直执行的时候会变为有效,通过按该按钮,就可以使程序停止下来,进入到单步调试状态。
  • 执行进去:该按钮用来实现执行到某个函数里面去的功能,在没有函数的情况下,是等同于执行过去按钮的。
  • 执行过去:在碰到有函数的地方,通过该按钮就可以单步执行过这个函数,而不进入这个函数单步执行。
  • 执行出去:该按钮是在进入了函数单步调试的时候,有时候可能不必再执行该函数的剩余部分了,通过该按钮就可以一步执行完该函数的余部分,并跳出函数,回到函数被调用的位置。
  • 执行到光标处:该按钮可以迅速的使程序运行到光标处,其实是挺像执行到断点处按钮功能,但是两者是有区别的,断点可以有多个,但是光标所在处只有一个。
  • 反汇编窗口:通过该按钮,就可以查看汇编代码,这对分析程序很有用。
  • Call STACK 窗口:通过该按钮,显示调用关系&局部变量窗口,显示当前函数的调用关系和局部变量,方便查看,对分析程序非常有用。
  • 观察窗口:MDK5 提供 2 个观察窗口(下拉选择),该按钮按下,会弹出一个显示变量的窗口,输入你所想要观察的变量/表达式,即可查看其值,是很常用的一个调试窗口。
  • 内存查看窗口:MDK5 提供 4 个内存查看窗口(下拉选择),该按钮按下,会弹出一个内存查看窗口,可以在里面输入你要查看的内存地址,然后观察这一片内存的变化情况。是很常用的一个调试窗口
  • 串口打印窗口:MDK5 提供 4 个串口打印窗口(下拉选择),该按钮按下,会弹出一个类似串口调试助手界面的窗口,用来显示从串口打印出来的内容。
  • 系统分析窗口:该图标下面有 6 个选项(下拉选择),我们一般用第一个,也就是逻辑分析窗口(Logic Analyzer),点击即可调出该窗口,通过 SETUP 按钮新建一些 IO 口,就可以观察这些 IO 口的电平变化情况,以多种形式显示出来,比较直观。
  • 系统查看窗口:该按钮可以提供各种外设寄存器的查看窗口(通过下拉选择),选择对应外设,即可调出该外设的相关寄存器表,并显示这些寄存器的值,方便查看设置的是否正确。

逻辑分析窗口使用

Set添加变量,变量类型(4)有 analysis/bit/status 等,如果是数字量,就选择 bit。

添加要查看的引脚,例如 GPIOA_Pin_3 引脚,则输入 PORTA.3 或者 PORTA>>3

DARMSTM.DLL -pSTM32F103RC

zoom 可以调整 in 和 out 来调节 Grid。

# 8 JTAG/SWD 调试

# 8.1 原理

Cortex-M 内核含有硬件调试模块,该模块可在取指(指令断点)出或访问数据(数据断点)时停止。 内核停止时,可以查询内核的内部状态和系统的外部状态。完成查询后,可恢复程序执行。

# 8.2 查看函数段/函数执行时间

设置:魔术棒-> Utilities->settings->Trace->Core Clock 更改为适当的频率。

如 stm32f103rct6 就设置为 72 Mhz

# 8.3 call stack 窗口

可以查看函数调用栈。

# 8.4 寄存器窗口

可以查看寄存器的相关信息。

# 8.5 watch window

查看函数首地址和变量值。

可以设置全局变量在被读或者被写后自动停止运行。

# 8.6 Memroy 窗口

查看内存的值,在里面输入你要查看的内存地址,然后观察这一片内存的变化情况。

注意:内存的值是小端模式。

# 8.7 系统查看窗口

该按钮可以提供各种外设寄存器的查看窗口(通过下拉选择),选择对应外设,即可调出该外设的相关寄存器表,并显示这些寄存器的值,方便查看设置的是否正确。

# 8.8 仿真时要注意的点

仿真时,要注意优化等级选择为 0。

调试停止在断点处时,只是内核停止,外设会继续运行。

断点设置不要打断通信。

# 9 keil 设置

# 9.1 编辑器设置

  1. 使用 utf-8 编码。
  2. 显示空格。
  3. C/C++ 文件用空格替换 tab,一个 tab 换成 4 个 空格。
  4. ASM 文件用空格替换 tab,一个 tab 换成 4 个 空格。
  5. 其他文件用空格替换 tab,一个 tab 换成 4 个 空格。
  6. 更改注释颜色
  7. 编辑器字体,c/asm 设置为:size:14,Fira Code Retina字体。

# 9.2 代码补全&于法检测

  1. 回车键/tab 选中补全选项。

# 9.3 global.prop 文件保存设置

MDK 安装目录下 global.prop 文件。

# 9.4 编译选项

  1. 优化等级 O0
  2. C 语言标准 C99。

# 10 C 语言基础

# 10.1 位操作

1. 在不改变其他位的情况下,对某几个位进行设值

GPIOA->CRL &= 0xFFFFFFFBF // 将第 bit6 清零。
GPIOA->CRL |= 0X00000040; /* 设置 bit6 的值为 1,不改变其他位的值 */
1
2

2. 移位操作提高代码的可读性

SysTick->CTRL |= 1 << 1;
SysTick->CTRL |= 0X0002;
1
2

第一种操作比第二种操作可读性更好。

3. 按位取反操作

按位取反在设置寄存器的时候经常被使用,常用于清除某一个/某几个位。

// 仅设置 CTRL 寄存器的第 0 位(最低位)为 0,其他位的值保持不变。
SysTick->CTRL &= ~(1 << 0) ; /* 关闭 SYSTICK */
SysTick->CTRL &= 0XFFFFFFFE; /* 关闭 SYSTICK */
1
2
3

可读性/可维护性都大大提升。

4. ^ 按位异或

该功能非常适合用于控制某个位翻转

GPIOB->ODR ^= 1 << 5;
1

5. 移位

左移补 0,右移正数 补 0,负数补 1。

# 10.2 extern 外部申明

extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。

# 10.3 stdint.h

C99 标准引进的标准 C 库的文件

#include <stddef.h>
#include <inttypes.h>
1
2

# 11 stm32 基础知识

# 11.1 寄存器基础知识

寄存器(Register)是单片机内部一种特殊的内存,它可以实现对单片机各个功能的控制, 简单的来说可以把寄存器当成一些控制机构,控制包括内核及外设的各种状态。

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。

寄存器是CPU内部的元件,包括通用寄存器、专用寄存器和控制寄存器。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。

stm32 寄存器是 32 位的。

内核寄存器,我们一般只需要关心中断控制寄存器和 SysTick 寄存器即可,其他三大类,我们一般很少直接接触。

//  GPIOB 的 ODR 寄存器为例,其寄存器地址为:0X40010C0C,所以我们对其赋值可以写成:

(*(uint32_t *)) (0x40010C0C) = 0xFFFF;
// 全部 0XFFFF,表示 GPIOB 所有 IO 口(16 个 IO 口)都输出高电平。

// 以结构体访问方式:
GPIOB->ODR = 0XFFFF;
1
2
3
4
5
6
7

# 11.2 stm32 系统架构

1. Coterx M 内核 & 芯片

ARM公司提供CM3内核和调试系统,其他的东西(外设(IIC、SPI、UART、 TIM等)、存储器(SRAM、FLASH等)、I/O等)由芯片制造商设计开发。这里ST公司就是 STM32F103芯片的制造商。

2. F1 系统架构

详细模块框架图见数据手册 第 2 节。

简略框架图见参考手册 2.1 节。

1 是主动单元,2 是被动单元。

主系统由以下部分组成:

四个驱动单元:

  • M3 内核 DCode 总线(D-bus)
  • 和 system 总线(S-bus)
  • 通用 DMA1
  • DMA2

DMA,即直接存储器访问,DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。

互联型有五个主动单元,增加了网口。

四个被动单元:

  • 内部 SRAM
  • 内部闪存存储器
  • FSMC
  • AHB到APB的桥,连接所有APB设备。

主动单元可以主动发起通信指令。

总线时钟频率

内核最高频率:72MHz

AHB:72Mhz,APB1:36MHz,APB2:72MHz

SDIO(用于 SD 卡的 I/O)和 复位/时钟控制(RCC) 连接到 AHB 上。

# 11.3 存储器映射

参考手册 2.2 节:

程序存储器、数据存储器、寄存器和输入输出端口被组织在同一个4GB的线性地址空间内。数据字节以小端格式存放在存储器中。可访问的存储器空间被分成8个主要块,每个块为512MB。

stm32 寻址范围

  1. 32根地址线,每根地址线有两个状态:导通和不导通。
  2. 单片机内存地址访问的存储单元是按字节编址而不是 bit。

数据总线宽度是编址单位。如果数据总线宽度是 32,则按 4 字节编址。

数据总线宽度是 16,则按 2 字节编址。

处理器能处理的字长(数据总线宽度)越大,运算能力越强。

如 64 位电脑,字长是 64位,则一次能处理 8 字节,即数据总线宽度(64位)。

地址总线 32 位,内存最多大为 232 即 4Gb。

寻址范围:4G 字节。即 232

0x0000 ~ 0xFFFFFFFF

如 19 根地址线,16根数据线的存储器芯片,

寻址空间是:512kb,内存大小是 1Mb。

存储器功能划分

STB 将 4GB 的内存空间分为八块:

Block0:

Block1:

Block2:

存储器映射

存储器可以存储数据的设备,本身没有地址信息,对存储器分配地址的过程称为存储器映射。

数据手册中的存储器映像图:

# 11.4 寄存器映射

寄存器是特殊的存储器,给寄存器地址命名的过程就是寄存器映射。

0x4001080C 映射为 GPIOA_ODR

根据参考手册2.3 存储器映像,可查看外设和外设挂在的总线。

根据参考手册 8.2.4 端口输出数据寄存器的偏移地址是 0CH,而查询 参考手册 2.3 GPIOA 的起始地址是: 0x40010800 所以 GPIOA_ODR的地址就是 0x4001080C

复位值:寄存器复位后的值:0x00000000。高 16 位未用,低 16 位有效。

寄存器映射后操作:

#define GPIOA_ODR *(uint32_t *)(0x4001080c)
GPIOA_ODR = 0xFFFF;
1
2

寄存器地址计算

  1. 总线基地址(BUS_BASE_ADDR)
  2. 外设基于总线及地址的偏移量(PERIPH_OFFSET)
  3. 寄存器相对于外设基地址的偏移量(REG_OFFSET)

寄存器地址 = BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET

查询参口手册 2.3 存储器映像

总线基地址:

  • APB1:0x4000 0000 ,偏移量 0
  • APB2:0x4001 0000,偏移量 0x1 0000
  • AHB: 0x4001 8000,偏移量 0x1 8000

APB1 基地址,也叫做外设基地址。(PERIPH_BASE)

偏移量是相对于外设基地址来说的。

GPIO 外设基地址及偏移量:

GPIOB 寄存器相对外设基地址的偏移量:

结构体映射寄存器

typedef struct {
   __IO uint32_t CRL;
   __IO uint32_t CRH;
   __IO uint32_t IDR;
   __IO uint32_t ODR;
   __IO uint32_t BSRR;
   __IO uint32_t BRR;
   __IO uint32_t CKR;
}GPIO_TypeDef;

#define GPIOA_BASE 0x4001 0800

#define GPIOA ((GPIOA_TypeDef*)GPIOA_BASE)

// 使用
GPIOA->ODR = 0xFFFF;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

定义在 stm32f103xe.h 中,725 行开始。

# 12 新建寄存器版本 MDK 工程

# 12.1 准备工作

官网下载 stm32Cubef1 固件包。

下载 Patch_CubeF1 1.8.3

# 12.2 新建工程步骤

新建工程文件夹

目录下新建

  • Drivers 硬件相关的驱动层文件
    • BSP 存放开发板板级支持包驱动代码,各种外设驱动
    • CMSIS 存放 CMSIS 底层代码,如启动文件 (.s文件)
    • SYSTEM 核心驱动代码,如 sys.c,delay.c 和 usart.c 等。
  • Middlewares 中间层组件文件和第三方中间层文件
  • Output 工程编译输出文件,.hex/.bin/.o 文件等
  • Projects MDK 工程文件
  • User HAL 库用户配置文件、main.c 文件、中断处理文件、分散加载文件

5 个目录。

新建工程框架

  1. 新建工程

  2. 保存工程

  3. 选择主控型号

选择 stm32f103rc

  1. 删除文件夹

删除 Listings 文件夹(用于存放编译过程产生的链接列表文件)和 Objects文件夹(用于存放编译过程产生的调试信息、hex、预览、lib文件等)。

DebugConfig 文件夹用于存放调试设置信息文件,不可删除。

# 12.3 添加文件

1. 添加工程名:Templates

2. 新建分组:Startup、User、Drivers/System、Docs

3. 添加文件

3.1. 添加 startup_stm32f103xe.s 到 Startup。256kb <= flash <= 512 kb

3.2. 修改启动文件:

Heap_Size EQU 0x00000200
;未用到编译器自带的内存管理(malloc,free等),设置 Heap_Szie 为 0
Heap_Size EQU 0x00000000
1
2
3

3.3. 修改函数:

Reset_Handler   PROC
                EXPORT Reset_Handler [WEAK]
                IMPORT __main
                ;寄存器版本代码,没有用到 SystemInit 函数,注释以下代码防止报错。
                ;HAL 库版本代码建议加上,以初始化 stm32 时钟等。
                ;IMPORT SystemInit
                ;LDR R0, =SystemInit
                ;BLX R0
                LDR R0, =__main
                BX R0
                ENDP
1
2
3
4
5
6
7
8
9
10
11

4. 魔术棒设置

4.1. Target 选项卡

设置使用的编译器版本、外部晶振频率

Keil 5.35 版本后不能修改 Xtal,默认 12Mhz。

编译器选择 armcc V5.06(自行安装)

4.2. Output 选项卡

设置 Objects 输出文件夹、生成 hex文件、输出浏览信息

Output 文件夹定位到 ../Output

勾选生成 hex 文件。

4.3. Listing 选项卡

设置 Listing 输出文件夹 为 ../Output

4.4. C/C++ 选项卡

设置全局宏定义、优化等级、C99 Mode、头文件包含路径

添加宏定义:STM32F103xE

优化等级选择 0

如果编译器选择 armclang6,推荐优化等级 1

勾选 C99 mode

设置头文件包含路径。

..\Drivers\CMSIS\Device\ST\STM32F1xx\Include
..\Drivers\CMSIS\Include
..\Drivers
..\User
1
2
3
4

推荐在编写代码时包含路径时基于头文件指定包含路径

设置路径 + 相对路径

即表示当前头文件包含路径所指示的 4 个文件夹里面,肯定有某一个文件夹包含了: SYSTEM/sys/sys.h 的路径,实际上就是在 Drivers 文件夹下面。

两者结合起来就是:

#include "../../Drivers/SYSTEM/sys/sys.h"

如:

#include "./SYSTEM/sys/sys.h"
1

4.5. Debug 选项卡

设置使用的仿真器类型、选择下载接口

4.6. Utilities 选项卡

设置下载功能、下载算法、下载算法起始地址和大小等(部分芯片需要修改)

4.7. Linker 选项卡

添加分散加载文件(要用到 外部 flash)

4.8. Utilities

点击 --Use Debug Driver-- Settings

勾上 reset and run

5 新建 main.c 编写代码并添加进组 User

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"

int main(void)
{
    uint8_t t = 0;
    sys_stm32_clock_init(9);
    delay_init(72);
    usart_init(72, 115200);

    while (1)
    {
        printf("t:%d\r\n", t);
        delay_ms(500);
        t++;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
最后更新: 2023/9/12 08:24:09