• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

SPI and 16F887

Winch

Member
I am working on two microcontrollers of the type 16F887 that I want to talk to each other as a master and slave.
Is there someone who has a sample program that works that I can use to compare with the software that I wrote myself?
I need to have a handhold to make sure what goes wrong?
Thanks,
 

Winch

Member
Oké Mike thanks.

Below the code for the Master.
The Master gives a correct signal to the outside.
As shown below.

LabNation_Screenshot2.png

Code:
'DEVICE PIC16F887

Define CONFIG1 = 0x23e4  '23e4
Define CONFIG2 = 0x3eff
Define CLOCK_FREQUENCY = 8

AllDigital  'alle ports digital

'defines the parameters of the LCD interfacing
Define LCD_BITS = 4
Define LCD_DREG = PORTD
Define LCD_DBIT = 4
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 2
Define LCD_EREG = PORTD
Define LCD_EBIT = 3
Define LCD_RWREG = PORTD
Define LCD_RWBIT = 0

'Defines the parameters of the PSI interfacing
Define SPI_SCK_REG = PORTC
Define SPI_SCK_BIT = 3
Define SPI_SDI_REG = PORTC
Define SPI_SDI_BIT = 4
Define SPI_SDO_REG = PORTC
Define SPI_SDO_BIT = 5
Define SPI_CS_REG = PORTC
Define SPI_CS_BIT = 7
SPIPrepare

'defines the SPI serial port
SSPCON.SSPEN = 0  'Enables serial port and configures SCK, SDO, SDI and SS as the source of the serial port pins
SSPCON.CKP = 1  'Clock polarity select bit: idle state for clock is a high level
SSPCON.SSPM0 = 0  'SPI master mode, clock = Fosc/4
SSPCON.SSPM1 = 0
SSPCON.SSPM2 = 0
SSPCON.SSPM3 = 0

SSPSTAT.CKE = 0  'SPI Clock Edge select bit: data transmitted on falling edge of SCK
SSPSTAT.SMP = 1  'SPI Master mode: 1 = input data sampled at end of data output time 0 = input data sampled at middle of data output time

'port names
Symbol RC7_CS = PORTC.7  'RC7-CS PSI output
Symbol RD0_CS = PORTD.0
Symbol ledred = PORTA.4  'control LED for version number and alarm signals
Symbol ledgreen = PORTC.6  'control LED for power and microcontroller
Symbol Escape = PORTB.0  'higher-1 key to increase warm light
Symbol Enter = PORTB.2  'higher-1 key to increase cold light
Symbol Down = PORTB.4  'lower-1 key to decrease warm light
Symbol Up = PORTB.5  'lower-1 key to decrease cold light

'declaring variable for the PIR Sensor
Dim pot1 As Byte  'voltage as variable "byte"(the measured analog value on input AN7)

'declaring variable for the switches
Dim d_escape As Byte
Dim d_enter As Byte
Dim d_up As Byte
Dim d_down As Byte

'declaring all kinds off variable
Dim n As Byte

'A gate set to the desired value
'76543210
PORTA = %00000000  'make all ports "PORTA" low
TRISA = %11101111  '1 = input,RA7,RA6,RA5,RA3,RA2,RA1,RA0 are set for input. 0 = output, RA4(LEDred), is set for output!
ANSEL = %11000000  '1 = Analog input, RA6 and RA7 are set for analog input, 0 = digital input, RA0,RA1,RA2,RA3,RA4,RA5 are set digital I/O input.

'B gate set to the desired value
'76543210
PORTB = %00000000  'make all ports "PORTB" low
TRISB = %11111111  '1 = input, 0 = output
WPUB = %11001010  'weak pull-up portB register. 1 = pull-up enabled 0 = pull-up disabled (datasheet page 51)

'C gate set to the desired value
'76543210
PORTC = %00000000  'make all ports "PORTC" low
TRISC = %00010111  '1 = input, Port RC0(Save),RC4(SDIspi) are set for input, 0 = output, RC1(CCP2),RC2(CCP1),RC3(SCKspi),RC5(SDOspi),RC6(LEDgreen),RC7(CSoutput) are set for output

'D gate set to the desired value
'76543210
PORTD = %00000000  'make all ports "PORTD" low
TRISD = %11111111  '1 = input, 0 = output

