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.

LAUNCHXL-F280025C: Send Single Byte Through SPI

Part Number: LAUNCHXL-F280025C
Other Parts Discussed in Thread: C2000WARE

Hi,

I'm a beginner with C & C2000. I'm trying to control the individual bytes sent through SPI - I'd like to be able to define each byte that is sent and how many times. At the moment though, every way I've tried results in a loop with the SPI module repeatedly sending the same byte.

I've started with the C2000 examples, specifically spi_ex1_loopback. I've added one GPIO input to trigger the data transmission, removed rData and disabled loopback mode. One of my code trials below:

// Included Files
#include "driverlib.h"
#include "device.h"
#include "board.h"


// Main
void main(void)
{
    uint16_t sData = 0;                  // Send data
    uint16_t sData2 = 0;                  // Send data
    uint16_t sData3 = 0;                  // Send data
    int counter = 0;

    Device_init();// Initialize device clock and peripherals
    Device_initGPIO();// Disable pin locks and enable internal pullups.
    Interrupt_initModule();// Initialize PIE and clear PIE registers. Disables CPU interrupts.
    Interrupt_initVectorTable();// Initialize the PIE vector table with pointers to the shell Interrupt
    Board_init();// Board initialization
    EINT;// Enable Global Interrupt (INTM)
    ERTM;// Enable  realtime interrupt (DBGM)

    
    while(1)// Loop forever. Suspend or place breakpoints to observe the buffers.
    {
        counter++;
        // Transmit data
        SPI_writeDataNonBlocking(mySPI0_BASE, sData);// sent 1 byte of sData
        SPI_writeDataNonBlocking(mySPI0_BASE, sData2);// then send 1 byte of SData2
        SPI_writeDataNonBlocking(mySPI0_BASE, sData3);// then send 1 byte of SData3

        if (GPIO_readPin(myGPIO0) == 0) { //when the input goes low, 1 byte of sData, sData2 and sData3 should be transmitted
            if (counter == 1){ // send only during the first loop
                sData = 100000;
                sData2 = 200000;
                sData3 = 4555;
            }
            else { //if counter != 1 send nothing
                sData = 0;
                sData2 = 0;
                sData3 = 0;
            }

        }
        else { // if myGPIO0 == 1 send nothing
                sData = 0;
                sData2 = 0;
                sData3 = 0;
            }

    }
}

//
// End File
//

This code ends up sending only 'sData' repeatedly rather than 'sData', 'sData2' and 'sData3' once each. I checked all the other SPI examples and opened spi.h but couldn't find how to do this.

Any suggestions and examples would be appreciated!

Thanks

