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.

TCAN4550: SPI connection with CC1352R

Part Number: TCAN4550
Other Parts Discussed in Thread: CC1352R,

Greetings! I am trying to set up SPI connection between CC1352R and TCAN4550 using spimaster example of CC13x2_26x2 SDK v3.10.01.11. To test the connection, I want to read TCAN4550 0x0000 register which contains device ID information (0x54, 0x43, 0x41, 0x4E according to datasheet, p.45). 

The problem is - whatever CC1352R transfers to TCAN4550, it always reads 0xc8 or 0x89 value, if TCAN is turned on and not sleeping. So there is some response, but the way of communication seems to be incorrect. Can someone pleas help to set the SPI?


The code is listed below:

/*
 *  ======== spimaster.c ========
 */
#include <stddef.h>
#include <stdint.h>
#include <string.h>

/* POSIX Header files */
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/display/Display.h>

/* Example/Board Header files */
#include "Board.h"

#define THREADSTACKSIZE (1024)

#define SPI_MSG_LENGTH  (4)

#define MAX_LOOP        (10)


static Display_Handle display;

unsigned char masterRxBuffer[4];
unsigned char masterTxBuffer[4];

/*
 *  ======== masterThread ========
 *  Master SPI sends a message to slave while simultaneously receiving a
 *  message from the slave.
 */
