PDA

View Full Version : Using SPI hardware



harryweb
- 6th November 2013, 15:07
Hi,

For several days I'm trying to use the MSSP
The complete project is to use 4 x PIC18F45K22 as slave and another one as Master.
At this time I just simulate data between 1 slave and the master with Proteus 8 and... the simulation works.
Unfortunately, test with my PCB makes me crazy.

When Master asking to slave with a "?" I expect to receive "!WAY0625"

7123

or HEX: 21 57 41 59 30 36 32 35

This is simulation give, but in fact (Real PCB) the slave never answer the good message beginning by "!"

7124

don't care about the "41 hex" in place of "3F hex", this is because I'm trying other than "?" to begin TX.

The problem is: Why $10 on MISO (or other stupid values)

Here is my code:


'************************************************* ***************
'* Name : master.BAS *
'* Author : Herve Helleboid *
'* Notice : Copyright (c) 2013 HYTEM *
'* : All Rights Reserved *
'* Date : 02/11/2013 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

DEFINE OSC 64

TRISA = %00000000
TRISB = %00000000
TRISC = %10010000
TRISD = %10000000
TRISE = %00000000


ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000

' configuration USART2 (communication avec FAV)
RCSTA2 = $90 ' Enable serial port & continuous receive
TXSTA2 = $20 ' Enable transmit, BRGH = 0
SPBRG2 = 77 ' 9600 Baud @ 48MHz, 0,16%

' configuration USART1 (communication RS232 externe)
RCSTA1 = $90 ' Enable serial port & continuous receive
TXSTA1 = $20 ' Enable transmit, BRGH = 0
SPBRG1 = 103 ' 9600 Baud @ 64MHz, 0,16%


SSPEN VAR SSP1CON1.5 ' SSP Enable bit
CKP VAR SSP1CON1.4 ' Clock Polarity Select
SMP VAR SSP1STAT.7 ' Data input sample phase
CKE VAR SSP1STAT.6 ' Clock Edge Select bit
SSPIF VAR PIR1.3 ' SPI interrupt flag
SS0 var PORTB.3
SS1 VAR PORTB.1
SS2 VAR PORTC.2
SS3 VAR PORTC.1
LED VAR PORTE.0
slave var byte
i VAR BYTE ' loop counter
a VAR BYTE[6] ' Holds characters read from slave

HIGH SS0 'slaves are waiting (slave select pin)
HIGH SS1
HIGH SS2
HIGH SS3

HIGH LED
PAUSE 300
LOW LED
pause 300

hserout ["rdy",13,10]

SSP1CON1 = %00100010

SSPIF = 0 ' clear buffer full status

mainloop:

GoSub getdata ' initiate conversion and receive data
hserout ["lst ",STR a\7,13,10] ' display received string
high SS0
Pause 500
toggle led
GoTo mainloop ' do it forever

getdata:
low SS0
pauseus 10
SSPBUF = "?" ' send ? to start conversion
GOSUB letclear ' wait for buffer to clear
IF SSPBUF<>"!" Then getdata ' wait for reply (!)

For i = 0 to 6 ' loop for 7 characters
SSPBUF = 0 ' write to SSPBUF to start clock
GOSUB letclear ' wait for receipt
a[i] = SSPBUF ' store received character in array
Next i ' get next character
Return

letclear:
IF SSPIF = 0 Then letclear ' wait for SPI interupt flag 1=TRx complet must be cleared
PauseUs 25 ' 25uS fudge factor
SSPIF = 0 ' reset flag
Return


and



' Name : SPISLAVE.pbp
' Compiler : PICBASIC PRO Compiler 2.6
' Assembler : PM or MPASM
' pic18f45k22 @ 16MHz PLLx4 = 64MHz
'

DEFINE OSC 64

TRISA = %00100000
TRISB = %00000000
TRISC = %10011000
TRISD = %10001000
TRISE = %00000000


ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00001000
ANSELE = %00000000


' Allocate RAM
dataout VAR BYTE[8] ' Data out array
SSPEN VAR SSP1CON1.5 ' SSP Enable bit
CKP VAR SSP1CON1.4 ' Clock Polarity Select
SMP VAR SSP1STAT.7 ' Data input sample phase
CKE VAR SSP1STAT.6 ' Clock Edge Select bit
SSPIF VAR PIR1.3 ' interrupt flag - last bit set
i VAR BYTE ' loop counter
a VAR BYTE[6] ' Holds 6 characters of data
led var PORTA.4
way var byte 'n° de voie


