STM32 F1(ARM Cortex-M3)开发绪论

——STM32 HAL库开发系列<1>

有很多同学寻求在STM32单片机开发或者ARM开发以及嵌入式开发这条路上快速入门,但是却被繁多的开发平台和晦涩难懂的专业名字搞得头昏脑胀,继而老虎啃天无法下嘴导致劝退。本文将通过对单片机的介绍、对ARM核心的介绍、对嵌入式开发的介绍以及对STM32系列的讲解和一个最小系统的实例来粗浅的介绍一个学习路线和入门途径。

1.什么是单片机/微处理器

文章的开头放一句暴论:单片机事实上和大家手中的智能手机和电脑并没有本质区别,就像泰山和珠穆朗玛峰也没有本质区别一样。在繁多的文章和视频中,我们总能听到这样稀奇古怪的英文缩写:CPU、MCU、MPU、DSP等等等等,那么要搞清楚他们的区别在何处,就需要先了解冯诺依曼结构定义下的计算机。作为我们的祖师爷之一,冯·诺伊曼老爷子提出计算机应当有五大结构:运算器、控制器、存储器、输入设备、输出设备,如下图所示。

在上图中,以一套PC机举例子,我们常说的CPU,也就是中央处理器(Central Processing Unit)包含了运算器和控制器两部分,事实上在现代微机技术中这两部分通常是高度集成在一个芯片之中的。例如我们要完成1+1=2这个简单的运算,就需要控制器命令运算器找到两个加数存放的位置,找到后执行加法运算,完成运算后将结果2放到指定地点。而存储器较为反直觉,它指的并不是硬盘、光盘这类存储介质,而是我们计算中的内存条,RAM(Random Access Memory),随机存储器,用于存放当前运行的程序需要立刻用到的数据;而我们所熟知的硬盘等存储介质事实上属于输入\输出设备中的一员。而CPU在发展过程中出现了三个经典分支:

  • MCU(Micro Control Unit)微控制器:一般集成了外围器件,例如充当“硬盘”的FLASH存储器
  • MPU(Micro Process Unit)微处理器:属于MCU的阉割版本,不带有外围器件,通常运算能力强
  • DSP(Digital Signal Processor)数字信号处理器:较于前者,功能单一,专用于处理信号的产品

嵌入式开发入门学习产品应当是所谓的“单片机”,也就是MCU。这类产品通常含有一个作为CPU的处理器内核,例如我们教程使用的STM32 F1就继承了ARM Cortex-M3内核;通常含有集成在芯片中的内存和所谓的硬盘,即FLASH存储器也称之为闪存,例如STM32F103C8T6,就在芯片内部集成了20KB的SRAM作为内存和64KB的FLASH存储器用于存储程序;同时我们应当认识到这样小小一枚芯片就相当于一台微型计算机,它同时包括了可以类比为南桥的AHB总线(Advanced High performance Bus)和相当于北桥的APB总线(Advanced Peripheral Bus),这两条总线上又可以含有很多的外设,例如常见的USB接口(是的,它含有片上USB2.0接口),用于通信的串口、IIC、SPI、CAN等等接口;当然也包括ADC(Analog-Digital Converter)用于将模拟信号转换为数字信号、生成脉宽调制波(PWM)的定时器以及众多的通用输入输出接口GPIO等等设备。

事实上,现代的单片机产品种类极其丰富,在数十年的发展中经历了8bit、16bit、32bit甚至64bit等等总线拓宽的产品革命,其运算能力和处理性能在不断提升,我们生活中常见的蓝牙音箱、蓝牙耳机、路由器、无线网卡等等产品的技术方案在硬件层绝大多数使用了单片机产品。下面列出在青少年教育以及嵌入式开发中大受欢迎的一些单片机开发板,例如51单片机、Arduino开发板、STM32开发板与近年来广受好评的物美价廉集成无线功能的国产芯片ESP32开发板:

2.STM32系列产品的特点与区分

在上一小节中我们了解了什么是单片机而STM32系列产品由于其优秀的生态支持、开发者友好、稳定的运行性能等优势加上正点原子不断的在相关从业人员和学生中进行推广,已经成为了国内很多学校甚至相关企业的主力开发平台。但是当我们打开淘宝或者京东希望为自己购买一块开发板开启嵌入式开发的大门时我们悲哀的发现自己被绊倒在门槛上——究竟如何从种类繁多的开发版和芯片中选择适合自己学习用途或者产品定位的款式呢?下面列出一些大受欢迎的相关产品,读者可以从中感受到选型的迷茫和纠结

  • STM32F103C8T6
  • STM32F103CBT6
  • STM32F103RCT6
  • STM32F103RET6
  • STM32F103VET6
  • STM32F103ZET6
  • STM32F030K6T6
  • STM32F407ZGT6
  • STM32F427ZET6
  • STM32F429VGT6
  • STM32H743VIT6
  • STM32MP157