void *masterThread(void *arg0)
{
    SPI_Handle      masterSpi;
    SPI_Params      spiParams;
    SPI_Transaction transaction;
    bool            transferOK;

    const char MASTER_MSG[SPI_MSG_LENGTH] = {0x41, 0x00, 0x00, 0x01};

    /* Open SPI as master */
    spiParams.frameFormat = SPI_POL0_PHA1;
    spiParams.bitRate = 4000000;
    spiParams.mode = SPI_MASTER;
    SPI_Params_init(&spiParams);
    masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
    if (masterSpi == NULL) {
        Display_printf(display, 0, 0, "Error initializing master SPI\n");
        while (1);
    }
    else {
        Display_printf(display, 0, 0, "Master SPI initialized\n");
    }

        strncpy((char *) masterTxBuffer, MASTER_MSG, SPI_MSG_LENGTH);
        memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);
        transaction.count = SPI_MSG_LENGTH;
        transaction.txBuf = (void *) masterTxBuffer;
        transaction.rxBuf = (void *) masterRxBuffer;

        transferOK = SPI_transfer(masterSpi, &transaction);

        if (transferOK) {
            Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[0]);
            Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[1]);
            Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[2]);
            Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[3]);
            }
        else {
            Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
        }


    SPI_close(masterSpi);

    Display_printf(display, 0, 0, "\nDone");

    return (NULL);
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    pthread_t           thread0;
    pthread_attr_t      attrs;
    struct sched_param  priParam;
    int                 retc;
    int                 detachState;

    /* Call driver init functions. */
    Display_init();
    GPIO_init();
    SPI_init();

    /* Configure the LED pins */
    GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

    /* Open the display for output */
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        /* Failed to open display driver */
        while (1);
    }

    /* Turn on user LED */
    GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);

    Display_printf(display, 0, 0, "Starting the SPI master example");
    Display_printf(display, 0, 0, "This example requires external wires to be "
        "connected to the header pins. Please see the Board.html for details.\n");

    /* Create application threads */
    pthread_attr_init(&attrs);

    detachState = PTHREAD_CREATE_DETACHED;
    /* Set priority and stack size attributes */
    retc = pthread_attr_setdetachstate(&attrs, detachState);
    if (retc != 0) {
        /* pthread_attr_setdetachstate() failed */
        while (1);
    }

    retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
    if (retc != 0) {
        /* pthread_attr_setstacksize() failed */
        while (1);
    }

    /* Create master thread */
    priParam.sched_priority = 1;
    pthread_attr_setschedparam(&attrs, &priParam);

    retc = pthread_create(&thread0, &attrs, masterThread, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1);
    }

    return (NULL);
}

  • Hello,

    Have you tried viewing the SPI signals on an oscilloscope? That can be useful for debug since it could verify all the hardware connections (as well as physical layer requirements like signal levels and timing) as well as verify whether the intended operations are actually occurring (or if there are some fixes needed to the software).

    Regards,

    Max

  • Hi,

    If referenced to the first 8 bits of TCAN4550's interrupt register, 0xC8 and 0x89 share the flags for Global Error and SPI Error. Since TCAN4550 transmits the contents of this register during the command phase of every transaction (when nCS is active) it is possible that this value is getting written to CC1352R RXbuffer. The indicated SPI error may occur when there are not exact multiple of 32 bits detected by TCAN4550 during one SPI transaction (nCS low). 

    As Max suggested, scope shots of the SPI lines (SDI, SDO, SCLK, and nCS) would help diagnose what is causing the potential error or misinterpretation. It may also be good to double check the code for all the data lengths being used (I did not see mismatches in what you have shared) and that nCS goes high after each transaction.

    Regards,

    Eric

  • Greetings Colleagues!
    Thanks for your help!

    I have resolved my issue. The problem was in the length SPI of message.  The CC13x2 SDK SPI library allows to transfer only 8 bit or 16 bit transfers, but TCAN 4550 needs 32 bit, so the nCS pin goes high after transfering every 8 bits of message. Thus, TCAN4550 generates error. As workaround I have used another pin instead of nCS and manually set it to low before the transfer, and high after the transfer. 
    Also, transfer works only in Polarity = 0, Phase = 0 mode.

    My code changes are listed below. Maybe it will help to someone with the same problem.

    *  ======== spimaster.c ========
     */
    #include <stddef.h>
    #include <stdint.h>
    #include <string.h>
    
    /* POSIX Header files */
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/SPI.h>
    #include <ti/display/Display.h>
    
    /* Example/Board Header files */
    #include "Board.h"
    
    #define THREADSTACKSIZE (1024)
    
    #define SPI_MSG_LENGTH  (4)
    
    #define MAX_LOOP        (10)
    
    #define HWREG8(x)                                                             \
            (*((volatile uint8_t *)((uint16_t)x)))
    
    static Display_Handle display;
    
    unsigned char masterRxBuffer[4];
    unsigned char masterTxBuffer[4];
    
    /*
     *  ======== masterThread ========
     *  Master SPI sends a message to slave while simultaneously receiving a
     *  message from the slave.
     */
    void *masterThread(void *arg0)
    {
        SPI_Handle      masterSpi;
        SPI_Params      spiParams;
        SPI_Transaction transaction;
        bool            transferOK;
    
        const char MSG1[SPI_MSG_LENGTH] = {0x41, 0x00, 0x00, 0x01};
    
        const char MSG2[SPI_MSG_LENGTH] = {0x00, 0x00, 0x00, 0x00};
    
    
        /* Open SPI as master (default) */
        SPI_Params_init(&spiParams);
        spiParams.frameFormat = SPI_POL0_PHA0; //works only in this mode
        spiParams.bitRate = 2000000;
        masterSpi = SPI_open(Board_SPI_MASTER, &spiParams);
        if (masterSpi == NULL) {
            Display_printf(display, 0, 0, "Error initializing master SPI\n");
            while (1);
        }
        else {
            Display_printf(display, 0, 0, "Master SPI initialized\n");
        }
    
            sleep (1); //without a pause doesn't work
    
            strncpy((char *) masterTxBuffer, MSG1, SPI_MSG_LENGTH);
            memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);
            transaction.count = SPI_MSG_LENGTH;
            transaction.txBuf = (void *) masterTxBuffer;
            transaction.rxBuf = (void *) masterRxBuffer;
    
            GPIO_write(Board_GPIO_LED1, 0); //DIO7 instead of nCS, goes low and activates transfer
    
            transferOK = SPI_transfer(masterSpi, &transaction);
    
            sleep (1);
    
    
            strncpy((char *) masterTxBuffer, MSG2, SPI_MSG_LENGTH);
            memset((void *) masterRxBuffer, 0, SPI_MSG_LENGTH);
            transaction.count = SPI_MSG_LENGTH;
            transaction.txBuf = (void *) masterTxBuffer;
            transaction.rxBuf = (void *) masterRxBuffer;
    
            transferOK = SPI_transfer(masterSpi, &transaction);
    
            GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON); //DIO7 instead of nCS, goes high and ends transfer
    
            if (transferOK) {
                Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[0]);
                Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[1]);
                Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[2]);
                Display_printf(display, 0, 0, "Master received: %x", masterRxBuffer[3]);
                }
            else {
                Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
            }
    
    
        SPI_close(masterSpi);
    
        Display_printf(display, 0, 0, "\nDone");
    
        return (NULL);
    }

    BR.
    Dmitriy

  • Hi Dmitriy,

    Thanks for sharing your solution! I'm glad to see you were able to find a work-around. 

    Regards,

    Eric