打印
[PIC®/AVR®/dsPIC®产品]

【Curiosity Nano测评报告】基于MCC的Timer0中断方式实现Blink

[复制链接]
7108|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
      使用MCC一段时间了,总的感觉还是相当不错的,但这款软件也有着很显著的缺点,帮助系统非常不完善,几乎完全靠摸索,尤其对于MCC生成框架代码后如何使用,很少资料参考。
       本文通过由MCC配置Timer0,采用中断方式实现Curiority Nano开发板板载LED闪烁功能的完整过程介绍,希望能对广大初学者有所帮助。

       新建基于开发板芯片PIC18F47Q10的工程项目,起名Timer0ISR_Blink,具体的过程请参考“”【Curiosity Nano测评报告】 外部引脚重定位之初体验(一)。
       单击MCC按钮,缺省保存后开始配置。首先在“System Module”选择内部时钟,4MHz,Clock Divider选择1,看门狗选择关闭,低电压编程允许。


      从Device Resource面板,添加Timer0模块。

      在Timer0配置面板中,首先选择时钟源为之前设定的HFINTOSC,这里顺便说一句,新的Timer0和我们过去熟悉的那个古老的Timer0不太一样了,可以工作在8位和16位两种模式,我们为了怀旧,还是用一下8位模式。
      另一个不同是现在Timer0有了前置和后置两个倍频器,当选择不同的倍频时,系统会自动计算出能够实现的定时范围,显示在Timer Period区域,这里我们希望LED的闪烁频率为1Hz,所以需要每500ms切换一次量灭状态。经过尝试,我们将前置及后置倍频器都调至最高,范围(2.048~524.288)ms,我们在Request Period输入框中输入期望的500ms回车后系统自动计算出能够实现的最接近的值,499.712ms,对我们的应用而言,足够了。
      勾选Enable Timer, Enable Synchronisation以及Enable Timer Interupt,如上图所示。

       接下来我们设置LED输出引脚,通过Curiorisity Nano开发板的电路原理图可以看到,LED与RE0引脚相连

      在Pin Manager面板中,将RE0设定为输出


      之后打开Pin Module面板,将RE0设置为单一的输出功能。为了之后编程的方便,此处最好给引脚起一个别名,本项目我们设定别名为“LED”


      至此,我们已完成MCC的配置流程,单击Generate,成功后关闭MCC。

      打开MCC为我们生成的tmr0.h,请大家注意这里的注解内容,它会简要介绍每个函数的功能和用法示例,当然,由于MCC还在不断的更新,所以可能这部分内容不是特别完善。但个人觉得,参考意义还是很大的。
       这里截取一段tmr0.h的内容

void TMR0_SetInterruptHandler(void (* InterruptHandler)(void));

/**
  @Summary
    Timer Interrupt Handler

  @Description
    This is a function pointer to the function that will be called during the ISR

  @Preconditions
    Initialize  the TMR0 module with interrupt before calling this isr.

  @Param
    None

  @Returns
    None
*/
      请大家注意描述部分,这个函数是专门用来设置在中断调用中执行的用户函数的。如果感觉很困惑,看一下tmr0.c中具体的中断执行代码,可能就清楚多了。红色部分的含义是,如果TMR0_InterruptHandler不为空,就执行这一函数。而之后的TMR0_SetInterruptHandler的功能,就是把输入的InterruptHandler函数指针,赋给TMR0_InterruptHandler,所以我们推断,设计一个符合要求的函数,用TMR0_SetInterruptHandler将其置为Handler,则在TMR0中断调用时,该函数就会执行。


void TMR0_ISR(void)
{
    // clear the TMR0 interrupt flag
    PIR0bits.TMR0IF = 0;
    if(TMR0_InterruptHandler)
    {
        TMR0_InterruptHandler();
    }

    // add your TMR0 interrupt custom code
}


void TMR0_SetInterruptHandler(void (* InterruptHandler)(void)){
    TMR0_InterruptHandler = InterruptHandler;
}


      初学者可能觉得很绕,为什么不直接在TMR0_ISR中断函数内直接编写需要的功能呢,这一圈绕的。开始笔者也有同样的困惑,而且也想当然的采用了自以为更正确简单的方式处理,结果就带来很多问题。
      下面填一下个人总结的经验、理解,可能不完全正确,仅供参考。经过一段时间的时间,对MCC的设计思想有了一定的理解,MCC是用来生成函数调用框架的,它生成的东西只能用,不能改
      个人对这种限制的理解是这样的,我们在开发过程中,会经常反复修改MCC实现的功能,这样当MCC重新生成对应框架代码时,就不能和用户编写的程序很好的协调。所以,对MCC生成的框架,我们只能在主程序或者另外的子模块中调用,而绝不要在原始文件里修改
     观察tmr0.h中TMR0_InterruptHandler的定义,

extern void (*TMR0_InterruptHandler)(void);
      

      根据功能要求,这个中断函数应该使LED的状态实现翻转,查阅MCC生成的pin_manager.h,我们找到了需要的函数LED_Toggle()



我们在主程序main.c中,#include之后,定义如下函数
void My_Timer0ISR(void){
    LED_Toggle();
}

       之后在main.c中,在SYSTEM_Initialize之后,调用 TMR0_SetInterruptHandler(My_Timer0ISR),然后将全局中断允许之前的注释取消,就完成了所有代码的创建。
      完整的main.c程序代码如下:

#include "mcc_generated_files/mcc.h"

void My_Timer0ISR(void){
    LED_Toggle();
}

/*
                         Main application
*/
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();
   
    TMR0_SetInterruptHandler(My_Timer0ISR);

    // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
    // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global and Peripheral Interrupts
    // Use the following macros to:

    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    // Enable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptEnable();

    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();

    while (1)
    {
        // Add your application code
    }
}


     编译运行后,Curiorisity Nano板载的LED正常闪烁。






使用特权

评论回复
沙发
huahuagg| | 2020-6-8 21:55 | 只看该作者
是的是 的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

144

帖子

1

粉丝