Menu

SPI Slave mode not working

2025-07-18
2025-07-21
  • Jemshid Kattumunda

    Hello everyone,
    I'm seeking help to print simple byte data from Arduino Uno to PIC16F877A via SPI interface. Here is the code mentioned below. I cannot get the output on serial monitor. kindly mention where I'm missing. If I'm hook-up Arduino to Arduino, it is working. Also If the PIC selected as master, and the Arduino is slave, still working. The only issue if I selected PIC as Slave mode and Arduino as master. I searched the help topics and the community but mostly the examples related to master mode and not slave mode.

    #chip 16F877A, 4                 
    
    #define USART_BAUD_RATE 9600     
    #define USART_TX_BLOCKING        
    
    dim dat as byte                  
    
    dir PORTB.7 in  'SS              
    dir PORTC.5 out 'SDO/MOSI/COPI   
    dir PORTC.4 in  'SDI/MISO/CIPO   
    dir PORTC.3 in  'SCK             
    
    SPIMode Slave                    
    
    do                               
    SPITransfer 0,dat                
    HserPrint dat                    
    HSerPrintCRLF                    
    wait 1 s                         
    loop                             
    
     
  • Anobium

    Anobium - 2025-07-19

    Hello,

    Your current code polls SPI transfers risks missed data. So, what is happening would be expectd.

    You need an interrupt handler.

    Why an Interrupt Handler Is Needed

    In SPI slave mode, the PIC16F877A relies on the Arduino to drive the Slave Select (SS) and clock (SCK) pins. Polling (SPITransfer) can miss data if unsynchronised, as the PIC’s SPI slave mode triggers an interrupt when the buffer (SSPBUF) is full. An interrupt handler ensures immediate data processing, boosting reliability.

    Modified PIC16F877A Code

    This revised code ( untested) uses an interrupt handler for SPI slave mode

    ' Start SPI slave mode
    SPIMode Slave
    
    Dim spidataready, spidat as Byte
    spidataready = false
    
    ' Enable interrupts
    On Interrupt SSP1Ready Call SPI_ISR
    
    ' Main loop
    do
        wait 10 ms        ' Space for other tasks
        if spidataready  then 
            HserPrint spidat     ' Print to serial
            HSerPrintCRLF
        end if
    loop
    
    ' Interrupt routine
    sub SPI_ISR
            spidat = SSPBUF      ' Read SPI buffer
            spidataready = true        
    end sub
    
     
  • Jemshid Kattumunda

    Hi Venn,
    Thank you for the quick reply. I tried to figure out but I don't have luck. even the interrupt also not working in my case.

     
  • Anobium

    Anobium - 2025-07-19

    I would need to see your complete code.

    Question. ISR being called? Add Hsersend "." to the ISR. Is the "." shown?

    Also, change.

    if spidataready then
    HserPrint spidat ' Print to serial
    HSerPrintCRLF
    spidataready = false
    end if

     
  • Jemshid Kattumunda

    Hi Venn,
    I made the changes as you suggested. The ISR not being called during program execution. I added HserSend "." into ISR sub, not responding at serial monitor. I'm using Simulide software for simulation. I attached pin connection with this post, please inspect if I made any wrong. The complete code below. Thanks in advance!

    #chip 16F877A, 4
    
    #define USART_BAUD_RATE 9600
    #define USART_TX_BLOCKING
    
    dir PORTB.7 in  'SS
    dir PORTC.5 out 'SDO
    dir PORTC.4 in  'SDI
    dir PORTC.3 in  'SCK
    
    SPIMode Slave
    dim spidat, spidataready as byte
    spidataready = false
    
    'Enable interrupts
    On Interrupt SSP1Ready Call SPI_ISR
    
    do
    wait 10 ms
      if spidataready then
        HserPrint spidat
        HSerPrintCRLF
        spidataready = false
      end if
    loop
    
    'Interrupt routine
    sub SPI_ISR
    spidat = SSPBUF 'Read SPI buffer
    Hsersend "." 'Test
    spidataready = true
    end sub
    
     
  • Anobium

    Anobium - 2025-07-21

    I cannot test, so you will have to. :-)

    This is likely to be something very simple.

    So, this code... change the SPIMode.. a parameter 0. Test, then change to 1. Test do same for 3 and 4. See the Help why this may help.

    I also changed the ISR but as you are not seeing the ISR active this is not the root cause issue.

    Evan

    #chip 16F877A, 4
    
    #define USART_BAUD_RATE 9600
    #define USART_TX_BLOCKING
    
    dir PORTB.7 in  'SS
    dir PORTC.5 out 'SDO
    dir PORTC.4 in  'SDI
    dir PORTC.3 in  'SCK
    
    SPIMode Slave // [,0|1|2|3]
    dim spidat, spidataready as byte
    spidataready = false
    
    'Enable interrupts
    On Interrupt SSP1Ready Call SPI_ISR
    
    do
        wait 10 ms
        if spidataready then
            HserPrint spidat
            HSerPrintCRLF
            spidataready = false
        end if
    loop
    
    'Interrupt routine
    sub SPI_ISR
        // Read SPI buffer
        SPITransfer spidat, spidat 
        Hsersend "." 'Test
        spidataready = true
    end sub
    
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.