'E gate set to the desired value
'76543210
PORTE = %00000000  'make all ports "PORTE"low
TRISE = %11111111  '1 = input, 0 = output

Lcdinit 0  'no cursor

ledgreen = 1  'turn on the green led!
pot1 = 0  'start "pot1" with zero
RD0_CS = 1

main:  'endless loop

    Lcdcmdout LcdLine2Home
    Lcdout "Pot1="
    Lcdcmdout LcdLine2Pos(6)
    Lcdout #pot1

    Adcin 7, pot1
    
For n = 1 To 10
    SPICSOn
            SPISend pot1
        WaitMs 10
    SPICSOff
Next n
    
Goto main

End  'end program
Below the code for the Slave.
Here I can not see the signal coming back correctly.
And the question is is it the software or is it something else?

What I find strange is the SSPCON.SSPEN setting that should be on enable, but then I get no signal from the master.
At the moment that I put it on disable, my master sends the signal outside. As can be seen above.

Here you doubt the software because it should be just the other way around?

Code:
'DEVICE PIC16F887

Define CONFIG1 = 0x23e4  '23e4
Define CONFIG2 = 0x3eff

Define CLOCK_FREQUENCY = 8

'OSCCON = %01110101  'Oscillator control (datasheet page 66)

AllDigital  'alle ports digital

'defines the parameters of the LCD interfacing
Define LCD_BITS = 4
Define LCD_DREG = PORTD
Define LCD_DBIT = 4
Define LCD_RSREG = PORTD
Define LCD_RSBIT = 2
Define LCD_EREG = PORTD
Define LCD_EBIT = 3
Define LCD_RWREG = PORTD
Define LCD_RWBIT = 0

'Defines the parameters of the PSI interfacing
Define SPI_SCK_REG = PORTC
Define SPI_SCK_BIT = 3
Define SPI_SDI_REG = PORTC
Define SPI_SDI_BIT = 4
Define SPI_SDO_REG = PORTC
Define SPI_SDO_BIT = 5
Define SPI_CS_REG = PORTA
Define SPI_CS_BIT = 5
SPIPrepare

'defines the SPI serial port
SSPCON.SSPOV = 1  'In slave mode, the user must read the SSPBUF
SSPCON.SSPEN = 1  'Enables serial port and configures SCK, SDO, SDI and SS as the source of the serial port pins
SSPCON.CKP = 1  'Clock polarity select bit: idle state for clock is a high level
SSPCON.SSPM0 = 0  'SPI slave mode, clock = SCK pin, SS pin control enabled
SSPCON.SSPM1 = 0
SSPCON.SSPM2 = 1
SSPCON.SSPM3 = 0

SSPSTAT.CKE = 0  'SPI Clock Edge select bit: data transmitted on falling edge of SCK
SSPSTAT.SMP = 0  'SPI Master mode: 1 = input data sampled at end of data output time 0 = input data sampled at middle of data output time

'port names
Symbol ledred = PORTA.4  'control LED for version number and alarm signals
Symbol ledgreen = PORTC.6  'control LED for power and microcontroller

'declaring all kinds off variable
Dim n As Byte
Dim waarde As Byte  'voltage as variable "byte"(the measured analog value on input AN7)

'A gate set to the desired value
'76543210
PORTA = %00000000  'make all ports "PORTA" low
TRISA = %11101111  '1 = input,RA7,RA6,RA5,RA3,RA2,RA1,RA0 are set for input. 0 = output, RA4(LEDred), is set for output!
ANSEL = %11000000  '1 = Analog input, RA6 and RA7 are set for analog input, 0 = digital input, RA0,RA1,RA2,RA3,RA4,RA5 are set digital I/O input.

'B gate set to the desired value
'76543210
PORTB = %00000000  'make all ports "PORTB" low
TRISB = %11111111  '1 = input, 0 = output
WPUB = %11001010  'weak pull-up portB register. 1 = pull-up enabled 0 = pull-up disabled (datasheet page 51)

'C gate set to the desired value
'76543210
PORTC = %00000000  'make all ports "PORTC" low
TRISC = %10011001  '1 = input, Port RC0(Save),RC3(SCKspi),RC4(SDIspi) are set for input, 0 = output, RC1(CCP2),RC2(CCP1),RC5(SDOspi),RC6(LEDgreen), are set for output

'D gate set to the desired value
'76543210
PORTD = %00000000  'make all ports "PORTD" low
TRISD = %11111111  '1 = input, 0 = output

