本文介绍了对称应用笔记PIC1000和AVR1000b,展示了它们如何应用于非凡的MPLAB®代码配置器(MCC)生成的代码。本文将介绍如何使用这些应用笔记来查看MCC的幕后情况,作为生成的裸机代码的参考。或者,如果您从裸机应用笔记开始,学习如何从头开始编写裸机代码,本文将向您展示如何更自信、更灵活地将这些知识应用于 MCC 设计。这是您的选择!应用笔记详细描述了每种架构的命名约定和寄存器访问方法的原因,以帮助您理解低级PIC®和AVR® MCU代码之间的差异。无论您如何进行设计,您都能够快速编写裸机 C 代码并了解 MCC 生成的驱动程序。
为您的应用选择 MCU(基于差异化外设,而不是特定 MCU 系列的经验)
Microchip结合了令人印象深刻的PIC和AVR微控制器(MCU)系列,拥有市场领先的8位MCU系列。作为嵌入式工程师,理想情况下,为给定项目选择MCU取决于哪种器件(外设)最能实现应用中难以实现的功能。通常,这是由该MCU上差异化外围设备的组合决定的。例如,您可能有严格的模拟测量应用要求,需要仔细检查MCU的模数转换器(ADC)。在一个应用中,PIC MCU的10位模数转换器(ADCC)外设(视频)可能具有优势,因为支持各种类型的内核独立后采样计算。对于另一个应用,AVR MCU 的 12 位差分 ADC 可能因其分辨率或与 AVR MCU 的事件系统配合使用而具有优势。两种ADC均提供相对专业化的功能,根据应用要求提供某些优势。
通常,熟悉的生态系统的支持会对MCU的选择产生重大影响。为了专注于为其设计选择最佳的MCU和外设,在过去几年中,我们付出了巨大的努力来调整PIC和AVR MCU产品系列的工具支持。Microchip仍然致力于支持Atmel Studio 7和Atmel START生态系统中的新AVR设备。除此之外,AVR MCU还被添加到MPLAB X集成开发环境(IDE)和MPLAB代码配置器(MCC)中,统一了这些MCU系列之间的开发体验。通用工具生态系统的支持旨在让您快速使用新的MCU系列,从而大大降低探索的障碍。然而,对于嵌入式开发人员来说,使用MCU进行舒适的开发比工具生态系统更深入,一直到寄存器级或裸机编码。
了解项目中的所有代码
MPLAB 代码配置器 (MCC) 或 Atmel START 等代码生成工具是节省大量设计时间的绝佳方法。但是,如果您不了解这些工具生成的代码,您可能永远不会完全适应它们。具有讽刺意味的是,您可能只有在不再需要该工具时才信任它。作为嵌入式开发人员,您也知道,如果不至少自己修改一些寄存器级代码,就不太可能进入生产环境。
裸机编码:使用器件数据表和头文件作为主要编程参考
MCU由多个构建模块或模块组成:CPU、SRAM、闪存、EEPROM和外设(例如ADC)。这些都在器件数据手册中定义,可通过寄存器进行配置。“裸机编码”中对“金属”的引用是指器件寄存器,因此它是指编写配置 MCU 模块所需的寄存器级代码的做法。此寄存器级代码的形式受器件头文件的影响,而器件头文件又受MCU外设模块结构的影响(数据手册)。因此,高效编写裸机代码需要具备数据表模块结构以及头文件定义的工作知识。因此,除了代码示例外,在此级别进行开发的主要编程参考通常是MCU数据手册和器件头文件。
裸机编码是一种嵌入式开发技能,往往在同一MCU系列的多个项目过程中掌握。对于特定的MCU,工程师熟悉MCU系列的数据表模块和头文件的隐式模式。了解这些模式有助于该MCU系列的快速开发,但也会产生选择不同MCU的阻力,即使它可能更适合新项目。随着时间的推移,能够快速处理与头文件定义相关的命名约定,使工程师能够利用现代 IDE 的代码完成功能,例如 MPLAB X IDE(或 Atmel Studio)。
虽然本文中使用的示例引用了 MCC 中的代码,但这些课程同样适用于从头开始编写代码。MCC 生成的项目的编码样式和项目结构可能与您自己实现的项目不同。但是,在寄存器级别,MCC 生成的代码与手动编码的代码非常相似。因此,MCC生成的代码被用作示例上下文,通过我们从PIC1000和AVR1000b应用笔记中了解到的内容,探索PIC和AVR MCU寄存器级代码之间的差异。在此过程中,我们还将指出一些您可能不知道的有趣的 MPLAB X IDE 编辑器功能。
MCC ADC 驱动器,用于 PIC MCU(带计算功能的 ADC)和 AVR MCU(12 位差分 ADC)
MCC 中的外设驱动程序完全支持模块的功能,包括可能促使您选择 MCU 的所有差异化功能。因此,无论您是否决定在生产中使用此生成的代码,MCC 都是快速评估这些外围设备性能的好方法。下图列出了PIC和AVR MCU的ADC外设驱动器的所有API功能。如您所见,由于外围功能不同,因此 API 自然也不同。但是,在基本级别上,它们仍然是ADC驱动程序,因此具有通用功能,因此具有许多通用API。例如,如果您只是对获得ADC结果感兴趣,则在这两种情况下,您只需调用:ADCx_GetConversionResult()。
图1: 为带计算的ADC提供API(PIC18F47Q10)和带窗口的ADC(AVR128DA48);在此处查看图 1 的高分辨率版本。
注意:图 1 中显示的导航器默认位于项目仪表板旁边。它也可以从MPLAB X IDE的右上角搜索栏中打开。
图 2 中 MCC 生成的 ADCx_GetConversionResult() 代码清单显示了此函数在 PIC18F47Q10 和 AVR128DA48 上的各自实现。MCC 驱动程序往往相对平坦。函数很少调用其他函数,但如果它们调用其他函数,它们往往紧邻。请注意函数中的代码如何使用寄存器级代码直接实现所需的功能,类似于您可能手动编写的代码。
在大多数情况下,MCC 生成的代码是根据为相应 MCU 系列编写代码的标准最佳实践方式量身定制的。因此,编码风格与Microchip应用工程师手写的应用笔记或技术简报中的代码非常相似。但是,您还会注意到PIC MCU的代码与AVR MCU的代码之间存在显著差异。
图 2:MCC 生成的 ADC 驱动器功能代码,在给定通道(PIC 和 AVR MCU)上返回转换结果;在此处查看图 2 的高分辨率版本。
PIC1000和AVR1000b应用笔记的背景和动机
在Microchip,精通为PIC或AVR MCU编写裸机代码的应用工程师最初依赖于MCC或Atmel START等工具,他们不会自然地无缝过渡到另一个。就我自己而言,在Microchip位于挪威的特隆赫姆办事处(AVR MCU的故乡)工作,我更有信心将MCC用于AVR MCU,而不是PIC MCU。正如我上面描述的,只有当您可以编写它们自己生成的代码时,人们才能 100% 适应这些工具。由于我发现为 PIC MCU 编写基本的裸机代码非常具有挑战性,因此这是意料之中的。此外,代码完成只有在您知道模式后才有效,因此在尝试编写寄存器级 PIC MCU 代码时,我得到的帮助非常少,令人沮丧。
图3:启动ADC转换的代码完成帮助(适用于PIC和AVR MCU);在此处查看图 3 的高分辨率版本。
涵盖该主题的经典应用笔记是AVR1000:为XMEGA编写C代码入门。这是在2008年发布的,当时对当时新的AVR MCU系列XMEGA的(外设)模块结构和头文件进行了扩展和改进。这些相同的约定在内部应用于此后发布的所有新AVR MCU设备。在描述所有新AVR MCU器件的C代码编写模式方面,本应用笔记可能并不明显。此外,还需要某种形式的文档来帮助理解寄存器级PIC和AVR MCU代码之间的差异。
为了利用AVR或PIC MCU的现有经验,我们创建了两个应用笔记。它们被设计为并排读取,以便熟悉其中一种架构的客户(或Microchip应用工程师)可以轻松发现两者之间的差异,并更快地启动和运行另一种架构。
让我们探讨这些对称应用笔记,它们旨在帮助理解低级PIC和AVR MCU代码之间的差异:
● AVR1000b:AVR C 代码入门
● PIC1000:开始编写 PIC16 和 PIC18 的 C 代码
以下各节给出了PIC1000和AVR1000b应用笔记各章节中涵盖的内容示例:
● 第 1 章:数据表模块结构和命名约定
● 第 2 章:头文件中的模块表示
第3章:为PIC和AVR MCU编写C代码(PIC1000和AVR1000b)
● 第 4 章:展示代码编写替代方法的应用示例
第1章:数据表模块结构和命名约定(PIC1000和AVR1000b)
裸机编码熟练程度不容易从一个MCU产品系列转换为另一个MCU产品系列的至少部分原因是数据表模块的组织模式往往是隐式的,并且通常需要推断命名约定。
每个章节的第一章都试图通过对模块组织和命名约定提供明确的指导来解决这个问题。
图 4:PIC 和 AVR MCU 的寄存器命名约定(摘自 PIC1000、AVR1000b);在此处查看图 4 的高分辨率版本。
例如,让我们考虑AVR和PIC MCU相对于ADC控制寄存器的寄存器命名约定。
图 5:AVR 和 PIC MCU 的 ADC 寄存器摘要摘录;在此处查看图 5 的高分辨率版本。
在 MPLAB X IDE(或 Atmel Studio 7)上工作时,可以使用 IO 视图找到寄存器、位和位字段的有用工作视图。如果启动调试会话,您将能够直接操作寄存器位,例如打开/关闭电路板上的LED。
图 6:使用 IO 视图查看模块寄存器、位和位字段。在调试模式下,此状态将为实时和交互式;在此处查看图 6 的高分辨率版本。
注意:您还可以使用 IO View 作为使用数据表的更有效方式,方法是选择寄存器,然后单击 pdf 图标。这将在该寄存器的上下文中打开数据表的 HTML 版本。最新的 PIC 和 AVR 设备支持此上下文帮助。
此外,对于AVR MCU,您还可以使用编辑器浏览HTML数据表。这是通过选择外围设备来完成的。注册,然后单击 PDF 数据表图标,请参见图 7。另请参阅 MPLAB® X - 上下文数据表帮助和 AVR® 中断(2 分 38 秒)。
图 7:来自 IO 视图(以及来自 AVR 编辑器)的数据表上下文帮助;在此处查看图 7 的高分辨率版本。
第2章:头文件中的模块表示(PIC1000和AVR1000b)
在本章中,您将找到PIC和AVR MCU的各种器件头文件定义的摘要,例如结构、联合和位字段掩码。这些定义将确定在为设备编写代码时将获得哪些代码完成帮助。使用这些定义,您的代码将比简单地将十六进制值分配给寄存器更具可读性。即使您注释了代码,如果注释已过时,也可能具有很难调试的代码。
让我们再次考虑图 1 中使用的代码完成示例。
对于PIC MCU,ADCON0寄存器中位的原因码完成选项是由于ADCON0bits_t的类型定义,由器件头文件中的结构和联合位字段定义组成。
对于AVR MCU,代码完成之所以建议ADC模块的ADC0实例中的寄存器列表,是因为定义了ADC_t结构,该结构由ADC模块中的所有寄存器组成。
图 8:由于位域定义 (PIC MCU) 和ADC_t结构 (AVR MCU) 以及 AVR/PIC MCU 头文件中的代码完成;在此处查看图 8 的高分辨率版本。
注意:AVR MCU模块的寄存器名称不是唯一的,即MCU中可能有多个ADC模块实例,此外可能有多个类型的模块具有CTRLA寄存器。因此,对于AVR MCU,寄存器仅在特定模块实例的上下文中完全定义。但是,PIC MCU在寄存器名称中内置了模块和实例,即ADCON1。
注意:对于 AVR MCU,可以选择模块实例寄存器定义。
图 9:AVR MCU 的模块实例寄存器定义;在此处查看图 9 的高分辨率版本。
第3章:为PIC或AVR MCU编写C代码(PIC1000和AVR1000b)
相关应用笔记的本章介绍了与器件寄存器写入相关的一些关键用例。使用第 2 章中讨论的设备头文件中的各种构造,给出了以下用例的最佳实践建议:
● 设置和清除寄存器位
● 配置寄存器位字段
● 更新/更改寄存器位字段
请注意,更新寄存器与设备重置后处于已知状态时该寄存器的初始配置不同。为了仅更新预期的位或位字段,需要考虑读取-修改-写入注意事项。
在本文使用的示例中,MCC 生成的代码编写如下,但是,有几种替代方法。
第 4 章:展示代码编写替代方法的应用示例
在本章中,为编写寄存器级代码的每种替代样式提供了代码清单。使用一个简单的应用程序,配置引脚,然后在按下按钮时打开LED。然后针对应用笔记的PIC MCU和AVR MCU版本支持的每种不同编码样式提供代码清单。这些代码清单可能是促进公司代码样式讨论的有用参考。例如,如果您正在规划同时使用 PIC 和 AVR MCU 的项目,那么位掩码或位位置样式可能允许 AVR 和 PIC MCU 之间的代码非常相似。
总结
这些对称应用笔记《为PIC/AVR编写C代码》(PIC1000和AVR1000b)旨在帮助工程师更轻松地编写可读寄存器级C代码,具体做法是:
在器件数据表中显式定义模块模式和命名约定
描述每个MCU模块的器件头文件结构和定义
提供访问和操作寄存器的最佳实践编码样式示例
无论您是从头开始编码,还是试图更好地理解 MCC 或 Atmel START 生成的代码,或者希望通过权衡选项做出明智的编码风格决策,它们都应该很有用。此外,这些应用笔记并排使用,有助于理解低级PIC和AVR MCU代码之间的差异。
具体来说,已经尝试理解MCC生成的代码,并充分利用MPLAB X IDE功能,如代码完成和IO视图,以便编写易于阅读的最佳实践C代码。视频中演示了其中许多MPLAB X IDE功能:MPLAB® X - 上下文数据表帮助和AVR中断,在编写按下按钮时打开LED所需的裸机AVR®代码的过程中。
因此,如果您习惯于为 PIC 或 AVR MCU 编写裸机代码,为什么不尝试在另一个上获取基础知识呢?
审核编辑:郭婷
全部0条评论
快来发表一下你的评论吧 !