MASTER and SLAVE PICs using SPI in Oshonsoft

Thread Starter

camerart

Joined Feb 25, 2013
3,837
I had written this mikroC PRO PIC code sometime ago. If you understand c then you can refer it else I will port my code as an example to OshonSoft PIC18 Basic and post it here.

Actually my code is multi-master but if you take it one way then it is master-slave.

View attachment 168501
Hi J2,
I don't understand Arduino, and this is what I got when I tried to open the RAR.
My set up is wired as yours.
Thanks, C.
 

Attachments

jjw

Joined Dec 24, 2013
823
Hi J,
Thanks, I've been reading this as I go along, but I think this is an Oshonsoft programming question.
C.
Yes it is, but it is needed, if you want to setup the PIC as slave.
Oshonsoft supports only master.
 
Last edited:

jayanthd

Joined Jul 4, 2015
945
Master can send a known byte like 0xAF to reuest data from slave and slave after receiving 0xAF should send the required data to master and master should read it and display it.
 

ericgibbs

Joined Jan 29, 2010
21,453
hi jjw,
There is a way that can force the hardware SPI in Oshonsoft.
These a clips are clips from a program I wrote for the TS ie@ C
I have it running at 20MHz with SPI and a TFT
E


Call spi_init() 'hw spi
WaitMs 100
Call lcd_reset() ''lcd_rst before LCD Init.
WaitMs 50
Call tft_init() 'initialise lcd
WaitMs 50

Proc:' example
ss = 0
spi8 = SSPBUF
SSPBUF = color.HB
While Not SSPSTAT.BF
Wend
spi8 = SSPBUF
SSPBUF = color.LB
While Not SSPSTAT.BF
Wend
ss = 1
endproc


Proc spi_init()
TRISC.5 = 0 'sdo to 9225
TRISC.2 = 0 'TRISC.2 = 0 'ss
TRISC.4 = 1 'sdi not used on TFT
TRISC.3 = 0 'clk
ss = 1
SSPSTAT = 0
'SSPSTAT.CKE = 1 'clock edge un remark for trailing edge
'SSPCON1 = 0x10 'full whack... at 8mhz 2mhz operation no SS control
SSPCON1 = %00100000
'00 = fosc/4.. 01 = fosc /16
'10 = fosc/64.. 11 contolled by timer2.
SSPCON1.CKP = 1 'clock polarity unremark for high polarity
End Proc

 

Thread Starter

camerart

Joined Feb 25, 2013
3,837
hi jjw,
There is a way that can force the hardware SPI in Oshonsoft.
These a clips are clips from a program I wrote for the TS ie@ C
I have it running at 20MHz with SPI and a TFT
E


Call spi_init() 'hw spi
WaitMs 100
Call lcd_reset() ''lcd_rst before LCD Init.
WaitMs 50
Call tft_init() 'initialise lcd
WaitMs 50

Proc:' example
ss = 0
spi8 = SSPBUF
SSPBUF = color.HB
While Not SSPSTAT.BF
Wend
spi8 = SSPBUF
SSPBUF = color.LB
While Not SSPSTAT.BF
Wend
ss = 1
endproc


Proc spi_init()
TRISC.5 = 0 'sdo to 9225
TRISC.2 = 0 'TRISC.2 = 0 'ss
TRISC.4 = 1 'sdi not used on TFT
TRISC.3 = 0 'clk
ss = 1
SSPSTAT = 0
'SSPSTAT.CKE = 1 'clock edge un remark for trailing edge
'SSPCON1 = 0x10 'full whack... at 8mhz 2mhz operation no SS control
SSPCON1 = %00100000
'00 = fosc/4.. 01 = fosc /16
'10 = fosc/64.. 11 contolled by timer2.
SSPCON1.CKP = 1 'clock polarity unremark for high polarity
End Proc

Hi E,
I can't read your code so well but it looks like a PIC talking to an LCD screen. If so then, the MASTER PIC is already talking to modules via SPI, but I have no experience with a MASTER talking to a SLAVE PIC, as above.
C.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,837
Master can send a known byte like 0xAF to reuest data from slave and slave after receiving 0xAF should send the required data to master and master should read it and display it.
Hi J2,
This is what I usually do, but in this case the SSPBUF (On the SLAVE) address is 0xfc9, which is not accepted because it's not a BYTE.
C.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,837
Yes it is, but it is needed, if you want to setup the PIC as slave.
Oshonsoft supports only master.
Hi J,
I realise the D/S is needed and I have set up the SLAVE as best as I can, but perhaps not perfectly.
At the moment I'm pretty sure that the SLAVE puts SSPBUF into 0xfc9, as the D/S.

