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

LPC23xx SSP slave Mode

Hi,
I am trying to communicate SSP on 2 LPC23xx boards. One is Master and other is Slave.
Master Board Sending data correctly but Slave Board is not receiving data.

Please help...or send Slave mode code ...initialization of SSP Slave is According to Datasheet.

Thank You

Parents Reply Children
  • Something like this could help you (this code was written for LPC24xx). Note that MISO is _not_ used in this case, as it is not useful to have the master generate clock pules for the slave (in this case):

    init:

       PINSEL0 |= (2<<12) ; // P0.6 SSEL1
            PINSEL0 |= (2<<14) ; // P0.7 SCK1
            //PINSEL0 |= (2<<16) ; // P0.8 MISO1 - not used, peers always transmit as a SPI master, see comments of 'spi_send_data'
            PINSEL0 |= (2<<18) ; // P0.9 MOSI1
    
            // SSP clock prescale register
            SSP1CPSR = 100 ; // at peripheral clock speed of 16[MHz], a value of 140 yields 12.5[KB]/sec
    
            // SSP (SPI) control settings
    
            // 8 bit transfers, SPI frame format, CPOL = 1, CPHA = 1, SCR = 1 (bit rate = PCLK/(SSP1CPSR * (SSP_SCR_BIT + 1) ) )
            SSP1CR0 |= (7<<SSP_DSS_BIT) | (0<<SSP_FRF_BIT) | (1<<SSP_CPOL_BIT) | (1<<SSP_CPHA_BIT) | (0<<SSP_SCR_BIT) ;
    
    #ifdef IO
    
            l_master_or_slave = 0 ; // master
            FIO_PORT_DIR(SPI_MASTER_IO_PORT) |= (1<<SPI_MASTER_IO_PIN) ; // output
            SPI_IO_MASTER_BIT_RESET
    
            // init GPIO 0.SPI_MASTER_DISPLAY_PIN interrupt
        IO0_INT_EN_F |= (1<<SPI_MASTER_DISPLAY_PIN) ;
    
    #elif DISPLAY
    
            l_master_or_slave = 1 ; // slave
            FIO_PORT_DIR(SPI_MASTER_DISPLAY_PORT) |= (1<<SPI_MASTER_DISPLAY_PIN) ; // output
            SPI_DISPLAY_MASTER_BIT_RESET
    
            // init GPIO 0.SPI_MASTER_IO_PIN_INPUT interrupt
        IO0_INT_EN_F |= (1<<SPI_MASTER_IO_PIN_INPUT) ;
    
    
    #endif
    
            // loop back mode disabled, SSP disabled, I/O part master / display part slave, SOD = 0
            SSP1CR1 |= (0<<SSP_LBM_BIT) | (0<<SSP_SSE_BIT) | (l_master_or_slave<<SSP_MS_BIT) | (0<<SSP_SOD_BIT) ;
    
            // enable interrupts - RORIM, RTIM, RXIM
            SSP1IMSC |= (1<<SSP_RORIM_BIT) | (1<<SSP_RTIM_BIT) | (1<<SSP_RXIM_BIT) ;
    
            // install ISR for SPI traffic
            install_irq(SSP1_INT, (void *)spi_handler, IRQ_PRIORITY_7) ;
    
            // enable SSP1 controller
            SSP1CR1 |= (1<<SSP_SSE_BIT) ;
    

    IRQ:

    __irq void spi_handler(void)
    {
            // determine the cause of the interrupt
    
    
    if ( (SSP1MIS>>SSP_RORMIS_BIT) & 1) { // RORMIS bit is 1 if another frame was completely received while the RxFIFO was full
    SSP1ICR = (1<<SSP_RORIC_BIT) ; }
    if ( (SSP1MIS>>SSP_RTMIS_BIT) & 1) { // RTMIS bit is 1 if the Rx FIFO is not empty, has not been read for a "timeout period"
    handle_incoming_spi_data() ;
    // clear interrupt SSP1ICR = (1<<SSP_RTIC_BIT) ; }
    if ( (SSP1MIS>>SSP_RXMIS_BIT) & 1) { // interrupt is cleared by reading the FIFO
    handle_incoming_spi_data() ; }
    // clear interrupt VICVectAddr = 0 ; }

  • "Note that MISO is _not_ used in this case, as it is not useful to have the master generate clock pules for the slave (in this case)"

    What do you mean by that?

    MISO on the slave doesn't have anything to do with need for clock pulses.

    The clock signal is always master -> slave.

    The MOSI signal is (often) connected master -> slave.

    The MISO signal is (often) connected slave -> master.

    Some programs are always sending data in both directions concurrently.

    Some are sending commands on MOSI while the slave sends zero or one bits.
    Then the master switches to sending dummy bits (normally zeros or ones) while picking up incomming bits from the slave.

    So yes - sometimes MISO isn't used. But irrelevant to the need for clock pulses.

  • "Note that MISO is _not_ used in this case, as it is not useful to have the master generate clock pules for the slave (in this case)"

    What do you mean by that?

    MISO on the slave doesn't have anything to do with need for clock pulses.

    The clock signal is always master -> slave.

    The MOSI signal is (often) connected master -> slave.

    The MISO signal is (often) connected slave -> master.

    Some programs are always sending data in both directions concurrently.

    Some are sending commands on MOSI while the slave sends zero or one bits.
    Then the master switches to sending dummy bits (normally zeros or ones) while picking up incomming bits from the slave.

    So yes - sometimes MISO isn't used. But irrelevant to the need for clock pulses.

  • In this case, both parties act like a master - there is no slave on the bus thus the MISO pin is not even configured. In other words, both use MOSI instead, and the synchronization happens using 2 external GPIO pins that generate interrupts to indicated who's the master of the bus (i.e. allowed to send).

  • "Then the master switches to sending dummy bits (normally zeros or ones) while picking up incomming bits from the slave."

    This is exactly what is not needed with the solution above (this is what I meant by "clock pulses").

  • I run a single full duplex channel, but augmented with an attention line - kind of an extra slave-select in reverse direction.

    If unit A wants something, it just sends data - it owns the clock.

    If unit B wants something, it draws one GPIO "attention" signal. This makes unit A start to run the SPI interface - potentially sending "NULL" data.

    So MOSI+MISO+SCLK+SSEL+GPIO-attention (5 signals) needed.

    But both sides can manage transfers - if A sends a question, it must look at the data to see which packet is answer to question, which data is filler NULL-data and which data is commands/requests from other side.

    Same if B sends a question.

  • Hi im facing new problem in LPC2368 ssp1..,,here i am not using SSEL pin and both master and slave boards SSEL pins are grounded.

    I established master-slave communication in interrupt method.
    Here master sends data after than slave sends slave response data...
    My master sending data and slave receiving data but slave response is not coming.

    after than i trying first data sending from slave to master...it also not working..
    slave waiting for Busy bit is cleared.

    any one please help me for slave send(MISO)

    Thanku

  • The master need not use the specific slave select output (a bit depending on what mode you have configured).

    But the slave needs to listen to the slave select, since that signal is an enable signal for the SPI slave device.

    So of course you don't get any slave response if you don't make use of the slave-select signal to enable the slave.

    Have you read through the full chapter for the SSP device in the processor user manual? I think it's time you read though that documentation one more time.

  • Dear sir,
    Thanku for ur response,i write code according to datasheet and again i studied datasheet with ur suggestion but slave response is not coming. slave only receiving

    for master i put DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 7
    for slave DSS data to 8-bit, Frame format SPI, CPOL = 1, CPHA = 1, and SCR is 7

    when slave sending response its waiting for busy bit forever;

    Thank you

  • I would expect that the master and slave use the same clock polarity...?

  • i tried all combinations ...

    here master CPOL = 0, CPHA = 0 for slave CPOL = 1, CPHA = 1 working master- slave data transfer

    and master CPOL = 1, CPHA = 0 for slave CPOL = 0, CPHA = 1 working master- slave data transfer

    other not working and my problem is at least no pluses coming on MISO

    Thank you

  • I'm not sure how we can help you.

    1) You haven't written that you have started to use the slave select signal as it is expected to be used. Having it grounded on the slave is not a correct use. SSEL is not just an enable. It is also the method the slave uses to make sure the bit counter is properly synchronized with the start of a transfer from the master - without SSEL toggling regularly, the slave will not get back in sync again if you lose a clock bit, or get some spurious noise in the clock signal.

    2) You try to run slave and master with different settings - they should use the same for phase and polarity.

    3) You haven't told us anything about how you have initialized the slave, or what the slave code looks like. Or if you have mapped all four signals from GPIO into their hard-coded functionality for SPI communication.

    4) You claim master->slave communiation works, but have given us zero information about what happens on the MISO signal - is it floating? Is the slave driving it constantly low? Is the slave driving it constantly high? Is it sending out data, but the master picks up something different from what the slave did try to send (happens if slave has lost sync and you refuse to use the SSEL signal).

    5) You haven't mentioned anything about what debugging you have tried. What you have seen. What you expected to see. What your beliefs are, based on the differences between what you saw and what you expected to see.

    We shouldn't have to drag information out of you. That is just information given to us, that you are not too interested in putting some effort into getting this problem solved. So the message must then be that we shouldn't be too interested in helping either.

    By the way - where in the manual did you see information that recommended that you should run master and slave with different settings? Or was that just a "let's do some random tests?"

  • Master init:

    void SSP1Handler (void) __irq {
            IENABLE;
            if ( SSP1MIS & SSPMIS_RORMIS ){             // Receive overrun interrupt
                    SSP1ICR = SSPICR_RORIC;                 // clear interrupt
            }
            if ( SSP1MIS & SSPMIS_RTMIS ){              // Receive timeout interrupt
                    f_ssp_rx=1;
                    SSP1ICR = SSPICR_RTIC;                  // clear interrupt
            }
            if ( SSP1MIS & SSPMIS_RXMIS ){              // Rx at least half full
                    f_ssp_rx=1;
            }
    
            if(f_ssp_rx == 1){
                    f_ssp_rx = 0;
                    IOCLR0 |=       0x00000040;
                    SSP1_Receive();
                    IOSET0 |=       0x00000040;
            }
    
            IDISABLE;
            VICVectAddr = 0;                                        // Acknowledge Interrupt
    }
    
    
    /*****************************************************************************
    ** Function name:               SSP1Init
    **
    ** Descriptions:                SSP1 port initialization routine
    **
    ** parameters:                  None
    ** Returned value:              true or false, if the interrupt handler
    **                                              can't be installed correctly, return false.
    **
    *****************************************************************************/
    void SSP1_Init( uint8_t mode ){
            BYTE i, Dummy=Dummy;
            PCONP |= (1 << 10);
            PINSEL0 |= 0x000AA000; // port 0 bits 7, 8, 9, 6 are SSP port SCK1,MISO1,MOSI1,andSSEL1
            IODIR0  |=      0x00000040;
            IOCLR0  |=      0x00000040;
            SSP1CR0 = 0x0747; // Set DSS data to 8-bit, Frame format SPI, CPOL = 1, CPHA = 0, and
            SSP1CPSR = 0x2;         //SSPCPSR clock prescale register, master mode, minimum divisor
            for ( i = 0; i < FIFOSIZE; i++ ){
                    Dummy = SSP1DR;         // clear the RxFIFO
            }
            //SSP1IMSC=0;
            install_irq( SSP1_INT, (void *)SSP1Handler, HIGHEST_PRIORITY );
            if(mode==1){    // The SSP controller acts as a slave on the bus
               SSP1CR1 |= SSPCR1_MS;
               //SSP1CR1 |= 0x06;   // ssp enable, ssp1 selects as Slave
            }
            else  SSP1CR1 |= SSPCR1_SSE;    // ssp enable, ssp1 selects as master
    
            SSP1CR1 |= SSPCR1_SSE;          /* Enable SSP */
    
            SSP1IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM ;// Set SSPINMS registers to enable interrupts
            LVDS_TX_EN_SET();
    }
    
    
    

  • slave init:

    /*****************************************************************************
    ** Function name:               SSP1Init
    **
    ** Descriptions:                SSP1 port initialization routine
    **
    ** parameters:                  None
    ** Returned value:              true or false, if the interrupt handler
    **                                              can't be installed correctly, return false.
    **
    *****************************************************************************/
    void SSP1_Init( uint8_t mode ){
            uint32_t i, Dummy=Dummy;
            SSP1CR1 = 0;
            PCONP |= (1 << 10);
            //PINSEL0 &= ~(0x000A8000);
            PINSEL0 |= 0x000AA000;// port 0 bits 7, 8, 9, 6 are SSP port SCK1, MISO1, MOSI1,ssel1
            SSP1CR0 = 0x0787;// Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 1, and
            SSP1CPSR = 0x2;
            for ( i = 0; i < FIFOSIZE; i++ ){
                    Dummy = SSP1DR;         // clear the RxFIFO
            }
            SSP1IMSC=0;
            install_irq( SSP1_INT, (void *)SSP1Handler, HIGHEST_PRIORITY );
            if(mode==1){
                    SSP1CR1 |= SSPCR1_MS;
            }
            else  SSP1CR1 &=~( SSPCR1_MS);    // ssp enable, ssp1 selects as master
            SSP1CR1 |= SSPCR1_SSE;
            SSP1IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM ;// Set SSPINMS registers to enable interrupts
            LVDS_TX_EN_SET();
    }