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.

MSP430F5526 SPI 时钟问题

Other Parts Discussed in Thread: MSP430F5526

请教TI工程师,

目前我在做的案子(24MH晶振,SMCLK和MCLK都选择24M频率),目前需要3MHz的频率;想通过配置USCI_B1配置成SPI master mode来产生一个3M的频率!

然后,现在打算参考ccs 中产生SPI的程序。

但是调试,CCS给的SPI例程发现,SPI产的波形并不是持续的时钟,而是断续的时钟:SPI是否可以产生持续的时钟

如下图所示:用示波器查看P4.3脚 CLK

  
// MSP430F552x 
//                 -----------------
//             /|\|                 |
//              | |                 |
//              --|RST          P1.0|-> LED
//                |                 |
//                |             P3.4|-> Data Out (UCA0SIMO)
//                |                 |
//                |             P3.5|<- Data In (UCA0SOMI)
//                |                 |
//  Slave reset <-|P1.1         P3.0|-> Serial Clock Out (UCA0CLK)
//
//
//   Bhargavi Nisarga
//   Texas Instruments Inc.
//   April 2009
//   Built with CCSv4 and IAR Embedded Workbench Version: 4.21
//******************************************************************************

#include <msp430.h>

unsigned char MST_Data,SLV_Data;
unsigned char temp;

int main(void)
{
  volatile unsigned int i;

  WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer

  P1OUT |= 0x02;                            // Set P1.0 for LED
/*                                          // Set P1.1 for slave reset
  P1DIR |= 0x03;                            // Set P1.0-2 to output direction
  P3SEL |= BIT3+BIT4;                       // P3.3,4 option select
  P2SEL |= BIT7;                            // P2.7 option select
  
  UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**
  UCA0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    // 3-pin, 8-bit SPI master
                                            // Clock polarity high, MSB
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 0x02;                           // /2
  UCA0BR1 = 0;                              //
  UCA0MCTL = 0;                             // No modulation
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

  P1OUT &= ~0x02;                           // Now with SPI signals initialized,
  P1OUT |= 0x02;                            // reset slave

  for(i=50;i>0;i--);                        // Wait for slave to initialize

  MST_Data = 0x01;                          // Initialize data values
  SLV_Data = 0x00;                          //

  while (!(UCA0IFG&UCTXIFG));               // USCI_A0 TX buffer ready?
  UCA0TXBUF = MST_Data;                     // Transmit first character

*/

/////
    P1DIR |= 0x03;                            // Set P1.0-2 to output direction
    P4SEL |= BIT1+BIT2+BIT3;                       // P3.3,4 option select
  //  P4DIR |= BIT3;                           // P2.7 option select

    UCB1CTL1 |= UCSWRST;                      // **Put state machine in reset**
    UCB1CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    // 3-pin, 8-bit SPI master
                                              // Clock polarity high, MSB
    UCB1CTL1 |= UCSSEL_2;                     // SMCLK
    UCB1BR0 = 0x02;                           // /2
    UCB1BR1 = 0;                              //
    //UCBxMCTL = 0;                             // No modulation
    UCB1CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
    UCB1IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

    P1OUT &= ~0x02;                           // Now with SPI signals initialized,
    P1OUT |= 0x02;                            // reset slave

    for(i=50;i>0;i--);                        // Wait for slave to initialize

    MST_Data = 0x01;                          // Initialize data values
    SLV_Data = 0x00;                          //

    while (!(UCB1IFG&UCTXIFG));               // USCI_A0 TX buffer ready?
    UCB1TXBUF = MST_Data;                     // Transmit first character

///////////////////////////////////////////////////////////////////////////////////////
  __bis_SR_register(LPM0_bits + GIE);       // CPU off, enable interrupts

  while(1);
}

