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.

Compiler/TM4C123GH6PZ: SPI communication

Part Number: TM4C123GH6PZ
Other Parts Discussed in Thread: EK-TM4C123GXL

Tool/software: TI C/C++ Compiler

Hi sir,

I am facing some issue in SPI communication.In my program sending data from Master device to slave device and read the data from slave and display it on UART. Both master and slave are using same microcontroller(TM4c123GH6PZ). So I am writing separate program for Master and slave.In master device, flashing program is for sending a character and the Slave board ,flashing program is for reading and display the received character through UART.

Given blow is my Master Transmission program

SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0));
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
GPIOPinConfigure(GPIO_PA2_SSI0CLK);
GPIOPinConfigure(GPIO_PA3_SSI0FSS);
GPIOPinConfigure(GPIO_PA4_SSI0RX);
GPIOPinConfigure(GPIO_PA5_SSI0TX);
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 |GPIO_PIN_3 | GPIO_PIN_2);

SSIConfigSetExpClk(SYSCTL_PERIPH_SSI0,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER,1000000,8);

SSIEnable(SYSCTL_PERIPH_SSI0);

SSIDataPut(SSI0_BASE,'A');
while(SSIBusy(SSI0_BASE));

Reception program in Slave given below

SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);//enable both peripherals:
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0));
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
GPIOPinConfigure(GPIO_PA2_SSI0CLK);
GPIOPinConfigure(GPIO_PA3_SSI0FSS);
GPIOPinConfigure(GPIO_PA4_SSI0RX);
GPIOPinConfigure(GPIO_PA5_SSI0TX);
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 |GPIO_PIN_3 | GPIO_PIN_2);

SSIConfigSetExpClk(SYSCTL_PERIPH_SSI0,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_SLAVE,1000000,8);

SSIEnable(SYSCTL_PERIPH_SSI0);

 while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx));

SSIDataGet(SSI0_BASE,&pui32DataRx);
UARTCharPut(UART0_BASE, pui32DataRx);

