This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430F249:定时器延迟

Guru**** 2539500 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/718133/msp430f249-delay-with-timers

器件型号:MSP430F249

您好!

这是我第一次使用 MSP430。

我开始处理一个使用 MSP430的项目。 一个老男人为 这个项目写了程序,我被要求修复它。

他不知道如何使用计时器、因此他执行了非常低效的延迟(具有"for "循环的函数)

现在、我想使用计时器和中断来提高 其效率。

但我不想太多(至少还没有)更改原始程序 ,因为它很长,而且可以正常工作。

因此、我需要一个延迟函数、该函数激活计时器、然后将 CPU 置于 LPM0中并等待中断

但是,我无法返回到延迟时间的"主要"地点。

我该怎么做?    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是每个人似乎都需要的东西之一、但没有公开的示例。 这是一个小型/简单的解决方案。

    它使用 Timer A (下面的"TA0")、但可以更改为使用 Timer B ("TB0")。 我在 Launchpad 上的 G2553上运行了该程序。

    标准免责声明:无保修、无支持、等等。

    [编辑:更正了拼写错误]

    //////
    tddemo.c
    // 使用计时器 A0实现简单延迟和时钟。
    // 设置 DEMO=1进行演示。
    // 无保修、无支持、等等。
    //
    #define demo 1. //在
    
    #include 下包含 main()程序 
    #include 
    define Hz 1000000UL //复位时时钟为~1MHz
    
    //#include "timer.h" //您可能需要其中一个最终
    为 extern void timer_init (void); //您可以
    extern void timer_wait_ms (uint16_t ms);//将这些
    extern uint16_t timer_fetch (void);// 变量
    
    uint16_t timer_ms;
    #pragma vector=TIMER0_A0_vector
    __interrupt void
    timer_ISR (void)
    {
    ++定时器_ms; //时钟节拍
    LPM0_EXIT; //唤醒前台
    return;
    }
    
    void
    timer_init (void)
    {
    TA0CCR0 = Hz / 1000 - 1; // 1ms 节拍
    TA0CCTL0 = CCIE; //中断
    TA0CTL = tassel_2 | ID_0 | MC_1 | TACLR;// SMCLK/1、向上计数模式(、清除)
    return;
    }
    
    uint16_t
    timer_fetch (void)
    {
    返回(timer_ms); //这很简单
    }
    
    void
    timer_wait_ms (uint16_t ms)
    {
    uint16_t start = timer_fetch ();
    while (timer_fetch ()- start < ms)//区分可避免一些竞争
    LPM0; //每1ms 唤醒一次以查看。
    return;
    }
    
    #if demo
    //
    //// main()
    //
    int
    main (void)
    {
    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
    // Launchpad P1.0 LED
    P1OUT &=~BIT0; //初始关闭(高电平有效)
    P1DIR |= BIT0; //输出
    timer_init();
    _enable_interrupt ();
    
    while (1)
    {
    P1OUT ^= BIT0; //切换 LED 以显示
    Timer_wait_ms (500); // 500ms -> 1Hz 闪烁
    }
    /*NOTREACHED*/
    返回0;
    }
    #endif // demo
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我可能应该提到:这种方法很适合多毫秒延迟。 这对于非常短的延迟没有用处。

    延迟要求越小,就越有用,例如__delay_cycles (),它不是低功耗的,但比 for 循环更可靠。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    多种不同的实现方式。

    我的应用中通常有一个自由运行的计时器、用于返回当前计时器节拍。 这样、下面的一段简单代码就可以正常工作:

     如果(tectches_Now ()- tectces_prev > DLY_ticks){//是否已经历足够的 tick

      ticks_prev += DLY_ticks;//更新前一个 tick 计数器

      do 什么();//执行用户代码

     }

    这种方法允许从一个(自由运行)定时器执行多个任务。 它具有高度便携性。 其缺点是如果 main()循环太长,它会受到抖动的影响。

    如果需要更多的实时应用程序,您可以安装一个计时器 ISR 来执行您的代码(如果它很短),或者在 main()循环中生成一个用于执行它的标志-同样,它受抖动的影响-如下所示:

     如果(timer_OVF ()){//if time is up - timer_OVF ()自行清除该标志

      do 什么();//执行用户代码

     }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢!!! 我不知道 LPM0_EXIT 命令存在... 你拯救了我! 很抱歉耽误你的时间!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢!!! 我也会尝试!