那么如何从这浩瀚如烟海中的芯片类型中选出自己想要的芯片或者说如何分别这些长得乱花渐欲迷人眼的芯片类型哪,我们就以初学者常常使用的STM32F103C8T6进行分析,首先开头的ST代表这款微控制器是意法半导体(ST-Microelectronics)推出的产品;M代表搭载了ARM Cortex内核的嵌入式微控制器产品,32代表系统总线宽度是32Bit也就是我们通常说的32位机。而F1则代表本芯片属于ST公司的“主流微控制器”,具体型号可见下表:

  • 主流产品(MainStream):F0、F1、F3、G0、G4
  • 高性能产品(High Performance):F2、F4、F7、H7
  • 低功耗产品(Ultra Low Power):L0、L1、L4(+)、L5、U5
  • 无线功能产品(Wireless):WB、WL
  • 高性能Arm Cortex-A内核产品:MP1
  • 更加详细内容参见ST官网对32位MCU说明

所以型号中提到的F103就是主流产品F1系列中编号为03的芯片,这也是STM32系列产品的本质性划分标准,那么C8T6代表什么意思呢?C代表这块芯片具有48引脚,例如RCT6后缀就代表这块芯片具有64个引脚,8代表具有64KB的FLASH空间用于存储程序,B-128K,E-256K以此类推。而最后的两个参数在初学阶段一般用不到,T代表LQFP封装,6代表工作温度范围,这两个参数一般默认选用T6或者是有什么用什么,除非对于温度和封装具有特殊要求才做出改变。如下是ST官网放出的概略图和F103系列产品的介绍:

3.ARM相关与STM32芯片架构

在众多的材料中时常看到ARM这个关键词,那么ARM究竟是什么又与我们介绍的STM32有什么关系呢?首先,ARM处理器是英国Acorn有限公司设计的低功耗成本的第一款RISC微处理器。ARM处理器本身是32位设计,但也配备16位指令集。说的精简一些,ARM是一种处理器架构,例如大家经常使用的Intel与AMD公司推出的CPU就是x86架构,而Apple公司推出的M1芯片与移动端设备使用的高通、骁龙、麒麟都是ARM架构的处理器。那么ARM与STM32是什么关系呢?

前文中提到,微处理器MCU事实上相当于一个微型计算机,这里面的CPU其实就是所谓的“内核”是由ARM公司提供的,当然包括对内核的调试接口也是ARM提供的;而ST公司将自己自主研发或者配置的FLASH,外设,时钟电路等等外围设备与这个内核结合并且封装成芯片就是我们看到的单片机。也就是说当我们使用汇编语言编写程序时我们需要调用ARM的汇编语言,完成的工作也仅限于指导内核与外设按照我们想要的方式自动运行,这个过程中内核对我们来说相当于一个“黑箱”,我们仅需要负责其输入输出的指令和数据而并不需要关心内核内部是如何处理我们的指令的——这是ARM公司研发部门与ST公司调试部门的任务,应当与嵌入式开发工程师区分开来。

上图所示为STM32F1微控制器的系统架构示意图。首先可以看到右上角由ARM公司提供的内核与调试接口部分,在开发环境中配置的SWD(Serial Wire Debug)或者Jtag、Jlink等仿真调试接口在芯片中对接的就是这部分的调试接口。内核可以直接与FLASH和总线矩阵沟通,FLASH存储器中保存了芯片上电后自动运行的程序代码和数据,而运行时环境(RE,Runtime Environment)的数据存储在SRAM运行内容中。需要注意的是整个系统的“核心”、“重中之重”是系统的总线矩阵,它负责链接内核、存储器以及众多外设。系统总线可以理解为我们人体的神经系统,对上链接作为核心的大脑,对下链接作为外设的身体各个器官。

总线矩阵可以直接连接的设备中有一类非常特殊:FSMC设备,又称可变静态存储控制器,形象的来讲带有这个接口的芯片可以“外挂FLASH”也就是说可以扩展内存和运存,而没有这个接口的芯片仅仅可以使用芯片出厂时自带的相关存储器。然而很遗憾的是,在中小型MCU上是不搭载这种类型的接口的,只在VE或者ZE等高级设备上才会搭载。

外设中较为特殊的一部分是RCC,用于控制芯片复位,也就是重启,还有时钟信号。我们经常说一个CPU的运行主频、睿频是多少GHz,这个指的就是芯片的SysTick或者可以叫做“心跳计时器”,这种设备就像是我们的心脏一样,整个芯片执行命令的时序由这部分电路来控制,这是至关重要的一部分。

