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.

SPI 主机从机通信问题

Other Parts Discussed in Thread: MSP430G2755, MSP430F5438A

现在,用两块430单片机进行SPI的通信,希望是从机发送数据,主机接收数据并返回。编写程序后发现主机没有主动产生时钟,现在用的是3线的SPI,是否需要4线的才能实现?

//******************************************************************************
//作为主机,接收SPI数据,并转换后发送回去,然后上传串口

#include <msp430.h>

unsigned char MST_Data,SLV_Data;

void Serial_init()
{
	P10SEL = 0x30;                             // P3.4,5 = USCI_A0 TXD/RXD
	UCA3CTL1 |= UCSWRST;                      // **Put state machine in reset**
	UCA3CTL1 |= UCSSEL_2;                     // SMCLK
	UCA3BR0 = 6;                              // 1MHz 9600 (see User's Guide)
	UCA3BR1 = 0;                              // 1MHz 9600
	UCA3MCTL = UCBRS_0 + UCBRF_13 + UCOS16;   // Modln UCBRSx=0, UCBRFx=0,
											// over sampling
	UCA3CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
	//UCA3IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

}

int main(void)
{
  WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
  Serial_init();
  //P1OUT |= 0x02;                            // Set P1.0 for LED
                                            // Set P1.1 for slave reset
 // P1DIR |= 0x03;                            // Set P1.0-2 to output direction
  P9SEL |= 0x0E;                            // P3.5,4,0 option select

  UCB2CTL1 |= UCSWRST;                      // **Put state machine in reset**
  UCB2CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    // 3-pin, 8-bit SPI master
                                            // Clock polarity high, MSB
  UCB2CTL1 |= UCSSEL_2;                     // SMCLK
  UCB2BR0 = 0x02;                           // /2
  UCB2BR1 = 0;                              //
 // UCA0MCTL = 0;                             // No modulation
  UCB2CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  UCB2IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

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

  __delay_cycles(100);                      // Wait for slave to initialize
  __bis_SR_register(GIE);       // Enter LPM4, enable interrupts
  while(1);
}


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_B2_VECTOR
__interrupt void USCI_B2_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B2_VECTOR))) USCI_B2_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(UCB2IV,4))
  {
  case 0:break;                             // Vector 0 - no interrupt
  case 2:                                   // Vector 2 - RXIFG
    while (!(UCA3IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
    UCA3TXBUF = 0xff-UCB2RXBUF;                  // TX -> RXed character
    while (!(UCB2IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
    UCB2TXBUF = 0xff-UCB2RXBUF;                  // TX -> RXed character
    break;
  case 4:break;                             // Vector 4 - TXIFG
  default: break;
  }
}
  • 和采用3线或者4线的spi没关系

  • 我用示波器看,发现时钟管脚没有输出。

  • 你好,

    请问你使用 的是那一颗芯片?

    记住SPI输出步骤:

    1.IO管脚配置为第二功能。

    2.SPI模块初始化正确

    3.主从SPI工作模式选择正确

    4.示波器钩波形

    3线4线区别只是少了EN使能从机的信号,和SPI输出没有关系。

    附件是我的SPI代码,跑在MSP430G2755上的。

    供你参考

  • 我从机使用的Luanchpad. G2553,主机用的是MSP430F5438A.  从机发送一个数据,主机接收到数据后发送给电脑,并通过SPI返回去;从机接收到数据后发送给电脑;停顿一段时间后又反复这样。实际测试的时候发现电脑接收的数据出现了重复。请问是什么原因呢?

    主机

    /* --COPYRIGHT--,BSD_EX
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *******************************************************************************
     *
     *                       MSP430 CODE EXAMPLE DISCLAIMER
     *
     * MSP430 code examples are self-contained low-level programs that typically
     * demonstrate a single peripheral function or device feature in a highly
     * concise manner. For this the code may rely on the device's power-on default
     * register values and settings such as the clock configuration and care must
     * be taken when combining code from several examples to avoid potential side
     * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
     * for an API functional library-approach to peripheral configuration.
     *
     * --/COPYRIGHT--*/
    //******************************************************************************
    //   MSP430F543xA Demo - USCI_A0, SPI 3-Wire Master Incremented Data
    //
    //   Description: SPI master talks to SPI slave using 3-wire mode. Incrementing
    //   data is sent by the master starting at 0x01. Received data is expected to
    //   be same as the previous transmission.  USCI RX ISR is used to handle
    //   communication with the CPU, normally in LPM0. If high, P1.0 indicates
    //   valid data reception.  Because all execution after LPM0 is in ISRs,
    //   initialization waits for DCO to stabilize against ACLK.
    //   ACLK = ~32.768kHz, MCLK = SMCLK = DCO ~ 1048kHz.  BRCLK = SMCLK/2
    //
    //   Use with SPI Slave Data Echo code example.  If slave is in debug mode, P1.1
    //   slave reset signal conflicts with slave's JTAG; to work around, use IAR's
    //   "Release JTAG on Go" on slave device.  If breakpoints are set in
    //   slave RX ISR, master must stopped also to avoid overrunning slave
    //   RXBUF.
    //
    //                   MSP430F5438A
    //                 -----------------
    //             /|\|                 |
    //              | |                 |
    //              --|RST          P1.0|-> LED
    //                |                 |
    //                |             P9.1|-> Data Out (UCA0SIMO)
    //                |                 |
    //                |             P9.2|<- Data In (UCA0SOMI)
    //                |                 |
    //  Slave reset <-|P1.1         P9.3|-> Serial Clock Out (UCA0CLK)
    //
    //
    //   M. Morales
    //   Texas Instruments Inc.
    //   June 2009
    //   Built with CCE Version: 3.2.2 and IAR Embedded Workbench Version: 4.11B
    //******************************************************************************
    //作为主机,接收SPI数据,并转换后发送回去,然后上传串口
    
    #include <msp430.h>
    
    unsigned char MST_Data,SLV_Data;
    
    void Serial_init()
    {
    	P10SEL = 0x30;                             // P3.4,5 = USCI_A0 TXD/RXD
    	UCA3CTL1 |= UCSWRST;                      // **Put state machine in reset**
    	UCA3CTL1 |= UCSSEL_2;                     // SMCLK
    	UCA3BR0 = 6;                              // 1MHz 9600 (see User's Guide)
    	UCA3BR1 = 0;                              // 1MHz 9600
    	UCA3MCTL = UCBRS_0 + UCBRF_13 + UCOS16;   // Modln UCBRSx=0, UCBRFx=0,
    											// over sampling
    	UCA3CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
    	//UCA3IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
    
    }
    
    int main(void)
    {
      WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
      Serial_init();
      //P1OUT |= 0x02;                            // Set P1.0 for LED
                                                // Set P1.1 for slave reset
     // P1DIR |= 0x03;                            // Set P1.0-2 to output direction
      P9SEL |= 0x0E;                            // P3.5,4,0 option select
    
      UCB2CTL1 |= UCSWRST;                      // **Put state machine in reset**
      UCB2CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    // 3-pin, 8-bit SPI master
                                                // Clock polarity high, MSB
      UCB2CTL1 |= UCSSEL_2;                     // SMCLK
      UCB2BR0 = 0x02;                           // /2
      UCB2BR1 = 0;                              //
      UCA0MCTL = 0;                             // No modulation
      UCB2CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
      UCB2IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt
     // __delay_cycles(100);                      // Wait for slave to initialize
      //__bis_SR_register(GIE);       // Enter LPM4, enable interrupts
     // MST_Data = 0x01;
      UCB2TXBUF = MST_Data;                     // Transmit first character
     // __delay_cycles(10000);
      __bis_SR_register(GIE);
      while(1)
      {
    	  __delay_cycles(10000);
    	  __delay_cycles(10000);
      }
    }
    
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_B2_VECTOR
    __interrupt void USCI_B2_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B2_VECTOR))) USCI_B2_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB2IV,4))
      {
      case 0:break;                             // Vector 0 - no interrupt
      case 2:                                   // Vector 2 - RXIFG
    
    	//Send Data to PC
        while (!(UCA3IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
        UCA3TXBUF =  UCB2RXBUF;                  // TX -> RXed character
    
        //Send Data back to Slave
        while (!(UCB2IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
        UCB2TXBUF = UCB2RXBUF;                  // TX -> RXed character
       // while (!(UCB2IFG&UCTXIFG));             // USCI_A0 TX buffer ready?
    
        UCB2IFG &= ~UCTXIFG;
        UCA3IFG &= ~UCTXIFG;
        break;
      case 4:break;                             // Vector 4 - TXIFG
      default: break;
      }
    }
    

    从机

    #include <msp430.h>
    //从机,主动发送SPI数据给主机,然后接收数据并上传。
    unsigned char temp = 0x00;
    unsigned char MST_Data;
    void Clk_init()
    {
    	BCSCTL1 = CALBC1_16MHZ;                    // Set DCO
    	DCOCTL = CALDCO_16MHZ;
    }
    void IO_init()
    {
    	P1SEL = BIT1 + BIT2 + BIT5 + BIT6 + BIT7;                     // P1.1 = RXD, P1.2=TXD
    	P1SEL2 = BIT1 + BIT2 + BIT5 + BIT6 + BIT7;
    }
    void Serial_init()
    {
    	UCA0CTL1 |= UCSSEL_2;                     // SMCLK
    	UCA0BR0 = 0x82;                              // 16MHz 9600 UCA0BRX=1666=0x0682
    	UCA0BR1 = 0x06;                              // 16MHz 9600
    	UCA0MCTL = UCBRS2 + UCBRS1;               // Modulation UCBRSx = 6
    	UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
    	//IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
    }
    void SPI_init()
    {
    	UCB0CTL1 = UCSWRST;                       // **Put state machine in reset**
    	UCB0CTL0 |= UCCKPL + UCMSB + UCSYNC;      // 3-pin, 8-bit SPI master
    	UCA0MCTL = 0x00;
    	UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
    	IE2 |= UCB0RXIE;                          // Enable USCI0 RX interrupt
    }
    
    void Init_all()
    {
    	Clk_init();
    	IO_init();
    	Serial_init();
    	SPI_init();
    }
    
    void SPI_SendData()
    {
    	UCB0TXBUF = MST_Data;                     // Transmit first character
    	while((IFG2&UCB0TXIFG) == 0);
    	IFG2 &= ~UCB0TXIFG;
    	MST_Data++;
    	__delay_cycles(100000);
    }
    
    
    int main(void)
    {
     	WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
    	Init_all();
    	__delay_cycles(75);
    	MST_Data = 0x01;
    	__bis_SR_register(GIE);
    	while(1)
    		{
    			SPI_SendData();
    		}
    }
    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCI0RX_ISR(void)
    {
    	temp = UCB0RXBUF;
    	//通过串口发给PC
    	while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
    	UCA0TXBUF = UCB0RXBUF;                    // TX -> RXed character
    	//while (!(IFG2&UCA0TXIFG));                // USCI_A0 TX buffer ready?
    	//IFG2 &= ~UCA0TXIFG;
    }
    
  • 你好,

    根据你的描述,现在已经解决了主机和从机的SPI通信问题,是这样吗?

    另外,我没有理解你新的问题,你新的问题是什么?

    现在看起来SPI写和读然后上传到主机端都没有问题呀?

  • 我的问题是:从机给主机发送一次数据,在串口调试的串口中可以看到,主机会重复地收到几次同样的数据。   不知道是因为SPI的问题还是因为串口的问题。有人说是中断服务里没有清除标志位,所以一直在中断服务里,一直在向串口发数据。是因为这样吗?

  • 你好,

    感觉不是。

    你串口波特率是不是设置的正确的?

    你可以屏蔽掉SPI接受数据模块,写一个简单的按键触发一次串口数据传输。

    这样你按一下按键看上位机发送多次次串口数据。

    另外,中断标志IFG是会自动清除清除,不需要你再清一次,你可以在UART中断里设置断点,你在调试模式看看中断标志位是否有清除。

    希望我的解答对你有帮助。