- Michael

  • Hi Michael,

    Are you using SPI FIFO? If not, you may need to use the Blocking function call for transfer, to make sure the TX is complete before initiating a new TX.

    The spi_ex1_loopback in C2000ware does not enable FIFO. You can refer to the spi_ex2_loopback_fifo_interrupts for using FIFO.

    If you do not want to use FIFO, use the SPI_writeDataBlockingNonFIFO function instead of SPI_writeDataNonBlocking

    Regards,

    Veena

  • Hi Veena,

    Thanks, using spi_ex2_loopback_fifo_interrupts solved the issue of not being able to send different bytes one after the other. However I am still struggling to find a solution to how I would specify the amount of times I'd want these bytes sent - it is still looping indefinitely. I've tried a for loop with a break and some if statements with no luck. Here's my new code derived from spi_ex2_loopback_fifo_interrupts:

    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    //
    // Globals
    //
    uint16_t sData[3];                  // Send data buffer
    __interrupt void spiTxFIFOISR(void);// Function Prototypes
    
    
    void main(void)// Main
    {
        Device_init();// Initialize device clock and peripherals
        Device_initGPIO();// Disable pin locks and enable internal pullups.
        Interrupt_initModule();// Initialize PIE and clear PIE registers. Disables CPU interrupts.
        Interrupt_initVectorTable();// Initialize the PIE vector table with pointers to the shell Interrupt
        Interrupt_register(INT_SPIA_TX, &spiTxFIFOISR);// Interrupts that are used in this example are re-mapped to ISR functions found within this file.
        Board_init();// Board initialization
    
        // Initialize the data buffers
        sData[0] = 26; //first byte
        sData[1] = 243; //second byte
        sData[2] = 73; //third byte
    
        Interrupt_enable(INT_SPIA_TX);// Enable interrupts required for this example
        EINT;// Enable Global Interrupt (INTM)
        ERTM;// Enable realtime interrupt (DBGM)
    
        while(1)// Loop forever. Suspend or place breakpoints to observe the buffers.
        {
            ;
        }
    }
    
    
    __interrupt void spiTxFIFOISR(void)// SPI A Transmit FIFO ISR
    {
        SPI_writeDataBlockingFIFO(SPIA_BASE, sData[0]);// Send data
        SPI_writeDataBlockingFIFO(SPIA_BASE, sData[1]);// Send data
        SPI_writeDataBlockingFIFO(SPIA_BASE, sData[2]);// Send data
    
        SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_TXFF);// Clear interrupt flag and issue ACK
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
    }
    
    //
    // End File
    //
    

    Any advice on how this could be done is appreciated.

    Thanks,

    - Michael

  • Hi Michael,

    This example is interrupt based, meaning, an interrupt is generated whenever the TX buffer is empty, and data is sent in the Tx interrupt ISR. 

    For your requirement, it would be best not to use TX interrupt and use writeData function as you did in first code snippet

    Regards,

    Veena

  • Hi,

    Is it possible to point to an example or code snippet? I've tried dozens of configurations of both spi_ex1_loopback and spi_ex2_loopback_fifo_interrupts. I still haven't found a way to define how many times the bytes should be transmitted.

    Thanks,

    - Michael

  • HI Michael,

    For the sake of example, we are transmitting data back to back in an infinite loop.

    For your application, please use the SPI_writeDataBlockingFIFO where you would like to initiate a TX.

    Use the spi_ex1_loopback example. Edit the syscfg settings to enable SPI FIFO. Call SPI_writeData function where you need to transfer, not inside the while(1) loop

    Regards,

    Veena

  • OR, if you do not wish to use FIFO, you can sue the settings in spi_ex1_loopback as-is and use SPI_writeDataBlockingNonFIFO function instead of SPI_writeDataNonBlocking.

    Blocking function waits till the TX is complete before initiating a new transfer.

    In case FIFO is enabled, when a new transfer is initiated while a TX is in progress, the new data is pushed to a FIFO memory and is transferred automatically when the current TX is completed.

    Hope this gives a better understanding of SPI_writeDataNonBlocking, SPI_writeDataBlockingNonFIFO and SPI_writeDataBlockingFIFO

    Regards,

    Veena

  • Hi Veena,

    Thanks for the explanation of FIFO and Blocking settings. I've still not found a solution to define the amount of bytes sent- I need the transfer to be initiated as a GPIO input goes low so I'm not sure if I can call the SPI_writeData function outside the while(1) loop since it may need to be continuously initiated and the GPIO will need to be continuously monitored. I've tried both with and without FIFO but it had no effect:

    // Included Files
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    
    uint16_t sData = 0;                  // Send data
    uint16_t sData2 = 0;                  // Send data
    uint16_t sData3 = 0;                  // Send data
    
    // Main
    void main(void)
    {
    
        int counter = 0;
    
        Device_init();// Initialize device clock and peripherals
        Device_initGPIO();// Disable pin locks and enable internal pullups.
        Interrupt_initModule();// Initialize PIE and clear PIE registers. Disables CPU interrupts.
        Interrupt_initVectorTable();// Initialize the PIE vector table with pointers to the shell Interrupt
        Board_init();// Board initialization
        EINT;// Enable Global Interrupt (INTM)
        ERTM;// Enable  realtime interrupt (DBGM)
    
    
        while(1)// Loop forever. Suspend or place breakpoints to observe the buffers.
        {
            SPI_writeDataBlockingFIFO(mySPI0_BASE, sData);
            SPI_writeDataBlockingFIFO(mySPI0_BASE, 0);
            SPI_writeDataBlockingFIFO(mySPI0_BASE, sData2);// then send 1 byte of SData2
            SPI_writeDataBlockingFIFO(mySPI0_BASE, 0);
            SPI_writeDataBlockingFIFO(mySPI0_BASE, sData3);// then send 1 byte of SData3
            SPI_writeDataBlockingFIFO(mySPI0_BASE, 0);
    
            if (myGPIO0 == 0) {     //if the input is low, counter is reset to 0
                counter = 0;
            }
    
            if (counter < 1000){    //counter stops counting at 1000 to avoid resetting
                counter++;
            }
    
    
            if (counter == 400) {   // as the counter hits a value of 400, initiate a transfer
                sData = 8456;
                sData2 = 98;
                sData3 = 4555;
            }
            else {  // for all other counter values, data = 0
                sData = 0;
                sData2 = 0;
                sData3 = 0;
            }
    
        }
    }
    
    //
    // End File
    //
    

    This is the closest I've gotten - being able to trigger a single initial transfer but the SPI transfer won't initiate as the input goes low after the first transfer. With other trials I've done of changing the counter, SPI_writeData, and adding debouncing, the SPI transfer either does not respond to the input or transfers unpredictably.

    I'm mostly looking for a technique from an experienced C developer on how SPI_writeData should be called as the input goes low. It is a pretty simple request: transfer sData once when the input goes low.

    Code examples are most useful

    Thanks,

    - Michael

  • Hi Michael,

    Why don't you configure the GPIO to trigger an interrupt, and you send the SPI Data in the interrupt ISR?

    To know more about GPIO interrupts, you can refer to gpio_ex3_interrupt example

    Regards,

    Veena

  • Thanks Veena, that worked. Putting SPI_writeData in the interrupt didn't, but resetting the counter in the interrupt instead of the while loop worked. Here's the code for anyone else needing it:

    // Included Files
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    __interrupt void gpioInterruptHandler(void);
    
    int counter = 0;
    uint16_t sData = 0;                  // Send data
    uint16_t sData2 = 0;                  // Send data
    uint16_t sData3 = 0;                  // Send data
    
    // Main
    void main(void)
    {
    
        Device_init();// Initialize device clock and peripherals
        Device_initGPIO();// Disable pin locks and enable internal pullups.
        Interrupt_initModule();// Initialize PIE and clear PIE registers. Disables CPU interrupts.
        Interrupt_initVectorTable();// Initialize the PIE vector table with pointers to the shell Interrupt
        Board_init();// Board initialization
        EINT;// Enable Global Interrupt (INTM)
        ERTM;// Enable  realtime interrupt (DBGM)
    
        GPIO_setInterruptType(GPIO_INT_XINT1, GPIO_INT_TYPE_FALLING_EDGE);
        GPIO_setInterruptPin(myGPIO0, GPIO_INT_XINT1);
        GPIO_enableInterrupt(GPIO_INT_XINT1);
    
        Interrupt_register(INT_XINT1, &gpioInterruptHandler);
        Interrupt_enable(INT_XINT1);
        Interrupt_enableMaster();
    
    
        while(1)// Loop forever. Suspend or place breakpoints to observe the buffers.
        {
            SPI_writeDataBlockingFIFO(mySPI0_BASE, sData);
            SPI_writeDataBlockingFIFO(mySPI0_BASE, 0);
            SPI_writeDataBlockingFIFO(mySPI0_BASE, sData2);// then send 1 byte of SData2
            SPI_writeDataBlockingFIFO(mySPI0_BASE, 0);
            SPI_writeDataBlockingFIFO(mySPI0_BASE, sData3);// then send 1 byte of SData3
            SPI_writeDataBlockingFIFO(mySPI0_BASE, 0);
    
    
            if (counter < 1000){    //counter stops counting at 1000 to avoid resetting
                counter++;
            }
    
    
            if (counter == 400) {   // as the counter hits a value of 400, initiate a transfer
                sData = 8456;
                sData2 = 98;
                sData3 = 4555;
            }
            else {  // for all other counter values, data = 0
                sData = 0;
                sData2 = 0;
                sData3 = 0;
            }
    
        }
    }
    
    
    __interrupt void gpioInterruptHandler(void)
    {
        counter = 0;
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
    }
    
    //
    // End File
    //
    

    Thanks,

    - Michael