void InitConsole(void) //UART initialization 
{
UARTClockSourceSet(SYSCTL_PERIPH_UART0,UART_CLOCK_SYSTEM);
//
// Enable the UART0 module.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
//
// Wait for the UART0 module to be ready.
//
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_NONE));
}

  • Hi sir,
    Sorry I didn't explain what issue I am facing. I Am not able to display the character sending from my master device.The hardware is working fine. I am not getting the issue with software.
    Thank you,
    Alphy
  • Hello Alphy,

    Have you checked if you are receiving the character correctly via a breakpoint? This would narrow down if the issue is with the SPI transmission, or the UART display.
  • Hi sir,

    I put break point and tested, in receiving field I am not able to read any data.But the device is communicating and it sending some garbage value in UART. Given below is the data receiving in UART. 

    11/30/2018 09:59:06.336 [RX] - <NUL><NUL>ÿ °?<NUL><NUL><NUL><NUL>?€<NUL><NUL><NUL><NUL>

    The given below is the slave data reception step.

    SSIEnable(SSI0_BASE);
    SSIDataGet(SSI0_BASE,&pui32DataRx);
    char_rx=(char) pui32DataRx;
    UARTCharPut(UART0_BASE, char_rx);

    I need to add any other functions in reception program to solve this issue.

    Thank you,

    Alphy

  • Hello Alphy,

    Thanks for that information, I had the time today to put your code into projects and run some tests. Here are my findings on issues within the code:

    1) SSIConfigSetExpClk and SSIEnable need to be configured with SSI0_BASE, NOT SYSCTL_PERIPH_SSI0

    2) Your InitConsole didn't work properly for me, I used the following:

    //*****************************************************************************
    
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
    	//
    	// Enable UART0 so that we can configure the clock.
    	//
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    	//
    	// Enable GPIO port A which is used for UART0 pins.
    	// TODO: change this to whichever GPIO port you are using.
    	//
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
    	//
    	// Configure the pin muxing for UART0 functions on port A0 and A1.
    	// This step is not necessary if your part does not support pin muxing.
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinConfigure(GPIO_PA0_U0RX);
    	GPIOPinConfigure(GPIO_PA1_U0TX);
    
    	//
    	// Use the internal 16MHz oscillator as the UART clock source.
    	//
    	UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
    	//
    	// Select the alternate (UART) function for these pins.
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
    	//
    	// Initialize the UART for console I/O.
    	//
    	UARTStdioConfig(0, 115200, 16000000);
    }

    3) Your receive won't work unless your codes turn on at the exact same time as the while loop you used will exit the first time no data is present, instead use this:

    while(!(SSIDataGetNonBlocking(SSI2_BASE, &pui32DataRx)));

    4) I don't think the second SSIDataGet makes sense here because you need to fetch one byte and you are already doing that in the line above, I would comment this out.

    Please try applying these changes and see if you get further progress.

  • Hello Ralph,

    1) SSIConfigSetExpClk and SSIEnable need to be configured with SSI0_BASE, NOT SYSCTL_PERIPH_SSI0 

    Already corrected this error.

    2) Your InitConsole didn't work properly for me, I used the following:

    InitConsole working properly for me

    I tried to display one character inside my init console and it is printing correct data in UART.

    3) Your receive won't work unless your codes turn on at the exact same time as the while loop you used will exit the first time no data is present, instead use this:

    while(!(SSIDataGetNonBlocking(SSI2_BASE, &pui32DataRx)));

    This one I tried still I am not getting any response. I used break point and checked still I am not receiving any character in debugger also.

    SSIEnable(SSI0_BASE);
    SSIDataGet(SSI0_BASE,&pui32DataRx);
    char_rx=(char) pui32DataRx;
    pui32DataRx &= 0x00FF;
    UARTCharPut(UART0_BASE, char_rx);

    once the debugger is reached in the highlighted section  then the arrow is not moving towards next function. Please find the attached image of debugger section for more clarification.

    Thank you, 

    Alphy

  • Hi Alphy,

    You can try a busy check after SSIDataGet also
    Ex:
    SSIDataGet(SSI0_BASE,&pui32DataRx);

    while(SSIBusy(SSI0_BASE))
    {
    }
    UARTCharPut(UART0_BASE, pui32DataRx);


    Regards
    Asif
  • Hi sir,

    I tried all those things still it is stopping there at SSIDataGet(SSI0_BASE,&pui32DataRx)  function.

    Whatever the data I am sending from master TX pin it is receiving at the RX pin of slave, it is verified using logical analyzer.

     I am having doubt about chip select also, SSI_FRF_MOTO_MODE_0 function is the chip selection function or is there any other method for make chip select low.

    Please help me to solve the issue.

    Thank you,

    Alphy

  • Hello Alphy,

    To make it simple, I am attaching c files for both master and slave which uses SSI0 to transmit a single byte and then on the slave receive that byte and print to UART. I tested this with EK-TM4C123GXL LaunchPad and it works well. Please try using this and see if your problem is resolved. If so, compare the configurations and code flow to see if you can learn what went wrong.

    Master: 

    //*****************************************************************************
    //
    // ti_master.c - Example demonstrating how to configure SSI2 in TI master mode.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/pwm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    #include "math.h"
    #include "driverlib/ssi.h"
    #include "driverlib/qei.h"
    
    //*****************************************************************************
    //
    //! \addtogroup ssi_examples_list
    //! <h1>TI Master (ti_master)</h1>
    //!
    //! This example shows how to configure the SSI0 as TI Master.  The code will
    //! send three characters on the master Tx then poll the receive FIFO until
    //! 3 characters are received on the master Rx.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - SSI2 peripheral
    //! - GPIO Port B peripheral (for SSI2 pins)
    //! - SSI2Clk - PB4
    //! - SSI2Fss - PB5
    //! - SSI2Rx  - PB6
    //! - SSI2Tx  - PB7
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of I2C0.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - None.
    //
    //*****************************************************************************
    
    
    //*****************************************************************************
    //
    // Main function entry starts here
    //
    //*****************************************************************************
    int
    main(void)
    {
    	SysCtlClockSet(SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL|SYSCTL_SYSDIV_5);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0));
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
    	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    	GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	GPIOPinConfigure(GPIO_PA5_SSI0TX);
    	GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 |GPIO_PIN_3 | GPIO_PIN_2);
    
    	SSIConfigSetExpClk(SSI0_BASE,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER,1000000,8);
    
    	SSIEnable(SSI0_BASE);
    
    	SSIDataPut(SSI0_BASE,'A');
    	while(SSIBusy(SSI0_BASE));
    
    }
    
    
    

    Slave: 

    //*****************************************************************************
    //
    // ti_Slave.c - Example demonstrating how to configure SSI2 in TI master mode.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/pwm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/systick.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    #include "math.h"
    #include "driverlib/ssi.h"
    #include "driverlib/qei.h"
    
    //*****************************************************************************
    //
    //! \addtogroup ssi_examples_list
    //! <h1>TI Master (ti_master)</h1>
    //!
    //! This example shows how to configure the SSI0 as TI Master.  The code will
    //! send three characters on the master Tx then poll the receive FIFO until
    //! 3 characters are received on the master Rx.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - SSI2 peripheral
    //! - GPIO Port B peripheral (for SSI2 pins)
    //! - SSI2Clk - PB4
    //! - SSI2Fss - PB5
    //! - SSI2Rx  - PB6
    //! - SSI2Tx  - PB7
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of I2C0.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - None.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Global variables used in interrupt handler and the main loop.
    //
    //*****************************************************************************
    uint32_t pui32DataRx;
    
    //*****************************************************************************
    
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
    	//
    	// Enable UART0 so that we can configure the clock.
    	//
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
    	//
    	// Enable GPIO port A which is used for UART0 pins.
    	// TODO: change this to whichever GPIO port you are using.
    	//
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
    	//
    	// Configure the pin muxing for UART0 functions on port A0 and A1.
    	// This step is not necessary if your part does not support pin muxing.
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinConfigure(GPIO_PA0_U0RX);
    	GPIOPinConfigure(GPIO_PA1_U0TX);
    
    	//
    	// Use the internal 16MHz oscillator as the UART clock source.
    	//
    	UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
    	//
    	// Select the alternate (UART) function for these pins.
    	// TODO: change this to select the port/pin you are using.
    	//
    	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
    	//
    	// Initialize the UART for console I/O.
    	//
    	UARTStdioConfig(0, 115200, 16000000);
    }
    
    
    //*****************************************************************************
    //
    // Main function entry starts here
    //
    //*****************************************************************************
    int
    main(void)
    {
    	SysCtlClockSet(SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_PLL|SYSCTL_SYSDIV_5);
    
    	InitConsole();
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0));
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
    	GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    	GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	GPIOPinConfigure(GPIO_PA5_SSI0TX);
    	GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 |GPIO_PIN_3 | GPIO_PIN_2);
    
    	SSIConfigSetExpClk(SSI0_BASE,SysCtlClockGet(),SSI_FRF_MOTO_MODE_0,SSI_MODE_SLAVE,1000000,8);
    
    	SSIEnable(SSI0_BASE);
    
    	while(1)
    	{
    
    		SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx);
    
    		if (pui32DataRx)
    		{
    			UARTCharPut(UART0_BASE, pui32DataRx);
    			pui32DataRx = 0x00;
    		}
    	}
    }
    

  • Hi sir,

    Thank you so much for sending the code, I tried that code also but it is not reading the data. I think some issue related to clock rate.I really appreciate your help sir.

    I will check if there any issue with my slave device. 

    Again thank you so much for your help sir.

    Thank you,

    Alphy