在 Linux 上开发 Atmel AVR 微控制器
无论您是创建小型互联网设备、硬件仪表、数据记录器,还是创建一支由自主机器人组成的军队来听您调遣,在很多情况下,您都需要可编程计算机的灵活性。在许多情况下,通用系统(例如您桌子下的主力机)不符合尺寸、成本或功耗的限制,而且简直是大材小用。您需要的是微控制器。
本文提供了逐步指导,介绍如何使用免费软件和 Linux 为 Atmel AVR 系列微控制器设置完整的开发系统。此处提供的详细说明将允许您将 Linux 系统转换为完整的 AVR 开发环境。本文将引导您完成构建、调试和安装简单程序的所有步骤。
当制造中央处理器 (CPU) 所需的所有电子元件(指令解码器、算术/逻辑单元、寄存器等)集成到单个芯片中时,您就拥有了一个微处理器。反过来,当您将此 CPU 与支持组件、内存和 I/O 外围设备捆绑在一起时,您就得到了一台微型计算机。进一步扩展集成和小型化,您可以将微型计算机的所有元素组合到单个集成电路中——瞧,微控制器。
半导体行业发展迅速,因此很难对微控制器一词提供准确而完整的定义。请考虑:一些微控制器芯片的容量和时钟速度超过了阿波罗登月舱计算机可用的 74KB 程序内存和 4KB RAM (该计算机重 30 公斤)。您可以预期今天的高配置 PC 将运行明天的嵌入式应用程序,微控制器的定义也会相应改变。
微控制器都具有微处理器内核、内存和 I/O 接口,许多还具有板载的其他外围设备。特定芯片的具体配置会影响其物理封装、引脚数量和成本。如果您习惯于使用微型计算机,您可能会觉得微控制器很紧凑。它们只有几个 KB 的程序 ROM 和大约 256 字节的 RAM。不过,别担心;在这个空间里可以做很多事情,正如麻省理工学院仪器仪表实验室在开发控制登月、从月球表面返回以及在轨道上会合的阿波罗登月舱软件时所展示的那样。
AVR 是具有哈佛架构(程序和数据存储器是分开的)的 8 位 RISC 平台。图 1 详细介绍了 ATtiny26 AVR 芯片的内部组织。像一个系列的每个成员一样,它具有自己的 I/O 和外围设备的特定组合,但它与所有其他 AVR 共享基本架构和指令集。ATtiny26 具有 2KB 的程序 Flash 存储器、128 字节的板载 SRAM 和 EEPROM、两个 8 位计数器和脉冲宽度调制器、11 个中断、分布在两个 8 位端口上的 16 个 I/O 引脚、一个 11 通道 10 位模数转换器等等——全部都在一个微小的 20 针 DIP 上。
许多因素使 AVR 微控制器成为一个不错的选择,尤其对于初学者来说。 AVR 是
易于编码:AVR 从一开始就被设计为允许使用高级语言轻松高效地进行编程,特别关注 C。
易于编程:板载可重编程 Flash 程序存储器和系统内编程接口的结合,使将软件传输到微控制器的过程变得简单且廉价。
功能强大且经济实惠:AVR 以低廉的价格提供强大的功能(1 MIPS/MHz,时钟频率高达 16MHz)和空间(高达 128K 的 Flash 程序存储器和 4K 的 EEPROM 和 SRAM)。大多数 AVR 甚至包括额外的外围设备,例如 UART 和模数转换器。
对业余爱好者友好:AVR 系列中的大多数芯片都采用易于使用的 8 针、20 针、28 针或 40 针双列直插封装 (DIP),并且可以从多个分销商处订购。
处理器内核由图 1 左上角部分的组件组成,包括用于读取程序存储器以及解码和执行该存储器中指令的元素。CPU 还可以将数据从 EEPROM、SRAM 和 32 个寄存器中取出和存储。这些寄存器充当 8 位值(1 字节)的极其高效的存储,并且 ALU(算术/逻辑单元)可以直接对 32 个寄存器中的每一个进行操作。此 AVR 具有基于 RAM 的堆栈。在其他一些没有任何 SRAM 的 AVR 中,堆栈是基于硬件的,将堆栈深度限制为三个。
大多数指令仅需一个时钟周期即可执行,并且 AVR 上没有内部时钟分频。CPU 在执行当前指令时,会获取并解码下一条指令。这些事实加在一起意味着 AVR 可以达到接近每 MHz 1 MIPS(每秒百万条指令)的性能。时钟频率高达 16MHz,您可以为特定应用选择速度、功耗和电磁噪声的正确平衡。
程序空间是一个连续的 Flash 存储器块,16 位宽,可以擦除/重写 10,000 次。您可以设计电路以允许使用系统内编程进行电路内固件升级。
所有 AVR 都有一些 EEPROM,并且大多数都有 SRAM;两者都是 8 位宽。EEPROM 旨在承受至少 100,000 次擦除/写入循环。EEPROM 很有用,因为它可以在嵌入式程序中写入,以保留数据,即使没有电源或在编程期间(例如在生产线校准中)。
所有 AVR,从微小的 8 针 DIP 到 44 针 Megas,都至少有一个数据端口。数据端口允许逻辑电平数据的输入或输出。AVR 端口是双向的,允许您在引脚上将它们设置为输入或输出。
许多 AVR 包括额外的硬件外围设备,例如用于串行通信的 UART 和用作内部系统时钟的校准 RC 振荡器。外部引脚通常具有两个或多个用途,它们的用途取决于您如何配置微控制器。例如,图 1 显示来自两个端口的某些 I/O 线可以与复用 A/D 转换器一起使用。
此处描述的工具集不是唯一可用的,但它允许您基本上做任何事情,并且这些工具可以很好地协同工作。该工具包由 Binutils、GCC、AVR Libc 和我们的 Makefile 模板组成,用于为 AVR 微控制器编写和构建程序;GDB 和 simulavr 用于调试您的软件;以及 avrdude 和硬件编程器,用于将您的软件传输到微控制器。请参阅在线资源,以获取所有软件的下载 URL。
幸运的是,所有这些工具的最新版本都包含对 AVR 平台的支持,因此安装非常简单。我们假设您已选择将所有内容安装在 /usr/local/AVR 下。
通过遵循资源中的链接下载当前 binutils 源代码的最新副本。解压源代码,移至 binutils-X.XX 目录,然后运行
$ ./configure --prefix=/usr/local/AVR --target=avr $ make # make install
/usr/local/AVR/bin 目录现在包含 ld、as、ar 和其他 binutils 可执行文件的 AVR 版本。现在将 /usr/local/AVR/bin 目录添加到您的 PATH。您可以通过添加
PATH="$PATH:/usr/local/AVR/bin"
从镜像中检索 Gnu Compiler Collection 的最新版本后,从解压缩的顶层源代码目录中运行以下命令
$ ./configure --prefix=/usr/local/AVR \ --target=avr --enable-languages="c,c++" \ --disable-nls $ make # make install
AVR Libc 包为 AVR 微控制器提供了标准 C 库的子集,包括数学、I/O 和字符串处理实用程序。它还负责基本的 AVR 启动程序,例如初始化中断向量表、堆栈指针等。要安装,请获取该库的最新版本,并从顶层源代码目录中运行以下命令
$ unset CC $ PREFIX=/usr/local/AVR ./doconf $ ./domake # ./domake install
Psychogenic 团队创建了一个标准的 Makefile 模板,简化了 AVR 项目管理。您可以轻松地为您的所有汇编、C 和 C++ AVR 项目自定义它。它为许多 make 目标提供了一切,从编译和上传到微控制器,到调试辅助工具,例如与反汇编混合的源代码,以及有用的 gdbinit 文件。可以进行模板的详细讨论,Makefile 模板在Linux Journal FTP 站点上作为列表 1 提供(请参阅资源)。将模板与其他 AVR 工具一起存储,将其移动到 /usr/local/AVR/Makefile.tpl。
通过结合使用 avr-gdb 和 simulavr,您可以通过模拟器在您选择的 AVR 微控制器上运行您的软件,同时使用 GDB 来单步执行和观察正在执行的代码。从项目站点获取 simulavr 源代码并执行安装
$ ./configure --prefix=/usr/local/AVR \ --with-avr-includes=/usr/local/AVR/avr/include $ make # make install
通过如下编译源代码来安装为 AVR 目标构建的 GDB
$ ./configure --target=avr \ --prefix=/usr/local/AVR $ make # make install
当您最终有一个程序准备好在实际硬件上进行测试时,您需要某种方式来上传数据并将其写入微控制器的 Flash 程序存储器。AVRDUDE 和兼容的硬件编程器是开发套件的最后两个组件。获取 AVRDUDE 源代码的副本并使用以下命令安装它
$ ./configure --prefix=/usr/local/AVR $ make # make install
您现在已经安装了完整 AVR 开发环境所需的所有软件组件。您所需要的只是将程序传输到微控制器的物理方式。
AVRDUDE 支持许多不同的硬件编程器配置。AVRDUDE 站点上描述了最简单的系统,它们仅由一个并行端口连接器、一个陶瓷振荡器和一个 DIP 插座组成。这些直接由计算机端口供电,可能并不适用于所有人。
更复杂一步,独立供电、带缓冲的系统内编程器可以很容易地构建(参见“资源”)。 Psychogenic 网页上讨论了两种只需要少量零件的编程器,其中描述了原理图,提供了电路板设计图,并有创建自己的印刷电路板的完整说明(如图 2 所示),适用于这些编程器。
也有许多商业解决方案可用。 如果您有兴趣轻松编程各种 AVR 系列芯片,请选择 Atmel 的 STK500 套件。 STK500 不仅仅是一个简单的编程器,它还是一个入门套件,允许您编程微控制器并轻松地进行新设计原型。 它包括许多 LED 和开关、一个振荡器、RS-232 接口和其他便利设施,可以很容易地与您的目标芯片连接。
我们这里的重点是开发系统,而不是 AVR 平台的编程。 对于在汇编、C 和 C++ 中编程 AVR 的信息,AVR Libc 文档是一个很好的起点。
微控制器世界的 Hello World 程序是经典的闪烁 LED。 Linux Journal FTP 站点上提供了一个稍微不同的主题,霹雳游侠迷们应该会喜欢。 在那里,您可以下载 C(列表 2)或 C++(列表 3)版本的示例程序,该程序会来回循环点亮八个发光二极管 (LED)。
创建一个项目目录——例如,~/helloavr/——并检索程序,将列表 2 保存为 ~/helloavr/kr.c,将列表 3 保存为 ~/helloavr/kitt.cpp。 此外,将 Makefile 模板 /usr/local/AVR/Makefile.tpl 复制到 ~/helloavr/Makefile。
使用此 Makefile 非常简单,并且可以轻松编译。 在您最喜欢的编辑器中打开 Makefile 并修改配置部分(在文件顶部附近),以便 MCU、PROJECTNAME 和 PRJSRC 变量设置如列表 4 所示。 MCU 变量确定我们要编译的 AVR 系列成员,PRJSRC 变量列出项目中使用的所有汇编、C 和 C++ 源文件。
列表 4. HelloAVR 项目 Makefile 配置选项
##### Target Specific Details ##### ##### Customize these for your project ##### # Name of target controller # (e.g. 'at90s8515', see the available avr-gcc mmcu # options for possible values) MCU=at90s8515 # Name of our project # (use a single word, e.g. 'myproject') PROJECTNAME=helloavr # Source files # List C/C++/Assembly source files: # (list all files to compile, e.g. 'a.c b.cpp as.S') # Use .cc, .cpp or .C suffix for C++ files, use .S # (NOT .s !!!) for assembly source code files. PRJSRC=kr.c
配置完 Makefile 后,编译和链接程序就像键入以下命令一样简单:make.
您也可以手动执行编译和链接步骤,通过发出以下命令:
$ avr-gcc -I. -g -mmcu=at90s8515 -Os \ -fpack-struct -fshort-enums \ -funsigned-bitfields -funsigned-char \ -Wall -Wstrict-prototypes -c kr.c $ avr-gcc -o helloavr.out kr.o
最显着的区别是添加了必需的 -mmcu 命令行参数,用于指定目标微控制器。 任何一种方法都会编译 kr.c 并创建 helloavr.out ELF 格式程序。 该文件无法在您的开发站上执行,但会在以后的调试阶段使用。
您还可以通过执行以下命令来构建 C++ 版本的程序:make clean,将 Makefile PRJSRC 变量更改为 kitt.cpp,然后再次发出:make.
Makefile 的一个有趣的目标是 disasm,无论是为了进行健全性检查、优化、底层调试,还是仅仅为了了解 AVR 的内部结构。 运行$ make disasm会将一些有关程序的信息(例如其 text/data/bss 大小)打印到控制台,并创建 helloavr.s。 该文件包含可执行文件的反汇编版本,与原始 C 源代码混合在一起。 浏览一下,可以看到 AVR Libc 和 avr-gcc 在幕后所做的工作,初始化中断向量表和数据,然后是程序的汇编和 C 版本。
现在我们使用 GDB 作为源代码级调试器,并以 simulavr 作为远程目标运行。 为此,在后台启动 simulavr 并创建一个合适的 gdbinit 文件
$ simulavr --gdbserver --device at90s8515 & $ make gdbinit
以这种方式运行make会创建 gdbinit-helloavr,该文件包含用于正确设置 GDB 的说明,以便它连接到 simulavr,加载编译后的程序,插入断点并开始执行。 使用以下命令启动 avr-gdb:
$ avr-gdb -x gdbinit-helloavr
您将看到 GDB 提示符; 程序执行在 main() 中的第一条指令之前暂停。 在第 71 行设置断点,使用b 71,然后按几次 C(继续)。 每次您单步执行第 71 行的指令时
71 PORTB = ~currentValue;
如果您已经构建或购买了编程器硬件,则可以在真实的 AT90S8515 芯片上安装和测试该软件。 通过设置 AVRDUDE_PROGRAMMERID 和 AVRDUDE_PORT 变量来配置 Makefile 中的 avrdude 部分,如上面的注释中所述。 使用
AVRDUDE_PROGRAMMERID=stk500 AVRDUDE_PORT=/dev/ttyS0
用于连接到第一个串行端口的 STK500 编程器。 确保编程器已连接到相应的端口,将微控制器插入编程器,供电,然后键入make writeflash。 这会生成 AVRDUDE 使用的 hex 文件,并将其内容写入芯片的 Flash 程序存储器。
对于使用 STK500 开发套件的用户,只需使用十线电缆将 PORTB 连接到八个板载 LED(如图 3 所示),并观看 das blinkenlights。 您可以通过构建如图 4 所示的原理图来设置您自己的测试硬件,该原理图将 LED 与合适的限流电阻连接,以便 PORTB 的每个引脚可以通过拉低并吸收电流来激活一个 LED。
您已经看到了闪烁的 LED? 恭喜你; 您已准备好开始创建自己的 AVR 设计和软件。 请参阅“资源”以获取大量 AVR 相关的信息和项目。 你几乎可以做任何事。
Atmel 通过其 AVR 应用笔记分享了许多有趣的项目创意,其中详细介绍了步进电机控制器、红外遥控接收器和发射器的实现,甚至是一个嵌入式 Web 服务器。 一个令人惊叹的项目 ContikiOS(请参阅“资源”)发布了一个开源的、支持 Internet、多任务、图形化的操作系统,该操作系统已移植到 AVR,并使用 VNC 服务器的版本而不是常规屏幕。
尽情体验这些多功能微控制器,请务必分享您的发现,祝您构建机器人军团好运!
Patrick Deegan 在麦吉尔大学攻读数学和物理联合课程时接触到 Linux 后,转行到 IT 和自由软件。 在从事物理、电子和软件开发之间摇摆不定,Pat 注定要共同创立 Psychogenic,现在他可以在那里花很多天(和夜晚)来玩这三者。