////////////////////////////////////////////////////////////////////
#pragma vector=USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
{
  volatile unsigned int i;

  switch(__even_in_range(UCB1IV,4))
  {
    case 0: break;                          // Vector 0 - no interrupt
    case 2:                                 // Vector 2 - RXIFG
      while (!(UCB1IFG&UCTXIFG));           // USCI_A0 TX buffer ready?

      if (UCB1RXBUF==SLV_Data)              // Test for correct character RX'd
        P1OUT |= 0x01;                      // If correct, light LED
      else
        P1OUT &= ~0x01;                     // If incorrect, clear LED

      MST_Data++;                           // Increment data
      SLV_Data++;
      UCB1TXBUF = MST_Data;                 // Send next value

      for(i = 20; i>0; i--);                // Add time between transmissions to
                                            // make sure slave can process information
      break;
    case 4: break;                          // Vector 4 - TXIFG
    default: break;
  }
}

////////////////////////////////////////////////////////////////////

/*
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
  volatile unsigned int i;

  switch(__even_in_range(UCA0IV,4))
  {
    case 0: break;                          // Vector 0 - no interrupt
    case 2:                                 // Vector 2 - RXIFG
      while (!(UCA0IFG&UCTXIFG));           // USCI_A0 TX buffer ready?

      if (UCA0RXBUF==SLV_Data)              // Test for correct character RX'd
        P1OUT |= 0x01;                      // If correct, light LED
      else
        P1OUT &= ~0x01;                     // If incorrect, clear LED

      MST_Data++;                           // Increment data
      SLV_Data++;
      UCA0TXBUF = MST_Data;                 // Send next value

      for(i = 20; i>0; i--);                // Add time between transmissions to
                                            // make sure slave can process information
      break;
    case 4: break;                          // Vector 4 - TXIFG
    default: break;
  }
}
*/

  • 你好,

    我建议你使用1M的SPI来测试一下你USCI_B是否正常,然后你再把时钟提上去。

  • Yiyuan,

       这个是SPI的特性决定的吧,SPI的报文信息传输,每次传输之间都会有一定的间隔,这样才能保证从设备在进行数据通信之间,数据已经准备好了。

    如果SPI的CLock信号一直是发出的话,从设备是来不及建立通信的。

    建议你是不是可以用我们其他模块试试。

    谢谢

  • 关于UCSI_B模块,把UCSI_B1配置成SPI模式,参考CCS中MSP430F5526的 MSP430F55xx_uscia0_spi_09工程,分别配置1M,500K,400K,和100K的是时钟输出,如下图所示:(code代码在后面)(晶振24M,MCLK和SMCLK都是24M)

    1)  设置1M输出:

    2)  设置500KHz

    3)400KHz

    4)100KHz

    从上图发现:

    每7个波形之后会产生一个双周期的波形

    这是怎么产生?

     

    代码:

    #include <msp430.h>

    unsigned char MST_Data,SLV_Data;

    unsigned char temp;

    void Init_Ports(void)

    {

        P1OUT = 0x00;

        P1DIR = 0xFF;

        P2OUT = 0x00;

        P2DIR = 0xFF;

        P3OUT = 0x00;

        P3DIR = 0xFF;

        P4OUT = 0x00;

        P4DIR = 0xFF;

        P5OUT = 0x00;

        P5DIR = 0xFF;

        P6OUT = 0x00;

        P6DIR = 0xFF;

    }

    int main(void)

    {

      volatile unsigned int i;

      WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer

      P2DIR |= BIT2;                            // SMCLK set out to pins

       P2SEL |= BIT2;

       P2OUT |=(BIT2); P2DIR |=(BIT2); P2SEL|=(BIT2);

       P5SEL |= BIT2+BIT3;                       // Port select XT2

        UCSCTL6 &= ~XT2OFF;                       // Enable XT2

        UCSCTL3 |= SELREF_2;                  // FLLref = REFO

                                                  // Since LFXT1 is not used,

                                             // sourcing FLL with LFXT1 can cause

                                               // XT1OFFG flag to set

        UCSCTL4 |= SELA_2;                     // ACLK=REFO,SMCLK=DCO,MCLK=DCO

     // Loop until XT1,XT2 & DCO stabilizes - in this case loop until XT2 settles

        do

        {

          UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);

                                                  // Clear XT2,XT1,DCO fault flags

          SFRIFG1 &= ~OFIFG;                      // Clear fault flags

        }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag

     

        UCSCTL6 &= ~XT2DRIVE0;              // Decrease XT2 Drive according to

                                                  // expected frequency

        UCSCTL4 |= SELS_5 + SELM_5;               // SMCLK=MCLK=XT2

      P1OUT |= 0x02;                            // Set P1.0 for LED

        P1DIR |= 0x03;                          // Set P1.0-2 to output direction

        P4SEL |= BIT1+BIT2+BIT3;                       // P3.3,4 option select

      //  P4DIR |= BIT3;                           // P2.7 option select

        UCB1CTL1 |= UCSWRST;                   // **Put state machine in reset**

        UCB1CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    // 3-pin, 8-bit SPI master

                                                  // Clock polarity high, MSB

    UCB1CTL1 |= UCSSEL_2;                     // SMCLK

       // 设置SPI时钟0x18--1M  0x30--500K 0x3C---400K 0xF0-100K 0x08---3M

        UCB1BR0 = 0x10;              UCB1BR1 = 0;                              //

        //UCBxMCTL = 0;                             // No modulation

        UCB1CTL1 &= ~UCSWRST;             // **Initialize USCI state machine**

        UCB1IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

        P1OUT &= ~0x02;                     // Now with SPI signals initialized,

        P1OUT |= 0x02;                            // reset slave

        for(i=50;i>0;i--);                       // Wait for slave to initialize

        MST_Data = 0x01;                          // Initialize data values

        SLV_Data = 0x00;                          //

        while (!(UCB1IFG&UCTXIFG));               // USCI_A0 TX buffer ready?

        UCB1TXBUF = MST_Data;                     // Transmit first character

      __bis_SR_register(LPM0_bits + GIE);       // CPU off, enable interrupts

      while(1);

    }

    ////////////////////////////////////////////////////////////////////

    #pragma vector=USCI_B1_VECTOR

    __interrupt void USCI_B1_ISR(void)

    {

      volatile unsigned int i;

      switch(__even_in_range(UCB1IV,4))

      {

        case 0: break;                          // Vector 0 - no interrupt

        case 2:                                 // Vector 2 - RXIFG

          while (!(UCB1IFG&UCTXIFG));           // USCI_A0 TX buffer ready?

          if (UCB1RXBUF==SLV_Data)          // Test for correct character RX'd

            P1OUT |= 0x01;                      // If correct, light LED

          else

            P1OUT &= ~0x01;                     // If incorrect, clear LED

          MST_Data++;                           // Increment data

          SLV_Data++;

          UCB1TXBUF = MST_Data;                 // Send next value

          for(i = 20; i>0; i--);           // Add time between transmissions to

                                        // make sure slave can process information

          break;

        case 4: break;                          // Vector 4 - TXIFG

        default: break;

      }

    }

    ////////////////////////////////////////////////////

  • 你好,

    我有些没有明白你所谓的双周期是什么意思?

    我现在看你设置的SPI模式空闲时CLK是高电平,不知道是不是这个原因。

    你可以UCB1CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    // 3-pin, 8-bit SPI master在这句话里去掉UCCKPL尝试。

  • Michael, 你好!

    如果把UCCKPL去掉! 原来双周期高电平部分都变成低电平!

    这可能是跟  所说的, 这个是SPI的特性决定的吧,SPI的报文信息传输,每次传输之间都会有一定的间隔,这样才能保证从设备在进行数据通信之间,数据已经准备好了。


    谢谢各位工程师!

  • 你好,

    如果UCCKPL去掉,可以解决你所谓的双周期高电平问题吗?

    如果是,我觉得是应该从机的工作模式决定了只能工作在SPI的第1,2中模式:空闲时,SPI时钟信号为低电平。

    如果我们有帮你解决问题,请结掉该贴。