# shift by 1 bit error in SPI

I am trying to implement the SPI communication on TM4C123. I have 1 board and try to send data from SSI1(master) to SSI0(slave), but I observe that the received value is always shifted to the left by 1 bit!! for example, I send 0x01 on the master and receive 0x02 on the slave, and so on. the SPI settings I used are:

• clocking of 8 MHz
• CPOL and CPH are zeros on both SPI modules
• 8 bit for the data field

Can anyone suggest a solution ??

EDIT: Here is the code

void SSI0_Init(void) ;

void SSI1_Init(void) ;

int main(){
SSI1_Init();
SSI0_Init();
InitConsole() ;

while(1){
// set ss low
GPIO_PORTD_DATA_R &= ~0x40 ;            // ss low
while ((SSI1_SR_R & 0x02) == 0 ){}      //wait till fifo not full
SSI1_DR_R = 0x01 ;                      // send char a
while (SSI1_SR_R & 0x10){}              // wait for TX complete
GPIO_PORTD_DATA_R |= 0x40 ;             // ss high

uint8_t data ;
while ((SSI0_SR_R & 0x04) == 0){}       // wait for not empty fifo flag
data = SSI0_DR_R ;                      // data reading

// set ss low
GPIO_PORTD_DATA_R &= ~0x40 ;            // ss low
while ((SSI1_SR_R & 0x02) == 0 ){}      //wait till fifo not full
SSI1_DR_R = 0x02 ;                      // send char a
while (SSI1_SR_R & 0x10){}              // wait for TX complete
GPIO_PORTD_DATA_R |= 0x40 ;             // ss high

while ((SSI0_SR_R & 0x04) == 0){}       // wait for not empty fifo flag
data = SSI0_DR_R ;                      // data reading

// set ss low
GPIO_PORTD_DATA_R &= ~0x40 ;            // ss low
while ((SSI1_SR_R & 0x02) == 0 ){}      //wait till fifo not full
SSI1_DR_R = 0x04 ;                      // send char a
while (SSI1_SR_R & 0x10){}              // wait for TX complete
GPIO_PORTD_DATA_R |= 0x40 ;             // ss high

while ((SSI0_SR_R & 0x04) == 0){}       // wait for not empty fifo flag
data = SSI0_DR_R ;                      // data reading

int dummy = data ;

}
}

void SSI0_Init(void){

// settings for TX, RX, SS, CLK in GPIO PORTA
SYSCTL_RCGCGPIO_R |= 0x01 ;     // clock on PORTA
SYSCTL_RCGCSSI_R |= 0x01 ;      // clock on SSI0 module
GPIO_PORTA_AFSEL_R |= 0x1c ;    // alt. function for PORTA 2, 3, 4, 5
GPIO_PORTA_PCTL_R &= ~0x000fff00 ;
GPIO_PORTA_PCTL_R |= 0x00022200;
GPIO_PORTA_DEN_R |= 0x1c ;      // digital enable

// settings of SSI0 module
SSI0_CR1_R = 0 ;                // disable during configuration
SSI0_CC_R = 0 ;                 // system clock
//SSI0_CPSR_R = 2 ;               // prescaler div by 2
SSI0_CR0_R = 0x07 ;             // 8MHZ, SPI mode, 8 bit frame, 2nd edge capture
SSI0_CR1_R |= 0x04 ;            // set as a slave
SSI0_CR1_R |= 0x02 ;            // enable
}

void SSI1_Init(void){

// settings for TX, RX, SS, CLK in GPIO PORTA

SYSCTL_RCGCGPIO_R |= 0x08 ;     // clock on PORTD
SYSCTL_RCGCSSI_R |= 0x02 ;      // clock on SSI1 module
GPIO_PORTD_AFSEL_R |= 0x09 ;    // alt. function for PORTD 0,3
GPIO_PORTD_PCTL_R &= ~0x0f00f ;
GPIO_PORTD_PCTL_R |= 0x02002;
GPIO_PORTD_DEN_R |= 0x09 ;      // digital enable

// settings for PD6 as SS signal
GPIO_PORTD_DIR_R |= 0x40 ;      // PD6 output
GPIO_PORTD_DEN_R |= 0x40 ;      // digital enable PD6
GPIO_PORTD_DATA_R |= 0x40 ;     // keep SS idle high

// settings of SSI1 module
SSI1_CR1_R = 0 ;                // disable during configuration
SSI1_CC_R = 0 ;                 // system clock
SSI1_CPSR_R = 2 ;               // prescaler div by 2
SSI1_CR0_R |= 0x07 ;            // 8MHZ, SPI mode, 8 bit frame
SSI1_CR1_R = 0x00 ;             // set as a master
SSI1_CR1_R |= 0x02 ;            // enable
}

• What if you send 0? What if you send 6? What about other numbers? Collect more info. – Andy aka Jan 14 '18 at 18:00
• Are you sure about the CPOL and CPH setting of the slave device? – Tom Carpenter Jan 14 '18 at 18:02
• As @TomCarpenter says, do check the SPI settings carefully. In one mode, the first bit is presented on MOSI when CS_N is asserted. In the other, the first bit appears on MOSI after the first SPI SCK after CS_N is asserted. Amongst other settings :-) Double-check the values against the datasheet for your specific part, just to be absolutely certain. – TonyM Jan 14 '18 at 18:39
• @BrianDrummond, to be honest, I'd call 20 MHz or 50 MHz fairly fast for SPI but not 8 MHz, particularly in loop-back to the same IC... Come to that: OP, (a) how is your loop-back wiring being done and (b) what's the crystal oscillator frequency of the chip? – TonyM Jan 14 '18 at 19:05
• the CPOL and other terminology has grossly messed up spi interfaces, ignore them what is relevant is what edge of the clock each side changes or samples on. The so called standard only covers half the possible combinations, and rarely do you see devices conform to these (spi, i2c, etc) specifications, so what matters is what edge are you samping on and changing on so that the other side can sample mid bit cell. sometimes the sending and sampling on the master ARE NOT THE SAME EDGE. smells so far like you do have one of these edges wrong. – old_timer Jan 14 '18 at 20:23

"Shifted by one bit" is the common symptom of SPI when the wrong clock setup is used. Either the master and slave disagree on what clock edge data is transferred, or you are starting at the wrong polarity from idle.

The first and obvious thing to do is to transfer a known test byte and look at the resulting chip select, clock, and data lines with a scope. Now compare that to what the slave device says it needs, and you will probably find a discrepancy.

Unfortunately, all four possible combinations of SPI clock idle polarity and active edge polarity are out there. You have to carefully read what your slave needs, then carefully read the datasheet of the master to see how to achieve that.

You haven't provided enough information to be certain, but I suspect you have misread your part's datasheet. From your description, the slave is listening for data "one bit delayed" from the master (not sure how to word that). Most probably, your code is timing bits so that the slave starts listening when the master sends the second bit (assuming the order is most significant bit first).

What to do next: