防止Microchip的MCC Melody覆盖你的代码

概述

Microchip的MCC能提升开发效率,程序员无需花费大量时间查阅数据手册即可快速配置微控制器。本文指出函数注册是连接MCC生成代码与程序员main.c程序的关键桥梁。这种注册方法提供了优雅的解决方案,可防止你的代码被MCC工具覆盖。

:stopwatch: 预计阅读时间: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致敬。

相关文章

如果您喜欢本文,或许这些相关文章也能为您提供帮助: