I am new to TM4C Microcontroller. I want to communicate between two TM4c1230d5pm through SPI, So that immediately after sending 1 byte as command by the master, the slave returns a byte of data.
1) RXFF Interrupt is raised only if RX FIFO is half-full or more. In case I would like to receive just one Byte, I should try another way.
2) RXTO Interrupt is raised basically 32 SSIClk periods after at least one character has been received into the RX FIFO. With this approach, if only one byte is recieved, I will get this interrupt with 32 SSIClk delay and this delay is a problem for my application.
That's why I used GPIO_INT, So when the falling edge occur in CS pin, Slave must return a Byte of data according to received Byte of command. But stuck in SSIDataGet(SSI0_BASE,&DataRx0[0]) in the interrupt handler.
Regards,
B.
/////////////////////////////SPI slave code/////////////////////////// #include <stdint.h> #include <stdio.h> #include <string.h> #include <stdbool.h> #include "inc/hw_i2c.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/debug.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "driverlib/pwm.h" #include "driverlib/pin_map.h" #include "inc/hw_gpio.h" #include "driverlib/rom.h" #include "driverlib/i2c.h" #include "driverlib/ssi.h" #include "driverlib/eeprom.h" #include "driverlib/adc.h" //SPI0 Definition #define SSI0_PERIPH SYSCTL_PERIPH_GPIOA #define SSI0_PORT GPIO_PORTA_BASE #define SCK0_PIN GPIO_PIN_2 #define CS_PIN GPIO_PIN_3 #define RX0_PIN GPIO_PIN_4 #define TX0_PIN GPIO_PIN_5 uint32_t DataRx0[4]; uint32_t DataTx0[4]; uint8_t Int_Active=0; void SPI0Init(void); void GPIOIntHandler(void); int main(void) { SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_3); SPI0Init(); IntEnable(INT_GPIOA); GPIOIntClear(GPIO_PORTA_BASE,GPIO_PIN_3); GPIOIntTypeSet(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_FALLING_EDGE); GPIOIntEnable(GPIO_PORTA_BASE, GPIO_PIN_3); IntMasterEnable(); while(1) { } } void SPI0Init(void) { uint32_t FIFO; // // The SSI1 peripheral must be enabled for use. // SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); // // For this example SSI1 is used with PortD[3:0]. The actual port and pins // SysCtlPeripheralEnable(SSI0_PERIPH); // // Configure the pin muxing for SSI1 functions on port D0, D1, D2, and D3. // GPIOPinConfigure(GPIO_PA2_SSI0CLK); // GPIOPinConfigure(GPIO_PA3_SSI0FSS); GPIOPinConfigure(GPIO_PA4_SSI0RX); GPIOPinConfigure(GPIO_PA5_SSI0TX); // // Configure the GPIO settings for the SSI pins. This function also gives // control of these pins to the SSI hardware. Consult the data sheet to GPIOPinTypeSSI(SSI0_PORT, SCK0_PIN | RX0_PIN | TX0_PIN ); // Configure and enable the SSI port for SPI master mode. Use SSI1, // system clock supply, idle clock level low and active low clock in // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data. // For SPI mode, you can set the polarity of the SSI clock when the SSI // unit is idle. You can also configure what clock edge you want to // capture data on. SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_SLAVE, 1000000, 8); // // Enable the SSI1 module. // SSIEnable(SSI0_BASE); // // Read any residual data from the SSI port. This makes sure the receive // FIFOs are empty, so we don't read any unwanted junk. This is done here // because the SPI SSI mode is full-duplex, which allows you to send and // receive at the same time. The SSIDataGetNonBlocking function returns // "true" when data was returned, and "false" when no data was returned. // The "non-blocking" function checks if there is any data in the receive // FIFO and does not "hang" if there isn't. // while(SSIDataGetNonBlocking(SSI0_BASE, &FIFO)); } void GPIOIntHandler(void) { GPIOIntClear(GPIO_PORTA_BASE,GPIO_PIN_3); SSIDataGet(SSI0_BASE,&DataRx0[0]); while(SSIBusy(SSI0_BASE)); if(DataRx0[0]==0x11) { SSIDataPut(SSI0_BASE,0x01); while(SSIBusy(SSI0_BASE)); SSIDataGet(SSI0_BASE,&DataRx0[1]); } else if(DataRx0[0]==0x22) { SSIDataPut(SSI0_BASE,0x02); while(SSIBusy(SSI0_BASE)); SSIDataGet(SSI0_BASE,&DataRx0[1]); } }
/////////////////////////////SPI master code/////////////////////////// #include <stdint.h> #include <stdio.h> #include <string.h> #include <stdbool.h> #include "inc/hw_i2c.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/debug.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "driverlib/pwm.h" #include "driverlib/pin_map.h" #include "inc/hw_gpio.h" #include "driverlib/rom.h" #include "driverlib/i2c.h" #include "driverlib/ssi.h" #include "driverlib/eeprom.h" #include "driverlib/adc.h" //SPI1 Definition #define CS_PERIPH SYSCTL_PERIPH_GPIOD #define CS_PORT GPIO_PORTD_BASE #define CS_PIN GPIO_PIN_1 #define SSI1_PERIPH SYSCTL_PERIPH_GPIOD #define SSI1_PORT GPIO_PORTD_BASE #define SCK1_PIN GPIO_PIN_0 #define RX1_PIN GPIO_PIN_2 #define TX1_PIN GPIO_PIN_3 uint32_t DataRx1[4]; uint32_t DataTx1[4]; void SPI1Init(void); int main(void) { uint32_t c=0; SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_0| GPIO_PIN_1); SPI1Init(); while(1) { // send data every 5s c++; if (c==5) { // send data1 //CS=1 CS=0 GPIOPinWrite(CS_PORT,CS_PIN,CS_PIN); SysCtlDelay(SysCtlClockGet()/3/100000); GPIOPinWrite(CS_PORT,CS_PIN,0); SysCtlDelay(SysCtlClockGet()/3/100000); SSIDataPut(SSI1_BASE,0x11); while(SSIBusy(SSI1_BASE)); SSIDataGet(SSI1_BASE,&DataRx1[0]); while(SSIBusy(SSI1_BASE)); GPIOPinWrite(CS_PORT,CS_PIN,CS_PIN); SysCtlDelay(SysCtlClockGet()/3/100000); } else if (c==10) { c = 0; // send data2 //CS=1 CS=0 GPIOPinWrite(CS_PORT,CS_PIN,CS_PIN); SysCtlDelay(SysCtlClockGet()/3/100000); GPIOPinWrite(CS_PORT,CS_PIN,0); SysCtlDelay(SysCtlClockGet()/3/100000); SSIDataPut(SSI1_BASE,0x22); while(SSIBusy(SSI1_BASE)); SSIDataGet(SSI1_BASE,&DataRx1[0]); GPIOPinWrite(CS_PORT,CS_PIN,CS_PIN); SysCtlDelay(SysCtlClockGet()/3/100000); } SysCtlDelay(SysCtlClockGet()/3); } } void SPI1Init(void) { uint32_t FIFO; // CS=1 SysCtlPeripheralEnable(CS_PERIPH); GPIOPinTypeGPIOOutput(CS_PORT, CS_PIN); GPIOPinWrite(CS_PORT,CS_PIN,CS_PIN); // // The SSI1 peripheral must be enabled for use. // SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1); // // For this example SSI1 is used with PortD[3:0]. The actual port and pins // SysCtlPeripheralEnable(SSI1_PERIPH); // // Configure the pin muxing for SSI1 functions on port D0, D1, D2, and D3. // GPIOPinConfigure(GPIO_PD0_SSI1CLK); // GPIOPinConfigure(GPIO_PD1_SSI1FSS); GPIOPinConfigure(GPIO_PD2_SSI1RX); GPIOPinConfigure(GPIO_PD3_SSI1TX); // // Configure the GPIO settings for the SSI pins. This function also gives // control of these pins to the SSI hardware. Consult the data sheet to GPIOPinTypeSSI(SSI1_PORT, SCK1_PIN | RX1_PIN | TX1_PIN); // Configure and enable the SSI port for SPI master mode. Use SSI1, // system clock supply, idle clock level low and active low clock in // freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data. // For SPI mode, you can set the polarity of the SSI clock when the SSI // unit is idle. You can also configure what clock edge you want to // capture data on. SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); // // Enable the SSI1 module. // SSIEnable(SSI1_BASE); // while(SSIDataGetNonBlocking(SSI1_BASE, &FIFO)); }