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.

[参考译文] MSP430FR5739:在MSP430平台上生成任意定时脉冲

Guru**** 2595150 points
Other Parts Discussed in Thread: MSP430FR4133

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/660487/msp430fr5739-arbitrary-timed-pulse-generation-on-msp430-platform

部件号:MSP430FR5739
主题中讨论的其他部件:MSP430FR4133

我需要从GPIO创建不同宽度的脉冲。   脉冲本身不是频率,而是重复高-低条件的任意定时,然后循环回自身以形成周期结构。   例如,我正在尝试使用定时器A来形成以下2个脉冲序列(不同时)  

问题是,我不能确切知道该做些什么,以何种方式使所有这些都发挥作用。   我**认为**我必须在连续模式下运行定时器A,并更新ISR中的TACR0。   此MSP430 Launchpad附带的示例非常不充分,因为它只显示50 % 占空比下的单个频率。   我可以很容易地做到这一点。   我还不能将所有关于“Timer_A”和“Timer0_A3”的信息与各种CCRx寄存器的中断向量信息结合在一起,如果没有某种代码示例,则解列太复杂。  

(1)作为MSP430计时器模块的专家,您将如何处理此问题?  代码的结构如何?

(2)我担心ISR延迟。   这些脉冲必须始终在每个重复周期的相同确切时间发生。   由于ISR内的CCR0更新,不能在严格计时中添加一个或两个额外的时钟周期。  也许我错了应该如何做到这一点。  在Timer_A数据表的"使用连续模式"部分中,表示 "在此用法中,时间间隔由硬件而不是软件控制,不受中断延迟的影响。"   我完全不理解这一点,因为在ISR中修改/添加TCCR0确实是“由软件控制”,  这背后的解释是什么?  其他模式(启动,连续等)  是否不同并受软件控制的延迟影响?   如果是,它们有何不同?为什么不同?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    处理器是否正在执行其他操作? 您始终可以设置计时器刻度(如Arduino "millis ()"),并按您需要的任何顺序对GPIO进行快速编程。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    首先,您必须接受每个时钟都有抖动的事实。 实际上,没有什么是完美的。
    其次,应将ISR延迟计算为时钟。 因此,如果您需要逻辑1表示1毫秒(+/-一些错误),并且中断延迟为10us (+/-一些错误),则必须确保逻辑1时间为990us,这样总计为1ms (+/-一些错误)。
    第三,你不清楚这里“任意”的意思,“任意”波形会重复吗? 还是永远不会重复?

    如果它们不会重复,那么这只是为计时器生成随机数并更改输出的问题。如果是这种情况,并且如果您需要为随机性建立已知边界, 然后必须实现随机数生成方法,使其完成周期数相同。 如果您不需要建立已知边界,那么您的数字生成方法可能会有所不同,您可以将其视为随机性的一部分。

    但是,如果它们需要重复,则需要预先生成信号矢量,然后将其馈入计时器。

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

    我有代码,并且大部分工作方式都是我想要的。  一些直接取自TI的示例,有些是我写的。  我想更新此线程,以防将来有人需要此线程。   目前,我有一个使用下面的代码运行的FR4133,但我打算在最终应用程序的FR5739上运行它。  

    #include <msp430fr4133.h>
    #include <main.h>//
    
    定时器A设置为2us tick时间 
    // pulseTiming[]是一个全局值,并且保持高/低交替 无符号int pulseTiming[8]={10,10,20,20,30,40,40}的tick数;
    //保持编号更新为脉冲中相同数目的条目Timing;
    //无法找到其他方法来动态更新此值
    //在下面对其进行硬编码。 volatile unsigned int numDges =8;
    //跟踪我们在重复脉冲循环 volatile unsigned int pulseIdx =0; int main(void) { WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器 P1DIR |= BIT5; //将WFP 1.5 设置为输出,并对其进行范围调整 initClock(); initTimerA(); enableConfig(); __bis_sr_register (GIE); //启用全局中断 同时(1) { // MCU处于活动状态信号 P1OUT ^= BIT0; __DELAY周期(400万); } }//main() void initClock(void){ P4SEL0 || BIT1 | BIT2; //将XT1引脚设置为第二个功能 做 { CSCTL7 &=~(XT1OFFG | DCOFFG); //清除XT1和DCO故障标志 SFRIFG1 &=~OFIFG; } 同时(SFRIFG1和OFIFG); //测试振荡器故障标志 __bis_sr_register (SCG0); //禁用FLL CSCTL6 |= XT1DRIVE_3; //将XT1驱动程序设置为最大长度? CSCTL3 |= SELREF__XT1CLK; //将XT1CLK设置为FLL参考源 CSCTL0 = 0; //清除DCO和MOD寄存器 CSCTL1 &=~(DCORSEL_7); //首先清除DCO频率选择位 CSCTL1 |= DCORSEL_3; //设置DCO = 8MHz CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz __DELAY周期(3); __BIC_SR_REGISTER (SCG0); //启用FLL while (CSCTL7和(FLLUNLOCK0 | FLLUNLOCK1));//轮询,直到FLL锁定 CSCTL4 = SELMS__DCOCLKDIV | LAST__XT1CLK;//设置ACLK = XT1CLK =3.2768万Hz // DCOCLK = MCLK和SMCLK源 CSCTL5 || DIVM_0 | DIVS_1; // MCLK = DCOCLK = 8MHZ, // SMCLK = MCLK/2 = 4MHz P1DIR || BIT0 + BIT4; //将MCLK和LED引脚设置为输出 P1SEL0 |= BIT4; //将MCLK引脚设置为第二个功能 P8DIR || BIT0 | BIT1; //将ACLK和SMCLK引脚设置为输出 P8SEL0 || BIT0 | BIT1; //将ACLK和SMCLK引脚设置为第二个函数 }//initClock() void initTimerA(void){ TA0CCTL0 |= CCIE; //已启用TACR0中断 TA0CCR0 =脉冲计时[0]; //首次初始化为tick的第[0]个值 TA0EX0 = TAIDEX_7; // TimerA时钟源SMCLK@4MHz / 8 >>> TimerA时钟频率2us TA0CTL || tassel__SMCLK | MC_2; //来自SMCLK的TimerA,连续模式 }//initTimerA() void enableConfig(void) { PM5CTL0 &=~LOCKLPM2; //禁用GPIO开机默认高阻抗模式 //要激活先前配置的端口设置 }// 计时器A0中断服务例程 #if defined(__TI_Compiler_version__)|| defined (__IAR_systems_icc__) #pragma vector = TIMER0_A0_vector __interrupt Timer_a (void) #Elif defined(__GA0__) void ___attribute__#PIR__#( 不支持) Timer0_Timer0)0#中断Timer_a vector (void Timer)0#中断Timer_IER)0#中断Timer_A (void Timer_IU #endif { P1OUT ^= BIT5; //计算此行的开销... IF (pulseIdx < numDges -1){ pulseIdx+;}//... 这一行... 否则 { pulseIdx =0;}//... 这一行... ??? TA0CCR0 +=脉冲计时[pulseIdx]; //最后,将TA0CCR0更新为下一个值 }

    以上代码生成以下波形。  如您所见,第一个脉冲高/低时间与预期一样(20us),整个模式每400us就会无限重复(下面的第二个屏幕截图) ,所以我想我主要在那里...但在上面的ISR中, 注释中指示的行是我需要找出中断延迟的内容,对吗?  

    如果是,我的TimerA比MCLK (  SMCLK = MCLK/2;  SMCLK/8)长很多,我该如何调整此计时?   MCLK的周期为125ns ,但TimerA的分辨率为2us。   是否有机制实现此修正系数?  感谢您的反馈。

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

    我有代码,并且大部分工作方式都是我想要的。  一些直接取自TI的示例,有些是我写的。  我想更新此线程,以防将来有人需要此线程。  目前,我有一个使用下面的代码运行的FR4133,但我打算在最终应用程序的FR5739上运行它。

    #include <msp430fr4133.h>

    #include <main.h>

    //定时器A设置为2us刻度时间

    // pulseTiming[]是一个全局值,并且保持高/低交替的“刻度数”

    unsigned int pulseTiming[8]={10,10,20,30,30,40,40};

    //保持编号更新为脉冲中相同数目的条目Timing;

    //无法找到其他方法来动态更新此值

    //在下面对其进行硬编码。

    易失性无符号int numDges =8;

    //跟踪我们在重复脉冲循环中的位置

    volatile unsigned int pulseIdx =0;

    内部主(无效)

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

      P1DIR |= BIT5;              //将WFP 1.5 设置为输出,并对其进行范围调整

      initClock();

      initTimerA();

      enableConfig();

      __bis_sr_register (GIE);         //启用全局中断

      同时(1)

      {

                          // MCU处于活动状态信号

        P1OUT ^= BIT0;

        __DELAY周期(400万);

      }

    }//main()

    void initClock(void)

      P4SEL0 || BIT1 | BIT2;          //将XT1引脚设置为第二个功能

      做

      {

       CSCTL7 &=~(XT1OFFG | DCOFFG);   //清除XT1和DCO故障标志

       SFRIFG1 &=~OFIFG;

      }同时(SFRIFG1 & OFIFG);        //测试振荡器故障标志

      __bis_sr_register (SCG0);         //禁用FLL

      CSCTL6 |= XT1DRIVE_3;          //将XT1驱动程序设置为最大长度?

      CSCTL3 |= SELREF__XT1CLK;        //将XT1CLK设置为FLL参考源

      CSCTL0 = 0;               //清除DCO和MOD寄存器

      CSCTL1 &=~(DCORSEL_7);         //首先清除DCO频率选择位

      CSCTL1 |= DCORSEL_3;           //设置DCO = 8MHz

      CSCTL2 = FLLD_0 + 243;          // DCODIV = 8MHz

      __DELAY周期(3);

      __BIC_SR_REGISTER (SCG0);         //启用FLL

      while (CSCTL7和(FLLUNLOCK0 | FLLUNLOCK1));//轮询,直到FLL锁定

      CSCTL4 = SELMS__DCOCLKDIV | LAST__XT1CLK; //设置ACLK = XT1CLK =3.2768万Hz

                           // DCOCLK = MCLK和SMCLK源

      CSCTL5 || DIVM_0 | DIVS_1;         // MCLK = DCOCLK = 8MHZ,

                           // SMCLK = MCLK/2 = 4MHz

      P1DIR || BIT0 + BIT4;          //将MCLK和LED引脚设置为输出

      P1SEL0 |= BIT4;             //将MCLK引脚设置为第二个功能

      P8DIR || BIT0 | BIT1;          //将ACLK和SMCLK引脚设置为输出

      P8SEL0 || BIT0 | BIT1;          //将ACLK和SMCLK引脚设置为第二功能

    }//initClock()

    void initTimerA(void){

      TA0CCTL0 |= CCIE;               //已启用TACR0中断

      TA0CCR0  =脉冲计时[0];          //首次初始化为tick的第[0]个值

      TA0EX0  = TAIDEX_7;             // TimerA时钟源SMCLK@4MHz / 8 >>> TimerA时钟频率2us

      TA0CTL  || tassel__SMCLK | MC_2 ;      //来自SMCLK的TimerA,连续模式

    }//initTimerA()

    void enableConfig(void)

      PM5CTL0 &=~LOCKLPM2;          //禁用GPIO开机默认高阻抗模式

                          //以激活先前配置的端口设置

    }

    //计时器A0中断服务例程

    #if defined(__TI_Compiler_version__)|| defined(__IAR_SYSTEMS _ICC__)

    #pragma vector = TIMER0_A0_vector

    __interrupt void Timer_A (void)

    #Elif已定义(__GMNU__)

    void __attribute__((interrupt (TIMER0_A0_vector))) Timer_A (void)

    #否则

    错误编译器不受支持!

    #endif

    {  

      P1OUT ^= BIT5;                 //计算此行的开销...

      IF (pulseIdx < numDges -1){ pulseIdx+; }//...  这一行...

      否则             { pulseIdx =0;}//...  这一行... ???

      TA0CCR0 +=脉冲计时[pulseIdx];        //最后,将TA0CCR0更新为下一个值

    }

    以上代码生成以下波形。

    如您所见,第一个脉冲高/低时间与预期一样(20us),随后的高/低时间与我预期的一样,并且整个模式在  正确的时间内每400us无限重复(第二个屏幕截图显示X1/X2在模式的开始/结束处)。   所以我想我主要是在那里...

    ...但在上述ISR代码中,注释中指明的行是我需要找出中断延迟的内容,对吗?

    如果是,我的TimerA比MCLK ( SMCLK = MCLK/2;  SMCLK/8)长很多,我该如何调整此计时?  MCLK的周期为125ns ,但TimerA的分辨率为2us。  是否有机制实现此修正系数?  感谢您的反馈。