' SSP1CON1 = %00000101 ' configure SPI slave, no SS
SSP1CON1 = %00000100 ' configure SPI slave with SS
CKP = 0 ' clock idle low
CKE = 0 ' transmit on idle to active transition
SSPIF = 0 ' clear SPI interrupt
SMP = 0 ' sample in middle of data

RCSTA1 = $90 ' Enable serial port & continuous receive
TXSTA1 = $20 ' Enable transmit, BRGH = 0
SPBRG1 = 25 ' 38400 Baud @ 64MHz, 0,16%

DEFINE ADC_BITS 8 ' ADCIN resolution (Bits)
DEFINE ADC_CLOCK 7 ' ADC clock source (Frc)
DEFINE ADC_SAMPLEUS 11 ' ADC sampling time (uSec)


dataout[0] = 87 ' Preset output WAY0625
dataout[1] = 65
dataout[2] = 89
dataout[3] = 48
dataout[4] = 54
dataout[5] = 50
dataout[6] = 53

HIGH LED
PAUSE 300
LOW LED


ADCIN 23,way

IF way < 30 then
way = 48 'way 0 for 470R
goto mainloop
endif

IF way < 60 then
way = 49 'way 1 for 2K2
goto mainloop
endif

IF way < 90 then
way = 50 'way 2 for 3K9
goto mainloop
endif

way = 51 'way 3 for 10K


mainloop:
SSPEN = 0 ' disable/enable SSP to reset port
SSPEN = 1
SSPBUF = "!" ' send reply $21 dec = 33
GoSub letclear ' wait for byte received
IF (SSPBUF <> "?") Then mainloop ' wait for ? to start conversion
toggle led
For i = 0 to 6 ' loop for 7 array locations
SSPBUF = dataout[i] ' send array variable
GoSub letclear ' wait until buffer ready
Next i ' next location
goto mainloop


letclear:
IF SSPIF = 0 Then letclear ' wait for interrupt flag
SSPIF = 0 ' reset flag
Return

End


7125

Any idea ? Someone can help ?

Regards
herve

harryweb
- 8th November 2013, 19:29
same as november 6

Measuring... Trying to understand what's wrong...

As I'm using PIC for my job... I'm sad... Too many hours (weeks) and... working now to make fast PIC's communication without pbp example (just one example found and not working ).

To be electronician is not an easy life !

Regards

harryweb
- 11th November 2013, 14:33
As nothing seem's to work... (not using simulation program now but real hardware)
Using now the smallest program to test what's wrong:


'************************************************* ***************
'* Name : master.BAS *
'* Author : Herve Helleboid *
'* Notice : Copyright (c) 2013 HYTEM *
'* : All Rights Reserved *
'* Date : 02/11/2013 *
'************************************************* ***************

DEFINE OSC 64


TRISA = %00000000
TRISB = %00000000
TRISC = %10010000
TRISD = %10000000
TRISE = %00000000


ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00000000
ANSELE = %00000000

' configuration USART1 (communication RS232 external)
RCSTA1 = $90 ' Enable serial port & continuous receive
TXSTA1 = $20 ' Enable transmit, BRGH = 0
SPBRG1 = 103 ' 9600 Baud @ 64MHz, 0,16%


SSPIF VAR PIR1.3 ' SPI interrupt flag
SSPEN VAR SSP1CON1.5 ' SSP Enable bit
SS0 var PORTB.3
LED VAR PORTE.0
slave var byte
i VAR BYTE ' loop counter
a VAR BYTE[6] ' Holds 6 characters read from slave
BF VAR SSP1STAT.0

HIGH SS0 'slave not in use

HIGH LED
PAUSE 300
LOW LED


hserout ["rdy",13,10]

Pause 50

SSP1CON1 = %00100010
SSP1STAT = %00000000

SSPIF = 0 ' clear buffer full status


mainloop:
pause 200
low SS0
pauseus 5
SSP1BUF = "?"
while BF = 1 : wend
pauseus 10
SSPIF = 0
high SS0
hserout [SSP1BUF," ",dec SSP1BUF,13,10] ' display received char
toggle led
GoTo mainloop ' do it forever

'************************************************* **********************************


' Name : SLAVE.pbp
' Compiler : PICBASIC PRO Compiler 2.6
' Assembler : PM or MPASM
' pic18f45k22 @ 16MHz PLLx4 = 64MHz
'

DEFINE OSC 64

TRISA = %00100000
TRISB = %00000000
TRISC = %10011000
TRISD = %10001000
TRISE = %00000000