I have added (Just for testing) an HSEROUT of SSPBUF, which I can see on a terminal, and I can change the numbers using the two test buttons of QEI.

Now I need the MASTER to READ the SSPBUF from 0xfc9 of the SLAVE.

NOTE: I'm getting differing answers, this is why I'm still mentioning addresses.
C.
 
Last edited:

jjw

Joined Dec 24, 2013
823
Hi J,
I realise the D/S is needed and I have set up the SLAVE as best as I can, but perhaps not perfectly.
At the moment I'm pretty sure that the SLAVE puts SSPBUF into 0xfc9, as the D/S.

I have added (Just for testing) an HSEROUT of SSPBUF, which I can see on a terminal, and I can change the numbers using the two test buttons of QEI.ress

Now I need the MASTER to READ the SSPBUF from 0xfc9 of the SLAVE.
C.
You don't need to know the address of the SSPBUF.
SSPBUF is a register like PORTA, TRISC, LATA etc.
In the slave you can write to it.
for example:
Dim somedata as Byte
SSPBUF = somedata

You can read it in the master:
Dim data as Byte
SPIreceive data

Look Erics code to setup HW SPI.
It sets the master.
You need to setup the HW slave in PIC184431:
SSPCON =??
SSPSTAT = ??
TRISC = ??
The values are in the d/s and in the link msg#1
 
Last edited:

jayanthd

Joined Jul 4, 2015
945
Hi C,

I was not able to make BASIC code with OshonSoft PIC18 Basic Compiler as I am not familiar with it. However I made mikroBasic PRO PIC code which is working.

Master sends 0xFF to request data and slave upon receiving 0xFF send the PORTB data to master and master receives it and displays it on its PORTB (LATB).

If you can build the circuit shown in attached video then you can test the working of my code. You can then port my basic code to your Basic Compiler.

I have use a 1 sec delay in master to show how data changes in SPI debugger of Proteus.

I have used 4 MHz XT OSC.


mikroBasic PRO PIC Codes

SPI Master

Code:
program Master

' Declarations section
dim Chip_Select as sbit at RC0_bit
dim Chip_Select_Direction as sbit at TRISC0_bit

dim flagRegister as byte
dim data_ as byte
dim spiDataReceived as sbit at flagRegister.0

sub procedure interrupt
    if(SSPIF_bit) then
       SSPIF_bit = 0
   
       if(BF_bit) then
          data_ = SSPBUF
          spiDataReceived = 1
       end if
    end if

    SSPOV_bit = 0
end sub

