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.

[参考译文] MSP430FR5969:PWM 频率开关延迟

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1320065/msp430fr5969-delay-in-switching-pwm-frequency

器件型号:MSP430FR5969

您好!  

我正在尝试同时运行两个计时器:用于生成 PWM 的 TimerA 和 TimerB。

定时器 A: 时钟源是使用16MHz 外部晶振的 TACLK (由另一个安装了 Y1的 msp430fr5969的引脚3.4提供16 MHz)
定时器 B:时钟源为 SMCLK、该时钟源映射到16MHz 的 MCLK (DCO 源)

我的最终目标是以高波特率生成2FSK 信号、为此、我将使用计时器 A 作为我的波特率源、并使用计时器 B 来生成 FSK 的2个频率

相关代码片段:  

void set_cpu_freq () {

FRCTL0 = FRCTLPW | NWAITS_1;
CSCTL0_H = CSKEY >> 8;//解锁 CS 寄存器
CSCTL1 = DCORSEL | DCOFSEL_4;//将 DCO 设置为8MHz
CSCTL2 = SELM__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;
CSCTL3 = DIVA_1 | DIVS__1 | DIVM_1;//将所有分频器设置为1



int main (void){


WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器


P1OUT &&~BIT3;//清除 P1.0输出锁存器以实现已定义的上电状态
P1DIR |= BIT3;//将 P1.0设置为输出方向

P1DIR &=~BIT2;

PM5CTL0 &=~μ A LOCKLPM5;//禁用 GPIO 上电默认高阻抗模式
//激活先前配置的端口设置

set_cpu_freq ();

while (1){
//消息生成代码:生成包含二进制信息的数组

__enable_interrupt ();
TA0CTL = TASSEL__TACLK | MC_1 | TACLR;// SMCLK、向上计数模式、无分频器
TA0CCR0 =(16000000/10000)- 1;//根据 SMCLK 频率设置周期
TA0CCTL0 = CCIE;//启用中断
TA0CCTL1 = OUTMOD_7;

TB0CTL = TBSSEL__SMCLK | TBCLR | MC_1;// SMCLK、向上计数模式、/8分频器
TB0CCTL1 = OUTMOD_7;
TB0CCTL0 = CCIE;//启用 CCR0中断

delay_ms (100);




#pragma vector=TIMER0_B0_vector
__interrupt void Timer0_B0 (void)
{
  P1OUT ^= BIT3;//生成 FSK 频率  

__attribute__((interrupt (TIMER0_A0_vector))//控制 FSK 信号的波特率
void timer_a0_isr (void){

if (TX_COUNTER < TXLEN){

  如果(arr[TX_COUNTER]=0){
    TB0CCR0 =(CPU_FREQ/(2*300000))-1;
  }
  否则为(arr[tx_counter]== 1){
    TB0CCR0 =(CPU_FREQ/(2*400000))-1;
  }
  TX_COUNTER++;

否则{
  TX_COUNTER = 0;
  disable_signal ();
  msp430_timer_stop ();

问题:  

如下图所示、我观察到频率开关之间的延迟约为6-7微秒、最初我同时对计时器 A 和 B 使用 SMCLK、观察到同一个问题。 我假设这肯定是一个问题、原因是两个计时器都使用相同的源、即 SMCLK、我切换到了当前的设置、即为计时器 A 使用 TACLK、为计时器 B 使用 SMCLK、但同样的问题仍然存在、 导致波特率限制、因为6-7微秒间隙随着我增加波特率例如30kbps 变得更加显著。 我的目标是至少具有100Kbps 的波特率。


期待社区提出一些建议,以缓解这一问题。

此致!

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

    1) 1)我完全不知道 TASSEL_TACLK 是如何工作的、因为我没有看到 TA0CLK (P1.2)的 P1SEL1设置。 我建议您对两个计时器都使用 SMCLK。

    2) 2) 是否要求将 P1.3用作 FSK 时钟? 它看起来 P1.4可以输出 TB0.1、因此将 TB0CCTL1设置为 OUTMOD_4 (切换)将为您提供现在拥有的信号、但没有延迟。 我怀疑示波器跟踪中的这些差距源于此延迟(在 TA0CCR0 ISR 运行时)。

    3) CCR0更新有非常严格的最后期限(20或26个计时器周期)。 您可能需要考虑使用 DMA 代替软件来更新 TB0CCR0。 [参考数据表(SLAS704G)表6-12]

    我想(2)是您现在所看到的、(3)是您接下来将遇到的。

    [编辑:我刚刚注意到 P1.3可以提供 TA1.2 [请参考数据表表表6-50],所以如果你不能切换引脚(上面的(2)),这是一个选项。]

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

    1) 1) 我完全不知道 TASSEL_TACLK 是如何工作的、因为我没有看到 TA0CLK (P1.2)的 P1SEL1设置。
    出错了。 我删除了线路
    P1SEL1 |=(BIT2);//将 P1.2 SEL 设置为 TA0CLK
    写入查询时。 TACLK 正常工作是因为从 P1.2上移除跳线会导致定时器 A 没有输出。

    2) 2)我通过在代码中进行以下添加和更改、按照针对 FSK 输出的建议切换到了 P1.4:  
    int main (void){
      P1SEL0 |= BIT4;//将引脚1.4设置为特殊功能输出
      P1DIR |= BIT4;//设置通道1 PWM 的输出引脚1.4


    TimerB 配置:  

    TB0CTL = TBSSEL__SMCLK | TBCLR | MC_1;// SMCLK、向上计数模式、/8分频器
    TB0CCTL1 = OUTMOD_4;
    TB0CCTL0 = CCIE;//启用 CCR0中断

    删除了 TimerB 的 ISR

    输出频率卡在500kHz 的单个频率上、它应根据以下代码进行更改  

    __attribute__(interrupt (TIMER0_A0_vector))
    void timer_a0_isr (void){

    if (TX_COUNTER < TXLEN){

      如果(arr[TX_COUNTER]=0){
        TB0CCR0 =(CPU_FREQ/(2*300000))-1;
      }
      否则为(arr[tx_counter]== 1){
        TB0CCR0 =(CPU_FREQ/(2*500000))-1;
      }
      TX_COUNTER++;

    否则{
      TX_COUNTER = 0;
      disable_signal ();
      msp430_timer_stop ();



    编辑:可能是因为我不熟悉编程 MSP430、所以我在第二点中以错误的方式实现了解决方案

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

    2) 2)删除此行:

    TB0CCTL0 = CCIE;//启用 CCR0中断

    因为您不需要中断。 此外,如果没有 ISR,CCIE 将会触发调用 ISR_Fault (或一些类似的名称),它将永久旋转,这将导致您的症状。

    1)我不会与成功争辩,但使用 TACLK 不能获得任何东西。 我(仍)建议改用 SMCLK。

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

    它解决了我所面临的问题,非常感谢您的帮助 在过去的几天里,我一直在为这件事感到苦恼。
    关于 TimerA ISR、我想再问一点、环路频率限制在100kHz 但不能指出为什么我要检查引脚1.3的输出来检查 ISR 环路的频率。


    TimerA0配置:  

    TA0CTL = TASSEL__SMCLK | MC_1 | TACLR;// SMCLK、向上计数模式、无分频器
    TA0CCR0 =(16000000/200000)- 1;//根据 SMCLK 频率设置周期
    // TA0CCR0 = 1;
    TA0CCTL0 = CCIE;//启用中断
    TA0CCTL1 = OUTMOD_7;
    TA0CTL |= MC_1;//启动计时器

    __attribute__(interrupt (TIMER0_A0_vector))
    void timer_a0_isr (void){
    P1OUT ^= BIT3;
    if (TX_COUNTER < TXLEN){

    if (arr_dump[TX_COUNTER]== 0){
    // TB0CCR0 =(CPU_FREQ/(2*2000000))-1;
    TB0CCR0 = 3;  

    否则、if (arr_dump[tx_counter]== 1){
    // TB0CCR0 =(CPU_FREQ/(2*2000000))-1;
    TB0CCR0 = 2;  

    TX_COUNTER++;

    否则{
    TX_COUNTER = 0;
    disable_signal ();
    msp430_timer_stop ();



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

    位周期(符号速率)受更新 TB0CCR0的速度限制、在本例中、更新 TB0CCR0 ISR 需要多长时间。 由于这也与您之前的时钟延迟有关、因此您测得的持续时间(6-7us)是对 ISR 时间的合理估算、相当于略高于100kHz 的时间。

    修整基于软件的更新或许能够获得一点收益、但其结果却非常接近最小值。 此处的解决方案是 DMA (上述(3))。 在此模型中、arr_dump []数组将 包含 TB0CCR0值(长度为 TX_LEN),DMA 将在 TA0CCR0上触发以将连续值写入 TB0CCR0。 我在上面提到了 DMA 触发表;每次传输所需的时间在用户指南表11-3中、但这些都是非常快的、可供您使用。

    这里有一个针对模拟应用的此方法演示:

    https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1311814/msp430f6777a-msp430f6777a-microcontroller-high-speed-gpio-toggle

    细节不同、但原理是相同的。 那个会更新占空比(固定周期)、但它仍然使用计时器触发器来更新计时器寄存器。