Hello,
I am getting familiar with the EK-TM4C1294XL board, trying to learn some basic things about ARM Cortex-M4 MCUs.
I need some help after having spent the entire day trying to implement SPI on EK-TM4C1294XL board.
I have browsed through several similar topics on this forum and played a little according to the suggestions therein, however without success. That is why I decided to make a new post.
The SPI device is an Analog Devices ADXL362 accelerometer that is mounted on a small breakout PCB. I have used that device sucessfully with a Raspberry Pi in the past.
Connections are as follows: I use the pins of the stacking connectors X6 and X7:
PQ0: SCLK
PQ1: ~CS
PQ2: MOSI
PQ3: MISO
I use Open Bench Logic Sniffer on my laptop PC to spy on the SPI bus. The TiVa evaluation kit runs on my desktop PC.
The code I use is the following:
// InitSPI3() - initialize SPI on SSI3 // Based on code that is available at: // e2e.ti.com/.../1429666 void InitSPI3(uint32_t SystemClock, uint32_t SPIMode, uint32_t SPIBitRate) { // The SSI3 peripheral must be enabled for use. MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); // Configure the pin muxing for SSI0 functions on port Q0, Q1, Q2, and Q3. MAP_GPIOPinConfigure(GPIO_PQ0_SSI3CLK); // SCLK MAP_GPIOPinConfigure(GPIO_PQ1_SSI3FSS); // ~CS MAP_GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0); // MOSI MAP_GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1); // MISO // Configure the GPIO settings for the SSI pins. This function also gives // control of these pins to the SSI hardware. // The pins are assigned as follows: // PQ2 - SSI3Tx // PQ3 - SSI3Rx // PQ1 - SSI3Fss // PQ0 - SSI3CLK MAP_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0); // Configure and enable the SSI port for SPI MASTER mode. MAP_SSIConfigSetExpClk(SSI3_BASE, SystemClock, SPIMode, SSI_MODE_MASTER, SPIBitRate, 8); //MAP_SSIAdvModeSet(SSI3_BASE, SSI_ADV_MODE_LEGACY); MAP_SSIAdvModeSet(SSI3_BASE, SSI_ADV_MODE_READ_WRITE); MAP_SSIAdvFrameHoldEnable(SSI3_BASE); MAP_SSIEnable(SSI3_BASE); } // used project 'hello' as a base int main(void) { ... uint32_t ui32ADXL362_ReadDevID[] = {0x0B, 0x00}; uint8_t i = 0; ... // // Run from the PLL at 120 MHz. // g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); // // Configure the device pins. // PinoutSet(false, false); ... // Initialize the SPI. // Settings are compatible with the ADXL362 accelerometer. // CPOL=CPHA = 0, f_SCLK, max = 1 MHz // InitSPI3(g_ui32SysClock, SSI_FRF_MOTO_MODE_0, 500000); ... SysCtlDelay(1); i = 0; while(i < 2) { SSIDataPutNonBlocking(SSI3_BASE, *(ui32ADXL362_ReadDevID+i++)); } SysCtlDelay(1); while(1) { ... } }
I try to read the Device ID by sending byte sequence 0x0B , 0x00 on the SPI bus. Page 20 of AD's datasheet shows the following waveforms for reading from a single address:
However, what I see on the SPI bus is different:
In InitSPI() function, using:
MAP_SSIAdvModeSet(SSI3_BASE, SSI_ADV_MODE_LEGACY);
results in having the ~CS line going to HIGH between successive byte transfers, which is not the desired case;
and using:
MAP_SSIAdvModeSet(SSI3_BASE, SSI_ADV_MODE_READ_WRITE); MAP_SSIAdvFrameHoldEnable(SSI3_BASE);
results in the above pattern EXCEPT for the end of transmission; ~CS line does not go to HIGH level . MISO line remains silent:
My question is:
is there any way to implement SPI correctly? What kind of detail am I missing?
I followed a suggestion here and here to use a GPIO pin as ~CS. Here is what I tried, albeit unsuccessfully:
void InitSPI3(uint32_t SystemClock, uint32_t SPIMode, uint32_t SPIBitRate) { // The SSI3 peripheral must be enabled for use. MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOQ); // Configure the pin muxing for SSI0 functions on port Q0, Q1, Q2, and Q3. MAP_GPIOPinConfigure(GPIO_PQ0_SSI3CLK); // SCLK //MAP_GPIOPinConfigure(GPIO_PQ1_SSI3FSS); // ~CS - commented out that line MAP_GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0); // MOSI MAP_GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1); // MISO // Configure the GPIO settings for the SSI pins. This function also gives // control of these pins to the SSI hardware. // The pins are assigned as follows: // PQ2 - SSI3Tx // PQ3 - SSI3Rx // PQ0 - SSI3CLK // Excluding PQ1 from the following function call-will make that a GPIO line MAP_GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_0); // rest of function is same as above } int main(void) { uint32_t ui32ADXL362_ReadDevID[] = {0x0B, 0x00}; uint8_t i = 0; // // Run from the PLL at 120 MHz. // g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); // // Configure the device pins. // PinoutSet(false, false); ... // // Initialize the SPI. // Settings are compatible with the ADXL362 accelerometer. // CPOL=CPHA = 0, f_SCLK, max = 1 MHz // InitSPI3(g_ui32SysClock, SSI_FRF_MOTO_MODE_0, 500000); // Initalize ~CS as a GPIO pin. GPIOPinTypeGPIOOutput(GPIO_PORTQ_BASE, GPIO_PIN_1); ... GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 0); SysCtlDelay(1); i = 0; while(i < 2) { SSIDataPutNonBlocking(SSI3_BASE, *(ui32ADXL362_ReadDevID+i++)); } SysCtlDelay(1); GPIOPinWrite(GPIO_PORTQ_BASE, GPIO_PIN_1, 1); ... }
..?
i need to make this simple thing work, therefore I really count on your kind assistance.