This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

C8051F120 SPI communication

Hi,
I am trying SPI communication between two C8051F120.
Master and slave in 3 wire mode config.
first time master sends data correctly but second time it get shifted by 1 bit.
Please help me for same.

  • Are you in control of the protocol, having written the source for both sides?

    You should use the slave select to synchronize the two sides. If you don't, then every single little noise pulse on the clock line will make the master and slave run unsynchronized.

    Your problem right now is probably your configuration of default state for the clock signal between transfers (note that for SPI you have four possible configurations for the clock. Which phase to clock data on, and what level to use when paused).

    But you have to think about both configuring the clock line correctly on both sides, and using the slave select to synchronize the slave.

  • At Master side i initialized spi0 as below:

    #define SYSCLK 3062500 // Internal oscillator frequency in Hz

    #define SPI_CLOCK 7000 // SPI clock

    //-----------------------------------------------------------------------------
    // SPI0_Init
    //-----------------------------------------------------------------------------
    //
    // Return Value : None
    // Parameters : None
    //
    // Configures SPI0 to use 3-wire Single Master mode. The SPI timing is
    // configured for Mode 0,0 (data centered on first edge of clock phase and
    // SCK line low in idle state).
    //
    //-----------------------------------------------------------------------------
    void SPI0_Init()
    { unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE

    SFRPAGE = SPI0_PAGE; // Switch to the necessary SFRPAGE

    SPIEN=0;

    SPI0CFG = 0x40; // Enable the SPI as a Master // CKPHA = '0', CKPOL = '0' SPI0CN = 0x01; // 3-wire Single Master, SPI enabled

    // SPI clock frequency equation from the datasheet

    SPI0CKR = (SYSCLK/(2*SPI_CLOCK))-1;

    SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
    }

    //******************************************
    At Slave side i initialized spi0 as below:

    void SPI0_Init(void)
    { unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE

    SFRPAGE = SPI0_PAGE; // Switch to the necessary SFRPAGE

    SPIEN=0;

    SPI0CFG = 0x00; // Operate in Slave mode // CKPHA = '0', CKPOL = '0' SPI0CN = 0x01; // 3-wire Slave mode, SPI enabled

    EIE1 |= 0x01; // Enable SPI interrupts

    SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
    }

    I have synchronized clock on both sides.
    i am not using SLave select(NSS) coz only one slave is
    present(3- wire mode).

    Actually first byte i am getting correctly on slave side but next byte is getting shifted.

  • You don't use slave select?

    If the two processors boots at different times, then the master can produce a spurious clock toggle that the slave sees.

    If the master starts to transmit before the slave is initialized, they will get out of sync.

    If there is a noise glitch on the SPI clock signal, they will get out of sync.

    Please explain exactly how you plan to get your slave to run synchronously with the master if (when) they get out of sync. The slave select signal is a very important signal, and expected to be used even if you only have one slave.

    Without a slave select, you must implement self-clocking data, which means that you can't use all 8 bits for a normal transfer. You may have to teach the slave that any combination of 8 ones followed by 8 zero (in any shifted combination) represents the start of a transfer (to teach the slave the current shifted state) and then you have to shift your data correspondingly. And you would need to send an extra dummy byte at the end of the transfer, to make sure that you shift out any remaining data bits from the slave receive register.

    Sounds simple? Maybe time to start thinking again about that slave select signal...