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.

[参考译文] MSP430F6777A:MSP430F6777A 微控制器高速 GPIO 切换

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

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

器件型号:MSP430F6777A

我使用的是 MSP430F6777A 微控制器。 SMCLK 的频率为25MHz。 我想切换 GPIO 引脚以驱动装配 LED。 对于此操作、我需要将 GPIO 引脚保持在高电平900ns、保持在低电平300ns。 循环和&&逻辑运算符的 IF 控制等操作会增加切换时间。 如何在不使用 PWM 模式下的计时器的情况下加快切换过程?

e2e.ti.com/.../AN1001_5F00_IC-Embedded-Solutions-of-SMD-LEDs-_2800_Ver-1.0_2900_.pdf

Toh=300ns
T0L=.00
T1H=.00
T1L= 300ns

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

    您好、Selim  

    我检查了波形、高电平信号始终为  T1H=900ns、低电平信号 始终为 T1L=300ns。

    是否可以知道何时  需要 TOH=300ns、t0l=900ns?

    谢谢

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

    尊敬的
    是否要发送逻辑0。 信号应该像这样发送。 (Toh=300ns、t0l=900ns)

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

    您是否有兴趣使用 PWM 计时器? 完全没有 CPU 参与。

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

    您好、Selim  

    请检查 PWM 计时器是否适合您的应用、作为 Keith 注释。

    谢谢

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

    嗨、Xiaodong、嗨、Keith

    如果我们要向 LED 驱动器发送10011001逻辑信息、则我们需要获得的信号如下所示。

    我们试图更改每个 PWM 中断中的占空比值来获得信号、但没有获得成功的结果。

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

    我认为 DMA 应该能够按您的要求工作。 您可以在 CCR0上触发以传输一个新的 CCRn 比较值。 如果序列是循环的、则可以将整个序列放入一个数组中并让它重复执行(DMADT=4)。 可能的触发器-即定时器和 CCRn 的选择-在数据表(SLAS962A)表6-14中。

    DMA 快速(在任何情况下比软件更快)、但不是瞬时的。 但如果 MCLK=MCLK,40ns 25MHz 节拍就能满足更新截止日期的要求。 [时序:参考用户指南(SLAU208Q)表11-3]

    [编辑:增加了对 DMA 传输时间表的引用。]

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

    Bruce、您好!

    感谢您的支持。 我尝试了您提到的方法。 但我无法按需要更改占空比值。

    将定时器周期的值设为12us、可以得到准确的数据、比如10101001。

    但我无法获得所需周期值1.2us 的信号。

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

    尽管有《用户指南》、但 DMA 看起来(以我的非专业人士的眼光看)似乎不符合要求。

    在这种情况下、CPU 正在做什么? 如果它不在 LPM0 (空闲)中、这是你可以尝试的吗?  

    [古代史:我曾与 F2系列 DMA 作过斗争。 症状是 SPI 溢出、就像 DMA 没有跟上一样-无论 DMAONFETCH 的设置如何、该设置应该允许 DMA 运行中间指令。 这不是我可以使用 LPM 的地方、因此我的权变措施是用 NOP-s (每个1个 MCLK)填充我的轮询循环、以便为 DMA 提供更多机会、此时 症状消失了。  即使当我在接近其限制的情况下运行 DMA 时、也要记住这一点。]

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

    您是否可以选择使用哪个计时器?

    我使用 TB0同时 CLLD=2成功完成了这个操作(在 F5529上)。 使用影子寄存器为 DMA 提供了整个更新 CCR2的周期、这似乎是足够的时间。 (它在25MHz 时工作、但20MHz 工作得更好、因为40不能分频300或900。)

    DMA 中仍然有价值、因为在24个时钟内尝试用软件更新 CCR2相当紧张。

    [编辑:对不起,我只是注意到 F6777A 没有计时器 B。我要把这个留给考古学家。]

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

    使用这种方法、我成功生成了您要查找的波形。 这是在 F5529上发生的、使用的是 CLLD=0的 TB0 (因此它的行为与 timerA 相同)。 在25MHz 时(在我的示波器上)、在舍入误差范围内、时序是正确的(在20MHz 下更好)。

    我仍然有一些我没有解释过的附带缺陷、所以我不能完全说"解决了"、但事实是、它可以成功表明可能在您的实施中有一些东西(或您的设备特定)导致了您遇到的麻烦。  

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

    Bruce、您好!

    是否尝试过使用 TimerA?  您能否共享使用 TimerB 制作的代码以供参考?

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

    这是我的工作方式。 它在 F5529上使用 TA0。 代码的后半部分(时钟设置)大部分粘贴自 TI 示例。

    //
    //  Generate bit encoding with a timer.
    //  No warranty, no support. I may not even exist.
    //
    #include <msp430.h> 
    #include <stdint.h>
    #define HZ      20000000UL      // MCLK=SMCLK=20MHz
    //  Long and Short pulses, measured in timer (SMCLK) ticks. For 20MHz:
    #define SHORT   6               // 6*50ns  = 300ns
    #define LONG    (3*SHORT)       // 3*300ns = 900ns
    #define PERIOD  (LONG+SHORT)
    #define USE_LPM     0
    uint16_t bits[] = {LONG, SHORT, LONG, SHORT, LONG, SHORT, SHORT, LONG}; // 10101001
    //uint16_t bits[] = {LONG, LONG , SHORT, SHORT, LONG, SHORT, LONG, LONG}; // 11001011
    //uint16_t bits[] = {SHORT, LONG , SHORT, SHORT, LONG, SHORT, LONG, LONG}; // 01001011
    #define NBITS   (sizeof(bits)/sizeof(bits[0]))
    extern void setDCOtoHz(void);
    
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
    	P1OUT &= ~BIT0;             // There's always an LED at P1.0,
    	P1DIR |=  BIT0;             //   right?
    #if HZ > 1000000UL              // Something other than post-reset speed
    	setDCOtoHz();
    #endif // HZ
    	P1DIR |= BIT3;              // P1.3 as TA0.2
    	P1SEL |= BIT3;              //  per SLAS590P Table 9-46
    
    	DMACTL0 = DMA0TSEL_1;       // TA0CCR0 per SLAS590P Table 9-10
    	__data20_write_long((uintptr_t) &DMA0SA, (uintptr_t)&bits[0]);
        __data20_write_long((uintptr_t) &DMA0DA, (uintptr_t)&TA0CCR2);
        DMA0SZ = NBITS;
        DMA0CTL = DMADT_0 | DMADSTINCR_0 | DMASRCINCR_3 | (0*DMADSTBYTE) | (0*DMASRCBYTE)
                | (0*DMALEVEL) | (0*DMAEN) | (USE_LPM*DMAIE);
    
        TA0CCR0 = PERIOD-1;
    	TA0CTL = TASSEL_2 | ID_0 | 0*MC__UP | TACLR;    // SMCLK/1, Up (soon)
    	__enable_interrupt();
    
    	while(1)
    	{
    	    P1OUT ^= BIT0;
            TA0CTL &= ~MC_3;         // Stop timer
            TA0CCTL0 &= ~CCIFG;      // Clear stale for DMA trigger edge
            TA0CCR2 = SHORT;         // Avoid early EQU2 (first-time-ever)
    	    TA0CCTL2 = OUTMOD_7;     // High pulse at the beginning
    	    DMA0CTL |= DMAEN;
    	    TA0CTL |= MC__UP|TACLR;  // Start timer
    #if USE_LPM
            LPM0;
    #else
            while (DMA0CTL & DMAEN)/*EMPTY*/;
    #endif
            TA0CCTL2 = OUTMOD_5;    // For last cycle just clear and leave it
    	    __delay_cycles(HZ/2);   // Pause to read the scope
    	}
    	/*NOTREACHED*/
    	return 0;
    }
    
    #if USE_LPM
    #pragma vector=DMA_VECTOR
    __interrupt void
    dma_ISR(void)
    {
        DMA0CTL &= ~DMAIFG;
        LPM0_EXIT;
        return;
    }
    #endif // USE_LPM
    
    //  Lifted from TI Example MSP430F55xx_UCS_10.c:
    void SetVcoreUp (unsigned int level)
    {
      // Open PMM registers for write
      PMMCTL0_H = PMMPW_H;
      // Set SVS/SVM high side new level
      SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
      // Set SVM low side to new level
      SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
      // Wait till SVM is settled
      while ((PMMIFG & SVSMLDLYIFG) == 0);
      // Clear already set flags
      PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
      // Wait till new level reached
      if ((PMMIFG & SVMLIFG))
        while ((PMMIFG & SVMLVLRIFG) == 0);
      // Set SVS/SVM low side to new level
      SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
    }
    //  Set the DCO to whatever HZ is (within DCORSEL=7)
    void
    setDCOtoHz(void)
    {
        // Increase Vcore setting to level3 to support fsystem=25MHz
        // NOTE: Change core voltage one level at a time..
        SetVcoreUp (0x01);
        SetVcoreUp (0x02);
        SetVcoreUp (0x03);
    
        UCSCTL3 = SELREF_2;                       // Set DCO FLL reference = REFO
        UCSCTL4 |= SELA_2;                        // Set ACLK = REFO
    
        __bis_SR_register(SCG0);                  // Disable the FLL control loop
        UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
        UCSCTL1 = DCORSEL_7;                      // Select DCO range 50MHz operation
        UCSCTL2 = FLLD_0 + (HZ/32768)-1; //762;   // Set DCO Multiplier for 25MHz
                                                  // (N + 1) * FLLRef = Fdco
                                                  // (762 + 1) * 32768 = 25MHz
                                                  // Set FLL Div = fDCOCLK/2
        __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
        // Worst-case settling time for the DCO when the DCO range bits have been
        // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
        // UG for optimization.
        // 32 x 32 x 25 MHz / 32,768 Hz ~ 780k MCLK cycles for DCO to settle
        __delay_cycles(782000);
    
        // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
        do
        {
          UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                                  // Clear XT2,XT1,DCO fault flags
          SFRIFG1 &= ~OFIFG;                      // Clear fault flags
        }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
    }
    

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

    你好,布鲁斯

    为微控制器配置时、我可以获得正确的信号。 感谢您的支持。