main:
'   Main program

    TRISA = 0xC0
    TRISB = 0x00

    PEIE_bit = 1
    GIE_bit = 1

    spiDataReceived = 0

    while(1)
         if(spiDataReceived = 0) then
            TRISC = 0x10
            Chip_Select_Direction = 0
            Chip_Select = 1
            SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            SSPIE_bit = 0
            Chip_Select = 0
            SPI1_Write(0xFF)
            Chip_Select = 1
            TRISC = 0x30
            Chip_Select_Direction = 1
            SPI1_Init_Advanced(_SPI_SLAVE_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            SSPIE_bit = 1
         else
            LATB = data_
            spiDataReceived = 0
         end if
     
         Delay_ms(1000)
    wend
end.
SPI Slave

Code:
program Slave

' Declarations section
dim Chip_Select as sbit at RC0_bit
dim Chip_Select_Direction as sbit at TRISC0_bit

dim flagRegister as byte
dim data_ as byte
dim spiDataReceived as sbit at flagRegister.0

sub procedure interrupt
    if(SSPIF_bit) then
       SSPIF_bit = 0
   
       if(BF_bit) then
          data_ = SSPBUF
     
          if(data_ = 0xFF) then
              spiDataReceived = 1
          end if
     
          data_ = 0
       end if
    end if

    SSPOV_bit = 0
end sub

main:
'   Main program

    TRISA = 0xC0
    TRISB = 0x00

    TRISC = 0x30
    Chip_Select_Direction = 1
    SPI1_Init_Advanced(_SPI_SLAVE_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
    spiDataReceived = 0
    SSPIE_bit = 1

    PEIE_bit = 1
    GIE_bit = 1

    while(1)
         if(spiDataReceived = 1) then
            SSPIE_bit = 0
            TRISC = 0x10
            Chip_Select_Direction = 0
            Chip_Select = 1
            SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            Chip_Select = 0
            SPI1_Write(PORTB)
            Chip_Select = 1
            Delay_ms(100)
            TRISC = 0x30
            Chip_Select_Direction = 1
            SPI1_Init_Advanced(_SPI_SLAVE_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            SSPIE_bit = 1
            spiDataReceived = 0
         end if
    wend
end.


SS1.png
 

Attachments

Last edited:

jayanthd

Joined Jul 4, 2015
945
Hi cameart,

If you can use mikroBasic PRO PIC Compiler then I can send you a key for it for free. I have an extra license for it. If yes then PM me.

The project (mikroBasic PRO PIC) that I posted compiles fine in demo Compiler.


jjw mentioned that PIC18 Basic Compiler doesn't have an hardware SPI library that works with/without interrupts. You will have to write your own hardware SPI library for it and use it with SPI interrupts to get the code working. Bitbanged SPI code will not work with SPI interrupts and you will not be able to get it working with bitbanged SPI library.

Alternate option is to use mikroBasic PRO PIC Compiler.
 
Last edited:

jayanthd

Joined Jul 4, 2015
945
Final project files attached.

PIC18F4431 SPI MASTER-SLAVE Code. XT 4 MHz.

mikroBasic PRO PIC Codes. See attached video. I have used PIC18F4431 for both master and slave. If you use mikroBasic PRO PIC then you can easily change it.

Master Code

Code:
program Master

' Declarations section
dim Chip_Select as sbit at RC0_bit
dim Chip_Select_Direction as sbit at TRISC0_bit

dim flagRegister as byte
dim data_ as byte
dim spiDataReceived as sbit at flagRegister.0

sub procedure interrupt
    if(SSPIF_bit) then
       SSPIF_bit = 0
      
       if(BF_bit) then
          data_ = SSPBUF
          spiDataReceived = 1
       end if
    end if

    SSPOV_bit = 0
end sub

main:
'   Main program

    TRISA = 0xC0
    TRISB = 0x00

    PEIE_bit = 1
    GIE_bit = 1

    spiDataReceived = 0
  
    while(1)
         if(spiDataReceived = 0) then
            TRISC = 0x10
            Chip_Select_Direction = 0
            Chip_Select = 1
            SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            SSPIE_bit = 0
            Chip_Select = 0
            SPI1_Write(0xFF)
            Chip_Select = 1
            TRISC = 0x30
            Chip_Select_Direction = 1
            SPI1_Init_Advanced(_SPI_SLAVE_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            SSPIE_bit = 1
            Delay_ms(20)
         else
            LATB = data_
            spiDataReceived = 0
         end if
    wend
end.
SLAVE code

Code:
program Slave

' Declarations section
dim Chip_Select as sbit at RC0_bit
dim Chip_Select_Direction as sbit at TRISC0_bit

dim flagRegister as byte
dim data_ as byte
dim spiDataReceived as sbit at flagRegister.0

sub procedure interrupt
    if(SSPIF_bit) then
       SSPIF_bit = 0
      
       if(BF_bit) then
          data_ = SSPBUF
        
          if(data_ = 0xFF) then
              spiDataReceived = 1
          end if
        
          data_ = 0
       end if
    end if
  
    SSPOV_bit = 0
end sub

main:
'   Main program

    TRISA = 0xC0
    TRISB = 0x00
  
    TRISC = 0x30
    Chip_Select_Direction = 1
    SPI1_Init_Advanced(_SPI_SLAVE_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
    spiDataReceived = 0
    SSPIE_bit = 1
  
    PEIE_bit = 1
    GIE_bit = 1
  
    while(1)
         if(spiDataReceived = 1) then
            SSPIE_bit = 0
            TRISC = 0x10
            Chip_Select_Direction = 0
            Chip_Select = 1
            SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            Chip_Select = 0
            SPI1_Write(PORTB)
            Chip_Select = 1
            TRISC = 0x30
            Chip_Select_Direction = 1
            SPI1_Init_Advanced(_SPI_SLAVE_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH)
            SSPIE_bit = 1
            spiDataReceived = 0
         end if
    wend
end.

SS2.png
 

Attachments

Last edited:

jayanthd

Joined Jul 4, 2015
945
Here is new project [attached]. It uses PIC18F4620 (Master) and PIC18F4431 (Slave) both @ XT 4 MHz.
Simulation video included in the attachment.
Tested and fully working in Proteus.
I have added a button to master for requesting data from slave. When button is pressed and released the master sends 0xFF to slave requesting data and slave upon receiving 0xFF responds by sending its PORTB data to master and master displays it on its PORTB.

If you want some other trigger for requesting data from slave then just change the button press and release detect code to some other triggering flag.

PDS_2019-01-24_13-48-13.png
 

Attachments

Thread Starter

camerart

Joined Feb 25, 2013
3,837
Here is new project [attached]. It uses PIC18F4620 (Master) and PIC18F4431 (Slave) both @ XT 4 MHz.
Simulation video included in the attachment.
Tested and fully working in Proteus.
I have added a button to master for requesting data from slave. When button is pressed and released the master sends 0xFF to slave requesting data and slave upon receiving 0xFF responds by sending its PORTB data to master and master displays it on its PORTB.

If you want some other trigger for requesting data from slave then just change the button press and release detect code to some other triggering flag.

View attachment 168559
Hi J2,
There is a lot of work there and it is very much appreciated.
As I can read your CODE and convert it to Oshonsoft I won't need your extra Mikro licence, but thanks for the offer. I have been using Oshonsoft for a long time, and for me, it is pretty good but not perfect. It has a simulator, which is valuable to me or I wouldn't be able to program at all. Oshonsoft has some problems, that need special attention some times. It has it's own SPI protocol, which I am already using. My two PICs are wired as yours.

As J1 and E are familiar with Oshonsoft and it's SPI etc, if you don't mind I'll try their solutions first, then if we don't get anywhere I'll concentrate on yours.

Once I get both PIC working I'll post the programs for you to compare.
Thanks,
C.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,837
You don't need to know the address of the SSPBUF.
SSPBUF is a register like PORTA, TRISC, LATA etc.
In the slave you can write to it.
for example:
Dim somedata as Byte
SSPBUF = somedata

You can read it in the master:
Dim data as Byte
SPIreceive data

Look Erics code to setup HW SPI.
It sets the master.
You need to setup the HW slave in PIC184431:
SSPCON =??
SSPSTAT = ??
TRISC = ??
The values are in the d/s and in the link msg#1
Hi J,
As already mentioned, I think I have the SLAVE set-up as the D/S and E's , msg, and it is outputting SSPCON by using a TEST HSEROUT, and I can see it in a RECEIVING Terminal.

I am trying to SEND a WORD (QEI) that is held in CAP2BUFL and CAP2BUFH
At the moment I have SSPBUF=CAP2BUFL, which is what I see in the Terminal. e,g, as I change the numbers they are RECEIVED.

--------------SLAVE--------------------------
From your message here, is this correct? [Just for the LOW BYTE TEST]
DIM AZIL as BYTE
DIM AZIH as BYTE

AZIL = CAP2BUFL
SSPBUF = AZIL

----------------MASTER------------------------------
Dim AZIL as Byte
SPIreceive AZIL

C.
 
Last edited:

jayanthd

Joined Jul 4, 2015
945
Hi J,
As already mentioned, I think I have the SLAVE set-up as the D/S and E's , msg, and it is outputting SSPCON by using a TEST HSEROUT, and I can see it in a RECEIVING Terminal.

I am trying to SEND a WORD (QEI) that is held in CAP2BUFL and CAP2BUFH
At the moment I have SSPBUF=CAP2BUFL, which is what I see in the Terminal. e,g, as I change the numbers they are RECEIVED.

--------------SLAVE--------------------------
From your message here, is this correct? [Just for the LOW BYTE TEST]
DIM AZIL as BYTE
DIM AZIH as BYTE

AZIL = CAP2BUFL
SSPCON = AZIL

----------------MASTER------------------------------
Dim AZIL as Byte
SPIreceive AZIL

C.
It is wrong.

Code:
SSPCON = AZIL
It should be

Code:
SSPBUF = AZIL
In my code when PIC18F4620 is master, PIC18F4421 will be slave and when PIC18F4431 is master, PIC18F4620 will be slave. I made master (PIC18F4620) send 0xFF to slave and request data.
 
Top