ANSELA = %00000000
ANSELB = %00000000
ANSELC = %00000000
ANSELD = %00001000
ANSELE = %00000000


' Allocate RAM
dataout VAR BYTE[8] ' Data out array
SSPEN VAR SSP1CON1.5 ' SSP Enable bit
CKP VAR SSP1CON1.4 ' Clock Polarity Select
SMP VAR SSP1STAT.7 ' Data input sample phase
CKE VAR SSP1STAT.6 ' Clock Edge Select bit
SSPIF VAR PIR1.3 ' interrupt flag - last bit set
i VAR BYTE ' loop counter
a VAR BYTE[6] ' Holds 6 characters of data
led var PORTA.4
BF VAR SSP1STAT.0

SSP1CON1 = %00000100 ' configure SPI slave with SS
CKP = 0 ' clock idle low
CKE = 1 ' transmit on idle to active transition
SSPIF = 0 ' clear SPI interrupt
SMP = 0 ' sample in middle of data
SSPEN = 1

RCSTA1 = $90 ' Enable serial port & continuous receive
TXSTA1 = $20 ' Enable transmit, BRGH = 0
SPBRG1 = 25 ' 38400 Baud @ 64MHz, 0,16%


HIGH LED
PAUSE 300
LOW LED

mainloop:

SSP1BUF = "!" ' send reply $21 dec = 33
while BF = 1 : wend
PAUSEUS 10
SSPIF = 0
toggle led
goto mainloop




Master send "?" and need to receive "!"
doing it forever

