Tool/software:
I'm trying to implement SSI0 (TM4C123 as a master) to communicate between the MCU and two Si834x isolated smart switches (as slaves) on CCS.
Before implementing the actual SPI protocol between them, I tried to observe the SSI0 timing diagram to verify that the data bytes are transmitting correctly. Basically, I'm sending 10 bytes and using logic analyzer (logic pro 8) to verify the data being transmitted.
However, it seems like there's an error every three bytes (1st, 4th, 7th, 10th byte). What is causing the issue and how should I fix it?
Also, I should mention that if I change the system clock frequency or bitrate, the error location changes but it still occurs once every three bytes (EX: errors happen at 2nd, 5th, 8th byte or 3rd, 6th, 9th byte...etc.)
Here is the code
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "Si834x.h"
#define NUM_SSI_DATA 10 //10 data bytes
void InitSPI(void) {
// Enable peripherals for SSI0 and GPIO Port A
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); //Enable SSI0 peripherals
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //Enable GPIO Port A for SSI0
// Configure SSI0 pins
// PA2 - SSI0CLK
// PA3 - SSI0Fss (Manual control)
// PA4 - SSI0Rx (MISO)
// PA5 - SSI0Tx (MOSI)
GPIOPinConfigure(GPIO_PA2_SSI0CLK);
GPIOPinConfigure(GPIO_PA4_SSI0RX);
GPIOPinConfigure(GPIO_PA5_SSI0TX);
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5);
// Set drive strength and pin type for SSI pins (8mA drive strength)
GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_5, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD);
// Configure and enable the SSI port for SPI master mode
SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 1000000, 8); //SSI_FRF_MOTO_MODE_3 -> Data captured on the second clock edge & Steady state High for SSI0Clk, 1 Mbps, 8 bits
SSIEnable(SSI0_BASE); //Enable the SSI0 module
// Configure PA3 for manual CS control
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3);
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); // Set CS High initially
SysCtlDelay(500);
}
void SPIWrite(uint8_t data) {
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, 0); // Pull CS Low to start communication
SSIDataPut(SSI0_BASE, data); // Transmit data
while (SSIBusy(SSI0_BASE)) {} // Wait until the transmission is complete
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3); // Pull CS High to end communication
// SysCtlDelay(10);
}
int main(void) {
uint32_t pui32DataTx[NUM_SSI_DATA];
// uint32_t pui32DataRx[NUM_SSI_DATA];
uint32_t ui32Index;
// SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // System clock: 80MHz
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // System clock: 16MHz
//Configure PE2 for OE and set it High
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)) {}
GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_2);
GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_2, GPIO_PIN_2);
InitSPI();
// Clear any residual data from the SSI port
//while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx[0])) {}
pui32DataTx[0] = 0x01;
pui32DataTx[1] = 0x12;
pui32DataTx[2] = 0x23;
pui32DataTx[3] = 0x34;
pui32DataTx[4] = 0x45;
pui32DataTx[5] = 0x56;
pui32DataTx[6] = 0x78;
pui32DataTx[7] = 0x89;
pui32DataTx[8] = 0x9A;
pui32DataTx[9] = 0xAB;
for (ui32Index = 0; ui32Index < NUM_SSI_DATA; ui32Index++) {
SPIWrite(pui32DataTx[ui32Index]);
}
return 0;
}
Here is the timing diagram (Channel 4 is CS)