虽然可以使用微控制器模拟器来完成本教程的大部分内容,但我们强烈建议你购买一个微控制器学习开发板,或者只有一个裸μC芯片、各种元器件和一个供电面包板。此外,还需要一个针对你设备的C编译器,以及可选的汇编器。汇编器和C编译器都是免费的,还需要一种将程序下载到μC的方法,这个下载过程将取决于特定的μC和它所安装的面包板。
关于测试设备,数字万用表真的很便宜,没有理由不拥有一个。
嵌入式工程师都需要一个示波器。但本教程并不需要示波器。
我们将利用哪些微控制器系列?
为了介绍不同类型的微控制器,本教程将围绕一个8位微控制器系列(Atmel AVR)和一个32位微控制器系列(ARM Cortex M3架构,以STM32系列的形式呈现)编写。选择这两个系列是为了在微控制器领域提供一个相当广泛的设备和方法的图景。
关于这些教程中使用的微控制器,以下是我将为每个处理器系列使用的硬件和工具的详细信息:
AVR
•硬件:搭载ATmega8515的Atmel STK-500开发板
•工具:Atmel Studio 6(免费)
ARM Cortex M3
•硬件:STM32VLDiscovery开发板,安装在自定义对接板上
•工具:Rowley Crossworks(个人许可证价值150美元-建议使用IAR Embedded Workbench Kickstart Edition的免费工具集)
使用哪种编程语言?
我将在本教程中使用的两种语言是C和汇编语言。首先,我想指出的是,这些不是嵌入式程序员可用的唯一两种语言,在许多情况下,其他语言可能是更好的选择。话虽如此,C和汇编语言不仅有助于了解μC编程,还可用于实际进行有效的μC编程。同时,它们也是无处不在的,因为无论您选择什么微控制器,几乎肯定都会有汇编器(用于处理汇编语言源代码)和C编译器(用于处理C源代码)可用。而对于其他语言则不一定如此。但是,如果您有兴趣并且有可用于您的设备系列的其他语言,我鼓励您考虑其他语言。
关于汇编语言,即使您不打算在嵌入式编程中使用汇编语言,我强烈建议您至少熟悉其概念以及您μC的指令集。原因是即使您最终不写任何汇编语言(我现在几乎不写了),您在某个时刻需要检查编译器和/或编译器提供的启动文件的输出,该文件以汇编语言编写或输出。
此外,请注意,“汇编语言”一词在本教程和其他地方通常会缩写为“asm”或“ASM”。
嵌入式程序如何运行?
在更深入地讨论嵌入式编程之前,我们先来简要介绍一下嵌入式程序的启动和运行方式。
假设您已经生成了一个程序文件并将其加载到微控制器程序存储器中(这些步骤我们稍后会更详细地讲解),当您打开设备或按下 RESET 按钮时,好事就会发生。
无论是哪种情况,当微控制器从复位中恢复时,它总是会去到一个特定的内存位置,由制造商定义,开始执行那里找到或指向的任何代码。
有时,这个内存位置包含直接的代码,例如在复位后,程序执行从程序地址0开始。
其他情况下,固定的内存位置是一个向量,即保存程序开头实际地址的位置,例如在复位后,控制器将其程序计数器加载为在程序地址0xFFFE处找到的值,因此开始执行位于地址0xFFFE和0xFFFF位置中的代码(假设使用16位程序地址,存储在2个字节中)。
在第一种情况下,您需要确保程序已加载到指定的启动地址,而在第二种情况下,您将把程序加载到控制器地址空间中的程序存储器的任何位置,并确保将该启动地址加载到复位地址向量中。
请注意,启动方法的选择不取决于您,而是取决于您选择的微控制器的设计。AVR使用第一种方法,而Cortex M3使用第二种方法。
当嵌入式程序开始运行时,通常需要进行相当数量的初始化和后勤工作,这些工作在程序的实质部分开始之前必须完成。大多数此类初始化工作是桌面程序员从未见过的,因为计算机引导代码和操作系统会处理它们。但在嵌入式系统中,很可能没有操作系统,并且必须显式提供所有引导代码和其他启动代码。可能需要首先初始化一些非常关键的硬件,例如控制内存访问时间和地址映射的硬件,以及系统时钟硬件。然后可能需要进行一些软件初始化,例如设置堆栈指针并从非易失性存储器复制数据到易失性存储器,以便可以访问和修改。接下来通常会进行另一轮硬件初始化,设置系统所需的任何外围设备,并设置初始输出状态。最后,可能会发生另一轮软件初始化。
这个初始化通常分为两个部分,第一个硬件和软件初始化步骤通常在所谓的启动代码中完成,后续的硬件和软件步骤则在用户程序中完成。在C程序中,这种区分更为明显,启动代码对于C程序是不可见的,它是在main()运行之前发生的代码,并以跳转或调用main()结束,从而开始可见的C程序。在汇编程序中,所有初始化步骤可能在用户代码中同样可见,尽管即使在这种情况下,第一步也可能存在于单独的启动源文件中。