AS I can see on my logic analyzer
MASTER send $3F (OK it's ? or decimal 63)
SLAVE send $21 (OK its ! or decimal 33)
This is measured with USBEE SX.

As I have a RS232 hardware connected to the PIC master (TX1) my master prog send to RS232 the received character
instead of receiving "!" (dec 33) it is always " " (dec 32)
sometimes also receiving strange characters

So... I was thinking that last bit is not recognized but:

If I change (slave prog) the character "!" by example by "W" or "0" it works fine every time !

I tried to send other different characters and for some of them, it's good...
For others it's decimal value -1 or decimal value + 1

Any help ?

Regards

HenrikOlsson
- 11th November 2013, 16:40
Hi,
I haven't looked that close at your code yet but have you tried putting the logic analyzer on the UART output of the PIC to verify what it is actually sending? Perhaps there's some baudrate issue, some problem with a USB-COM dongle (if you're using one) or something else on that side of equation. On the other hand I see you're outputting rdy at the start and I expect that to display properly. What if you change that to Ready! does it still display properly?

You could always try:

RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $24 ' Enable transmit, BRGH = 1
SPBRG = 130 ' 9600 Baud @ 64MHz, -0,02%
SPBRGH = 6
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator

/Henrik.

harryweb
- 11th November 2013, 20:09
Hello Henrik,

Thank you for your message
I have tryed your code and change rdy to ready without any result. I will try tomorrow on another computer (direct RS232 port, no USB dongle) to see if the problem isn't here.

Best Regards

Archangel
- 12th November 2013, 08:55
Are you certain your configs are set correctly to operate that PIC @ OSC 64 ?

harryweb
- 12th November 2013, 10:59
Hi,

@ Henrik
On another computer (real RS232 port) = same result

@Archangel
Hi and thank you for your reply

Do you think I forgot something in config bit ?
I'm not expert... May be you can check my config bits:

7127

Maybe I can try at 16MHz, but I choose this pic because of 64MHz.
Regards

HenrikOlsson
- 12th November 2013, 17:58
Hi,
I had never used the MSSP module in slave mode Before but I just had a play with two 18F25K20 devices, one as master and one as slave.
The master sends the letters "A" to "Z" and outputs both what it sends and what it recieves to the serial terminal.
The slave responds with the letters "Z" to "A". It outputs what it receives and what it sends to the serial terminal.

At this time I did not have time to implement and test the SS-line but apart from that it appears to work as expected.

You might be able to gain some insight into your trouble by looking at these two programs.

Here's the code for the master:

'************************************************* ***************
'* Name : SPI Master.pbp *
'* Author : Henrik Olsson *
'* Notice : Copyright (c) 2013 [Henrik Olsson] *
'* : All Rights Reserved *
'* Date : 2013-11-12 *
'* Version : 1.0 *
'* Notes : Designed to run on 18F45K20, AMICUS18 platform. *
'* : *
'************************************************* ***************
DEFINE OSC 64 ' Default oscillator speed on the AMICUS18 is 16*4MHz
DEFINE LOADER_USED 1 ' We're using a bootloader.

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 138 ' 115200 Baud @ 64MHz, -0,08%

SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator

TRISC = %10010110 ' RX, TX, SDO, SDI, SCK, N/U, N/U, CS
TRISB = %11111111 ' N/U, N/U, N/U, N/U, N/U, N/U, N/U, N/U

' Aliases for the MSSP module status and control bits.
SSPEN VAR SSPCON1.5 ' SSP Enable bit
CKP VAR SSPCON1.4 ' Clock Polarity Select
SMP VAR SSPSTAT.7 ' Data input sample phase
CKE VAR SSPSTAT.6 ' Clock Edge Select bit
BF VAR SSPSTAT.0 ' Buffer full flag.

' Set up the MSSP module.
CKP = 0 ' Clock idles low
CKE = 0 ' Transmit on idle to active transition.
SMP = 0 ' Sample in middle of data
SSPEN = 1 ' Enable SPI pins
SSPCON1.0 = 1 ' Slow down SPI clock to Fosc/16 for now.

i VAR BYTE
Response VAR BYTE

Response = SSPBUF ' Dummy read to buffer and BF-flag

HSEROUT ["Master start...", 13]
HSEROUT ["TX - RX",13]
Pause 5000

Main:
For i = "A" to "Z" ' Send letters A to Z
SSPBUF = i ' Load buffer with content
While BF = 0 : WEND ' Wait for operation to complete
Response = SSPBUF ' Read response
HSEROUT [i, " - ", Response, 13]
PAUSE 10
NEXT

HSEROUT ["Done.....", 13]

Pause 5000

Goto Main

And here's the code for the slave:

'************************************************* ***************
'* Name : SPI Slave.pbp *
'* Author : Henrik Olsson *
'* Notice : Copyright (c) 2013 [Henrik Olsson] *
'* : All Rights Reserved *
'* Date : 2013-11-12 *
'* Version : 1.0 *
'* Notes : Designed to run on 18F45K20, AMICUS18 platform. *
'* : *
'************************************************* ***************
DEFINE OSC 64 ' Default oscillator speed on the AMICUS18 is 16*4MHz
DEFINE LOADER_USED 1 ' We're using a bootloader.

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 138 ' 115200 Baud @ 64MHz, -0,08%

SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator

TRISC = %10011111 ' RX, TX, SDO, SDI, SCK, N/U, N/U, CS
TRISB = %11111111 ' N/U, N/U, N/U, N/U, N/U, N/U, N/U, N/U

' Aliases for the MSSP module status and control bits.
SSPEN VAR SSPCON1.5 ' SSP Enable bit
CKP VAR SSPCON1.4 ' Clock Polarity Select

SMP VAR SSPSTAT.7 ' Data input sample phase
CKE VAR SSPSTAT.6 ' Clock Edge Select bit
BF VAR SSPSTAT.0 ' Buffer Full bit

' Set up the MSSP module.
CKP = 0 ' Clock idles low
CKE = 0 ' Transmit on idle to active transition.
SMP = 0 ' Sample in middle of data

While PortC.4 = 1 : WEND ' Wait for SCK pin to be idle before enabling MSSP
SSPCON1 = %00100101 ' Slave mode, no SS

i VAR BYTE
Response VAR BYTE

HSEROUT ["Slave start...", 13]
HSEROUT ["RX - TX", 13]

Main:
For i = "Z" to "A" STEP -1
SSPBUF = i ' Load buffer
While BF = 0 : WEND ' Wait for data to arrive
Response = SSPBUF ' Read data from buffer, clears flag.
HSEROUT [Response, " - ", i, 13]
NEXT

HSEROUT ["Done...",13]

Goto Main

/Henrik.

HenrikOlsson
- 12th November 2013, 18:41
Hello again,
Looking at the slave code in post #3 above it says

CKE = 1 ' transmit on idle to active transition
The setting and comment does not match, Setting the CKE bit makes the slave, in this case, output data on active to idle state of the clock. But, looking at the master code it is set up to sample the data in the middle of the cycle. I'm not sure if this is the actual problem but comparing it to my examples it's something that differs.

/Henrik.

harryweb
- 13th November 2013, 19:19
Dear Henrik, and other who tryed to help me.

Today I made a new prototype.. Soldering new components on a new (but same) professionnal dual layer PCB and, using same programs
Plugin and.... Working !

I really don't know what's wrong with the first one.
My new prototype has just what is needed to test the SPI. (Only 2 pic and max232a)

Trying now to write the complete program... God bless me ;)

Thank you very much
7129