'E gate set to the desired value
'3210
PORTE = %0000  'make all ports "PORTE"low
TRISE = %1111  '1 = input, 0 = output

Lcdinit 0  'no cursor

ledred = 1  'turn on the red led!
waarde = 0

main:  'endless loop

Lcdcmdout LcdClear
Lcdout "Pot1="

For n = 1 To 10
    SPICSOn
        SPIReceive waarde
    SPICSOff
        
    Lcdcmdout LcdLine1Pos(6)
    Lcdout #waarde
    WaitMs 50
Next n

Goto main

End  'end program
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
One thing you need to understand... Oshonsoft has no hardware SPI... Vladimir only used software SPI so using internal settings messes with the software implementation..

I have the codes for hardware SPI, but not for slave... You can have it by all means

Code:
'----------------------------------------
Proc spi_init()
 TRISC.5 = 0
 TRISC.2 = 0
 TRISC.4 = 1
 TRISC.3 = 0
 ss = 1
 SSPSTAT = 0
 'SSPSTAT.CKE = 1  'clock edge un remark for trailing edge
 SSPCON1 = 0x20  'full whack... at 8mhz 2mhz operation no SS control
      '00 = fosc/4.. 01 = fosc /16
      '10 = fosc/64.. 11 contolled by timer2.
 SSPCON1.CKP = 1  'clock polarity unremark for high polarity
End Proc                                          
'----------------------------------------
Function do_spi_8(data As Byte) As Byte
 do_spi_8 = SSPBUF
 SSPBUF = data
 While Not SSPSTAT.BF
 Wend
 
End Function                                      
'----------------------------------------
This will get a byte on the spi whilst transferring another.. If you use this DO NOT declare any SPI stuff in Oshonsoft
 

Winch

Member
Hi Ian, I owe you an answer!
I had not worked with procedures and functions before. Something that I will use more often.
At the end this has become the code!

Code:
main:  'endless loop

Adcin 7, data

Lcdcmdout LcdLine2Home
Lcdout "Pot1="
Lcdcmdout LcdLine2Pos(6)
Lcdout "", #data, " "
        
For n = 1 To 10
    Call spi_init()
        RC7_CS = 0
            data = do_spi_8(data)
        RC7_CS = 1
Next n

WaitMs 10
    
Goto main

End  'end program                                 

'* SPI set as master
Proc spi_init()
    TRISC.5 = 0  'SDO = output
    TRISC.4 = 1  'SDI = input
    TRISC.3 = 0  'SCK = output
    RA5_SS = 1  'set "slave select" high
    SSPSTAT = 0
    SSPSTAT.CKE = 1  'clock edge un remark for trailing edge
    SSPCON = 0x20  'SPI: Master mode, Clock = Fosc/4
                        'CKP: Idle state for clock is a low level
                        'SSPEN: SPI mode, enebles serial port
End Proc                                         

Function do_spi_8(data As Byte) As Byte
    do_spi_8 = SSPBUF
    SSPBUF = data
    While Not SSPSTAT.BF
    Wend
End Function
And the slave code as well.

Code:
main:  'endless loop

Lcdcmdout LcdClear
Lcdout "Pot1="

For n = 1 To 10
    Call spi_init()
        RA5_SS = 0
            value = do_spi_8(value)
        RA5_SS = 1
    Lcdcmdout LcdLine1Pos(6)
    Lcdout "", #value, " "
Next n

Goto main

End  'end program                                 

'* SPI set as slave function
Proc spi_init()
    TRISC.5 = 0  'SDO = output
    TRISC.4 = 1  'SDI = input
    TRISC.3 = 1  'SCK = input
    RA5_SS = 1  'set "slave select" high
    SSPSTAT = 0
    SSPSTAT.CKE = 1  'clock edge un remark for trailing edge
    SSPCON = 0x24  'SPI: Slave mode, Clock = SCK pin, SS pin control enabled
                        'CKP: Idle state for clock is a low level
                        'SSPEN: SPI mode, enebles serial port
End Proc                                         

Function do_spi_8(value As Byte) As Byte
    do_spi_8 = SSPBUF
    SSPBUF = value
    While Not SSPSTAT.BF
    Wend
End Function
You have been a great help. Thanks!
 

Latest threads

EE World Online Articles

Loading

 
Top