而DMA是一类极其特殊的外设接口,我们知道假设我们想将电脑上的USB摄像头采集到的图像显示在屏幕上就需要CPU和显卡的帮助,也就是说所有数据都要经过总线矩阵和内核的处理,当我们的数据对于实时性要求很高但是处理复杂度很低的时候这是个非常低效的沟通方式——你无法想象在平日学习中你问你的同桌借一块橡皮需要向班主任、教导主任、校长打报告层层审批,简直是个灾难性的方案。而DMA设备就给我们提出了解决方案——直通专线,它可以将数据在内存、外设、接口之间直接传输,F1产品提供两条这样的通道。

我们最常见的外设是搭载在AHB和APB两条总线上的,AHB相当于我们电脑上的南桥芯片,用于高速数据通信,因此我们不难想象为什么与SD卡通信的SDIO接口需要直接挂载在这条高速公路上——当我们要安装一款超大的软件或者游戏的时候我们通常选择安装在固态硬盘中而不是老掉牙的机械硬盘中。APB相当于电脑上的北桥芯片,它通信速率的要求相对AHB上的设备较为低下,但是可以产生很多变种:

  • GPIO:General Purpose Input/Output 基础的输入输出,例如按键与点亮LED灯
  • 串行通信接口:UART、IIC、SPI、CAN等等,足以兼容大部分的通讯协议
  • IWDG/WWDG:俗称的看门狗,用于检测芯片是否陷入死机状态——关键时刻救命
  • RTC:用于精确计时的外设接口,如果MCU用于某种时钟项目必不可少
  • USB:很可惜USB接口通常只能达到2.0Full Speed通信,但是可以外接USB-PHY芯片
  • ADC:Analog-Digital Converter用于将连续的模拟信号转换为数字信号,例如测电压
  • DAC:用于将数字信号通过双积分转换为模拟信号,可惜只有FLASH 256K以上才有
  • Timer:定时器,具有计时和定时中断,可实现PWM、编码器输入等时基函数功能
  • IIS:音频接口,如果要完成语音识别和音频播放,必不可少的硬件接口
  • 需要注意,所有外设都能通过GPIO进行软件算法模拟,但是硬件接口仍然高效而方便

4.STM32F103C8T6最小系统实例

在上文中介绍了STM32开发的相关入门知识,虽然笔者尽量使用了非专业术语的、通俗易懂的语言但是对于真正的零基础人群来说仍然令人昏昏欲睡切摸不着头脑,下文将分析一个STM32最小系统开发板的构造与下图所示的淘宝热销入门板子高度相像:

这里要先澄清一个基础概念,什么是最小系统?顾名思义,“最小”的意思就是缺少了任何一部分整个开发板将处于不可用或者无法发挥出芯片的完全功能的窘境之下。这里还是以装机过程做比喻,想完成一台电脑的装机过程什么是必不可少的呢:CPU、内存、主板、硬盘、电源、机箱/机架,如果考虑被动散热+服务器装机那么显卡、显示屏、散热或许都可以不考虑。同样的,下面列出对于一个STM32开发板来说”必不可少“的部分:

  1. STM32C8T6芯片:芯片包括了内核(CPU)、FLASH(硬盘+内存条)
  2. 外接晶振电路:STM32芯片可以并且大多数时间使用外接的高速且稳定的时钟信号
  3. 复位电路:一个按钮,用于RESET内核,没有的话将陷入频繁插拔电源的窘境
  4. BOOT模式选择电路:相当于进入主板BIOS的接口,如果没有将会限制功能
  5. SWD调试接口:用于芯片仿真程序与Debug,没有将无法调试
  6. 供电电路:使用线性稳压器LDO实现,芯片3.3V供电而很多时候外接电源5V
  7. USB接口:用于给芯片供电以及使用片上USB接口
  8. LED灯:有助于提升用户友好程度,毕竟Blink程序点灯相当于“Hello World”

首先,先看一下STM32F103C8T6芯片的引脚定义,立创EDA中官方提供的原理图封装如下所示,并且附上芯片部分的原理图,我们可以看到其中有8个引脚较为个数,标为红色的是3.3V电源输入,而标为黑色的是芯片的接地引脚,为了避免芯片工作时电压与外设及自身产生串扰,需要在四个电源输入引脚就近放置100nF电容,这里使用X5R或者X7R的C0603封装,根据ST官方给出的DataSheet可以看到每个引脚的定义。

首先要完成的是芯片供电电路,这里使用一个线性稳压器LDO,最经典的LDO莫过于LM7805这颗三端稳压器芯片,但是这里采用一种更小封装和功率的芯片——毕竟STM32芯片的最大峰值电流也不到300mA没必要杀鸡用牛刀,使用RT9193-33GB,能够输出3.3V电压。LDO稳压器要正常工作需要在输入端和输出端接入滤波电容,使用两颗X5R或者X7R陶瓷电容并联的方案,100nF与10uF,前者用于滤去高频小幅度的波动而后者用于滤去低频大幅度电压波动。原理图如下:

根据官方DataSheet可以看到,芯片的时钟源可以选择四种:LSI内部低速时钟,LSE内部高速时钟,LSE外部低速时钟,HSE外部高速时钟。前两者依靠片内的RC振荡电路实现,后两者依靠外部晶振电路实现。高速时钟接入一颗8MHz晶振,经过PLL锁相环后倍频9倍即可达到此芯片允许的最高速度72MHz;低速时钟接入一颗32.768KHz晶振,经过15次分频后即可得到标准的1KHz频率时钟。此处的晶振电路均由一个大电阻\(1M\Omega\)和两个100nF小电容形成高阻抗震荡电路,并且接入PC13与PC14构成的低速时钟接口和PD0与PD1构成的高速时钟入口。需要注意的是,时钟电路处于高速震荡状态,PCB布线时应当尽量采取平衡阻抗(说人话就是差不多长)的布线方式并且尽量接近芯片远离其他线路。原理图如下:

接下来要完成的就是芯片的BOOT电路与复位电路。市面上很多开发版将BOOT电路处理为跳线帽+排针的方式,但是个人认为这样不够美观并且占空间太大,所以此处采用一个2P拨码开关完成设计。可以从下方的原理图中看到开关非常简单,一端接入芯片引脚一端接地,而接入芯片的一端还可以并联一个上拉电阻结构,这样一来开关断开时由于芯片输入端口高阻抗线路中没有电流流过,芯片引脚拉高电平为1,当开关导通时输入引脚直接接地,由于有\(1K\Omega\)电阻的存在不至于短路或者电流过大引起局部发热。同时在开关的两侧并联一个100nF陶瓷电容用于增加稳定性和“消抖”,考虑到芯片读取电平速度大大高于人类切换开关状态的速度,如果不加入这种物理消抖的装置将会造成误判导致无法正常工作。

这里要额外说明一下BOOT电路的作用,具体工作方式和芯片内部改变将在以后的文章中进行分析。BOOT引脚包括BOOT0和1,其高低电平状态对应的工作方式如下表所示:

BOOT0BOOT1对应功能和启动方式
0X系统从FLASH代码0x08000000启动执行,多数情况下的选择
01系统从出厂Bootloader 0x1FFFB000启动执行,用于串口烧程序
11系统从内存SRAM代码0x20000000启动执行,用于快速调试

接下来是SWD调试接口和USB接口,这次绘制的开发板并没有绘制LED灯的部分,如果读者有兴趣可以自行添加,LED作用的方式非常简单,将LED的正极接入到GPIO输出或者电源输出,负极串联一个阻值适中的电阻后接地——阻值太大将会导致LED灯发光微弱,太小会导致大电流发热,以及给整个电路带来不好的影响。SWD接口非常简单,由4P排针构成,分别为3V3供电,GND接地,PA13引脚的IO与PA14引脚的CLK构成,当然考虑到供电波动,应该在正负极之间接入100nF滤波电容。

USB接口此处选用一个MicroUSB接口,事实上使用TypeC接口会更加友好但是这种类型的接口对于新手来说过于麻烦所以此处仍然使用MicroUSB接口,接口的四个固定点、接地引脚、ID引脚全部接地,供电引脚是5V电压供电,在D+和D-两条线上串入\(22\Omega\)电阻保证阻抗,同时两条线在布线时应当差分布线——USB信号是差分信号,PCB走线长度应当一致,同时将USB+通过\(1.5K\Omega\)上拉保证其静默时处于高电平。

此时所有最小系统必要功能均完成,可以开始整体的PCB布线工作,没有处理的芯片引脚统统通过单排排针引出,下面展示完成布线后的PCB图和3D模型图:

5.嵌入式开发学习路线

本文所指的嵌入式学习路线并不包括嵌入式Linux或者是嵌入式Android开发的部分,仅仅包括在MCU层次进行嵌入式开发的知识点和学习路线,该路线图包含内容较为齐全,要达成某个目标事实上可能仅仅需要学习其中的某一部分,比如本系列教程主要是面对HAL库的,故而在HAL环境下变成并不需要对寄存器编程和标准库编程做过多学习即可达成较为可观的工程能力。如下分别是编程环境与编程语言学习、硬件电路实现学习、各类功能原理与实现方法学习的路线,本教程也会尽可能覆盖这些方面。

You May Also Like

About the Author: Fenice

本人及开发团队主要兴趣领域为:自动控制理论、网站开发、移动端开发、嵌入式系统、机器人相关项目、电力电子技术、电动机控制。以及,兼任北京海淀区北下关街道反卷委员会常务委员长并且获得“全年度中国最佳懒狗”称号。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注