概述
Microchip的MCC能提升开发效率,程序员无需花费大量时间查阅数据手册即可快速配置微控制器。本文指出函数注册是连接MCC生成代码与程序员main.c程序的关键桥梁。这种注册方法提供了优雅的解决方案,可防止你的代码被MCC工具覆盖。
预计阅读时间:5分钟
密切关联问题
本文解答以下密切关联问题:
-
关于Microchip的MCC需要了解哪些事实?
-
与Microchip MCC Melody配合时的最佳代码结构实践是什么?
-
使用Microchip MCC时最大的陷阱是什么?
引言
Microchip的MPLAB代码配置器(MCC)是简化微控制器配置的图形界面工具。程序员无需花费数小时查阅数据手册手动配置外设,几分钟内就能直观完成微控制器配置。
我们将不探讨这个已有详尽文档的工具,而是聚焦一个常被忽视的集成问题。具体来说,如何将MCC生成的代码无缝集成到项目中。换句话说,我们将介绍最佳实践,确保在更新微控制器配置时MCC不会破坏我们的代码。
我们将以PIC16F13145 Curiosity评估板为例(图1)。
种子程序可在此处下载。
Digital.X.zip (957.8 KB)
图 1 :作者面包板上的PIC16F13145 Curiosity开发板,配有辅助按键和LED。
技术提示 :MCC对经验丰富的程序员来说是绝佳工具。但新手通过手动配置寄存器会获益更多。花几周时间研读数据手册能强化他们的技能。在我看来,这就像学习骑自行车。我们建立的数据手册肌肉记忆,将在出现问题时发挥重要作用。此外,学习一款微控制器(如主推的PIC16)是通向其他设备(包括其32位近亲)的入门途径。
可惜我们不再拥有纸质版的数据手册了。错误总是被高亮并加双下划线标注。比如误写TRIS寄存器而非端口寄存器——这个小错误让我花了数小时排查。
使用 MCC 工具
图2展示了一个典型的MCC项目。本例中,配置逻辑模块(CBL)和定时器零(TMR0)已被添加到项目。还包含系统级配置,如中断服务程序以及时钟和引脚配置等。
为保持文章简洁,我们将重点讨论按下高亮的"Generate"按钮后发生的操作。更多信息请参阅本页。
图 2 :使用MPLAB MCC配置PIC16项目的界面,其中Generate按钮已高亮显示。
MCC 代码生成器将数据存放在何处?
图3展示了项目文件结构。MCC生成的代码存放在明确标注的mcc_generated_files分支中。
关于 MCC 必须了解的事项
-
每次按下生成按钮(图2)时,MCC都会覆盖mcc_generated_files目录内容。
-
这些文件中的任何代码都将丢失,导致极大困扰。
-
此结构外的文件不会被修改。例如main.c文件就不会被MCC改动。
图 3 :MPLAB项目文件结构,重点展示mcc_generated_files目录。
如何将 MCC 生成的文件与 main.c 关联?
这是本文的核心内容。我们不修改MCC文件,而是利用C语言内置的函数注册机制。
函数注册示例
假设我们有个被main()调用的Bob ()函数。在机器层面,我们知道Bob函数被分配了一个由程序计数器操作的内存地址。我们可以使用函数指针将Bob函数重定向到Alice()。现在,当我们调用Bob函数时,实际上是Alice在执行任务。
首选的MPLAB代码模板如下所示:
- 超级循环不做任何操作。
- TMR0中断服务例程封装在函数My_1ms_Callback中。
- TMR0产生1毫秒中断。
- 连接到端口B第5引脚的LED每秒切换一次状态。
#include "mcc_generated_files/system/system.h"
volatile uint16_t msTicks = 0;
static void My_1ms_Callback(void){
if (++msTicks >= 500) {
msTicks = 0;
LATBbits.LATB5 ^= 1;
}
}
int main(void){
SYSTEM_Initialize();
/*
* Register the custom 1ms callback with MCC’s timer module.
*/
TMR0_OverflowCallbackRegister(My_1ms_Callback);
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
while(1){
;
}
}
清单 1 :展示函数注册过程的极简代码。
函数注册的操作
我们的目标是利用mcc_generated_files中的代码(图3),且不对MCC文件做任何修改——否则它们会被破坏。解决方案是将My_1ms_Callback注册到MCC生成的代码中。这就像之前的例子,我们调用Bob()但实际由Alice()执行。
函数注册通过这行简单代码实现:
TMR0_OverflowCallbackRegister(My_1ms_Callback);
就这样,这是实现main()与MC生成代码无忧链接的关键。函数注册是通往成功的桥梁。
结语
我不得不承认,和你们许多人一样,我也没有阅读Microchip的说明文档。曾有一段时间我对这些工具感到沮丧。希望这个小技巧能为你节省时间。
最后让我们向发明函数指针的Kernighan和Ritchie致敬。
相关文章
如果您喜欢本文,或许这些相关文章也能为您提供帮助:


