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.

CCS/TM4C123GH6PM: SPI read on TM4C123GH6PM

Part Number: TM4C123GH6PM

Tool/software: Code Composer Studio

Hi all,

I am currently working on an SPI read function to pull data from an accelerometer (AIS328DQ) and am not able to see any traffic on the MISO line. I am able to see the correct traffic on the MOSI line where I am attempting to read from a specific address, but the MISO line is 0xFF when the correct value I should see according to the datasheet is 0x32. I have pasted my code below and also the screenshot from my logic analyzer

void PortBInit()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    //GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_5);
    //GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, GPIO_PIN_1);

    GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    GPIOPinConfigure(GPIO_PB5_SSI2FSS);
    GPIOPinConfigure(GPIO_PB7_SSI2TX);
    GPIOPinConfigure(GPIO_PB6_SSI2RX);

    GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 |
                       GPIO_PIN_4);
}
void SPIInit()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI2))
    {
    }

    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);
    //moto_mode_3 -> CPOL = 1, CPHA = 1
    SSIDisable(SSI2_BASE);
    SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 1000000, 8);
    SSIEnable(SSI2_BASE);
}

void AIS328DQ::read(uint8_t numBytes, uint8_t registerAddress)
{
    uint8_t bytesProcessed = 0;
    //first byte send contains address we want to read from
    //second byte sent contains 0's
    uint8_t addReadBit = 0x80;
    TxDataArray[0] = (registerAddress | addReadBit);
    TxDataArray[1] = 0x00;
    // Read any residual data from the SSI port.  This makes sure the receive
    // FIFOs are empty, so we don't read any unwanted junk.
    // The "non-blocking" function checks if there is any data in the receive
    // FIFO and does not "hang" if there isn't.
    while(SSIDataGetNonBlocking(SSI2_BASE, &RxDataArray[0]));
    //SSIDataGet(SSI2_BASE, &RxDataArray[0]);

    while (bytesProcessed < numBytes)
    {
        //put data into the Tx FIFO
        while (SSIBusy(SSI2_BASE));

        SSIDataPut(SSI2_BASE, TxDataArray[bytesProcessed]);
        //chill out for a bit
        while(SSIBusy(SSI2_BASE)); //look into this

        SSIDataGet(SSI2_BASE, &RxDataArray[bytesProcessed]);

        bytesProcessed++;
    }
}

uint8_t AIS328DQ::getWhoAmI()
{
    uint8_t whoAmI;
    read(2, WHO_AM_I);
    whoAmI = RxDataArray[1] & 0x000000FF; //should be in index 1 of array
    return whoAmI;
}

Any help is greatly appreciated. Thanks!

  • Kyle Garland said:
    I am currently working on an SPI read function to pull data from an accelerometer (AIS328DQ) and am not able to see any traffic on the MISO line.

    The AIS328DQ datasheet shows that the CS must remain low for the entire read or write transaction. E.g.:

    And the AIS328DQ only drives SDO on the second set of 8 clock pulses when CS is low.

    Whereas your LSA capture shows "SPI ENABLE":

    • goes low for the first byte
    • goes high
    • goes low for the second byte

    As a result I think the AIS328DQ will never drive the MISO signal.

    Since the AIS328DQ uses 16-bit transfers, and the TM4C123GH6PM asserts FSS for one frame, try setting the SPI to use a 16-bit frame by changing the SSIConfigSetExpClk() ui32DataWidth argument to 16. I.e.:

       SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 1000000, 16);

  • Hi Chester,

    I was also wondering why the CS line wasn't staying low, and it makes sense to change the Config to 16 bits instead of 8. I will try that out and see what happens.

    Thanks!

  • I changed the DataWidth parameter but am getting some interesting results from the logic analyzer. The MSB is sent first and since the TivaWare function parameters for SSI transmit and receive use 32 bits (not sure why when the fifo length is 16 bits), there is 0's being sent first, then my data. Attached is the screenshot.

    The data sent should be 0x20 0x27 instead of 0x00 before each byte.

    At this point I have typecasted everything to uint8_t, but still gets this result.

  • Kyle Garland said:
    The data sent should be 0x20 0x27 instead of 0x00 before each byte.

    When the data width is 16-bits then the SSIDataGet() and SSIDataPut() functions operate on 16-bits at once. I.e. you will need to change your code to call SSIDataPut() and SSIDataGet() once for each 16-bit transfer for the AIS328DQ. See the following notes for the functions:

    24.2.2.10 SSIDataGet

    Note:
    Only the lower N bits of the value written to pui32Data contain valid data, where N is the data width as configured by SSIConfigSetExpClk(). For example, if the interface is configured for 8-bit data width, only the lower 8 bits of the value written to pui32Data contain valid data.

    24.2.2.12 SSIDataPut

    Note:
    The upper 32 - N bits of ui32Data are discarded by the hardware, where N is the data width as configured by SSIConfigSetExpClk(). For example, if the interface is configured for 8-bit data width, the upper 24 bits of ui32Data are discarded.