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.

MSP430 SPI I/O Question

Other Parts Discussed in Thread: MSP430WARE, DRV8301, MSP430F5638

I'm an SPI newbie, using MSP430Ware here, SPI mode on USCI A1.

I can set the SPI in loopback mode and send single characters around, so my SPI test works fine.  But now I'm seeing example code where there's a dummy read after every byte of a data packet is sent out, before reading the slaves response.

Should I be doing that too? Im trying to talk to a DRV8301 EVAL board and I'm not seeing anything logical back, just trash. 


All help appreciated!

Ed Averill

 

  • Edward Averill said:
    But now I'm seeing example code where there's a dummy read after every byte of a data packet is sent out, before reading the slaves response.

    You mean that after each data byte sent as part of a packet, the example code reads the RXBUF register? There is no harm in doing that. It avoids a bogus UCOE flag in the status register (bogus in the sense that if you don't care/need the data returned then you don't care that it was overrun).

    I didn't read the datasheet for the part you referenced, but generally you issue the read command on the SPI and then transmit dummy bytes equal to the number of returned bytes you expect, all as part of a single packet.

  • Ok, I see what you mean.. but I'm seeing what I think is "Unexpected behavior"...

    There's nothing live on the SPI bus, but I'm sending out garbage to make sure the IOs are set up right.. but, oddly, I immediately get an RX interrupt right after a transmit!  There's nothing live on the bus, there's a DRV8301 but it's not powered at all.. this doesn't make sense to me.

    At first I thought that loopback mode must have been set but the control register says it's off, and I'm sending 0xFF and seeing 0x00 in the RX register.

    I'm fairly sure this isn't "working as designed"...

    Here's my setup code:

    Bool SPI_Init()
    {
    	Bool retVal = TRUE;
    
    	// Kill the loopback mode flag
    
    	inLoopback = FALSE;
    
    	// First, make sure no slaves are selected, this will prevent any
    	// reset-caused glitches on the bus
    
    	if(SetSPISlaveSelect(SPI_SLAVE_NONE) == FALSE)
    		return FALSE;						// Select control failed
    
    	// We're the SPI master, set us up
    
    	retVal = USCI_A_SPI_masterInit(SPI_BASE,
    	        USCI_A_SPI_CLOCKSOURCE_SMCLK,
    	        UCS_getSMCLK(),
    	        12500000,
    	        USCI_A_SPI_MSB_FIRST,
    	        USCI_A_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,
    	        USCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW
    		);
    
    	// Time to enable the bus
    
        USCI_A_SPI_enable(SPI_BASE);
    
        // Clean up any interrupt flags that might be lingering
    
        USCI_A_SPI_disableInterrupt(SPI_BASE,
        		USCI_A_SPI_RECEIVE_INTERRUPT | USCI_A_SPI_TRANSMIT_INTERRUPT);
    
        USCI_A_SPI_clearInterruptFlag(SPI_BASE,
        		USCI_A_SPI_RECEIVE_INTERRUPT | USCI_A_SPI_TRANSMIT_INTERRUPT);
    
    	return retVal;
    }
    

    Slave Select just twiddles a GPIO going to various SPI slaves:

    tatic Bool SetSPISlaveSelect(int SPI_Slave_ID)
    {
    	Bool retVal = TRUE;
    
    	// FIXME Add code when the GPIOs are defined
    
    	switch(SPI_Slave_ID)
    	{
    	case SPI_SLAVE_NONE:		// Deselect ALL SPI devices
    		GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN0);			// DRV8301 is ACTIVE LOW
    		break;
    	case SPI_SLAVE_LCD:			// LCD cntroller
    		break;
    	case SPI_SLAVE_MOTOR:		// Motor controller
    		GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0);			// DRV8301 is ACTIVE LOW
    		break;
    	case SPI_SLAVE_NET:			// Ethernet controller
    		break;
    	default:
    		retVal = FALSE;			// Unknown Slave ID, fail the call
    		break;
    	}
    
    	return retVal;
    }

    Read is pretty trivial:

    int SPI_Read(int DevAddr, unsigned char *pBuf, int nLength)
    {
    	int nRead = 0;
    	int nTimeout = 0;
    	int RXWait = SPI_RX_WAIT;
    	unsigned int taskKey;
    	static unsigned char pDummy[1] = {0x0ff};
    
    	taskKey = Task_disable();				// Stop task switches
    
    	SetSPISlaveSelect(DevAddr);				// Select the slave to work with
    
    	while(nLength-- > 0)
    	{
    		nTimeout = SPI_BUSY_TIMEOUT;
    	    // Wait for all TX/RX to finish
    	    while(USCI_A_SPI_isBusy(SPI_BASE))
    	    {
    	    	nTimeout--;
    	    	if(nTimeout <= 0)
    	    		break;			// Timed out
    	    }
    	    if(nTimeout <= 0)
    	    	break;				// Ok, bail the read loop - error state
    	    // Send one dummy byte for every byte of response we want, if needed
    	    if(inLoopback == FALSE)
    	    	USCI_A_SPI_transmitData(SPI_BASE, pDummy[0]);
    	    USCI_A_SPI_clearInterruptFlag(SPI_BASE, USCI_A_SPI_TRANSMIT_INTERRUPT);	// Clear interrupts
    	    // FIXME timeout if no response from slave unit
    	    *pBuf++ = USCI_A_SPI_receiveData(SPI_BASE);
    		nRead++;					// Another character in
    		RXWait = SPI_RX_WAIT;		// Reset wait count
    	    USCI_A_SPI_clearInterruptFlag(SPI_BASE, USCI_A_SPI_RECEIVE_INTERRUPT);	// Clear interrupts
    	}
    
    	SetSPISlaveSelect(SPI_SLAVE_NONE);		// Done, deselect
    
    	Task_restore(taskKey);					// Swsitching OK now
    
    	return nRead;
    }


    Nothing pops out at me as obviously wrong, but this is my first SPI bus work so there's a good chance I'm being stupid.

    Any idea as to what I'm doing wrong? MSP430F5638 on a TS430PZ100-USB prototyping board, jumpered to a DRV8301 BOOST eval board.. the eval board is unpowered.

    All help, clues, comments, suggestions GREATLY appreciated.

    Ed Averill

     

  • Edward Averill said:
    but, oddly, I immediately get an RX interrupt right after a transmit!

    Not odd (well, maybe to you, lol) but this would be expected behavior.

    Edward Averill said:

    At first I thought that loopback mode must have been set but the control register says it's off, and I'm sending 0xFF and seeing 0x00 in the RX register.

    I'm fairly sure this isn't "working as designed"...

    It sounds like it is working exactly as designed.

    Everytime a bit is clocked out of the transmit register, a bit is clocked into the receive register. And since you say that the external device is not powered, you would expect the MISO line to be low, and all the bits clocked into the receive register (while clocking out your 0xFF bits from the transmit register) to be binary 0.

    Edward Averill said:
    so there's a good chance I'm being stupid.

    I probably wouldn't go that far. But I would suggest finding some good reading material on how SPI works.

  • Mmmph.. been trying to find a decent doc on SPI, lots of code samples but my Google-Fu is weak.. maybe the EE here can point me in the right direction..

    Regardless, *now* I understand what I'm seeing!  It all makes sense now.. thanks!

    Ed Averill

     

**Attention** This is a public forum