4

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
}
SH90
  • 41
  • 1
  • 3
  • 1
    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
  • 4
    Are you sure about the CPOL and CPH setting of the slave device? – Tom Carpenter Jan 14 '18 at 18:02
  • 1
    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
  • 8 MHz is also fairly fast for SPI. You might see if the same problem occurs at 1 MHz as a test. –  Jan 14 '18 at 18:57
  • 1
    @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
  • 1
    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

2 Answers2

5

"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.

Olin Lathrop
  • 310,974
  • 36
  • 428
  • 915
0

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:

Post your code.

Run more tests. See what happens if you send 0b10000000 - do you get 0?

Lowering the bus speed is so easy to do it's probably worth a try, but I sincerely doubt it will do anything.

dpdt
  • 1,707
  • 16
  • 26
  • thanks for replay. when i send 0 the slave receive 0 but for all other values the shifting always happens. but i can't replay with my code because it is longer than the allowed comment – SH90 Jan 19 '18 at 21:21
  • @SareaHariri 0 shifted is 0. So I suspect that it is also shifted. As for posting your code, don't put it in a comment. Instead, edit your own post to put it in. – dpdt Jan 22 '18 at 00:08
  • i have added the code to the original post. Regards, Sarea – SH90 Jan 24 '18 at 11:36