Hi T,So you've done what I suggested back in posts #23 and #34. That's a good first start. Congratulations!
If you like, post both sides of the code... if not done properly there are still multiple ways for this to go south.
Does the master set SS low and then high around each byte or does it just do it once around the whole block of 35 bytes?
What peripherals are they? - for example all I2C devices are just two wire, and you have to include the address of the device you're wanting to use - but SPI uses (at least) 3 wires, with the third wire the chip select for that particular device. So I2C just uses 2 wires, however many devices they are, while SPI use 2 wires, PLUS an extra chip select wire for each device.Hi T,
Yes, they are long posts, and difficult to digest, but I suppose my subconsious must have be taking notes.
I'll post them later, as they are not finished yet.
The MASTER C/S-SS the whole block of 35 BYTES., and there are the odd mistakes.
I have other successful peripherals, where the MASTER sends the address of where each BYTE to be READ is and they work without an acknowledgment track, how is this possible?
C
That doesn't matter here. Your problem isn't whether it has an address, or a register, or an array, or a message, or a while-wend loop.The PIC has an EEPROM, as mentioned earlier.
As I would expect. There are ways to speed up the communications in a master-slave arrangement but that's way beyond your skill level. We're already struggle here, so best to just get it working reliably. That's hard enough.Some of the other peripherals have 1US delays, by experiment, and they all work just fine.
Hi P,An SPI hardware peripheral is different than a master-slave setup with two pics.
The hardware peripheral is MUCH faster since there's no code invoked on the peripheral end.
With a master-slave, the master pic has to allow the slave pic time to read each byte, process it, and prepare what it wants to send back next time before the master can send the next byte.
If you add a 'delay 100us' on the master side each time you send a byte that'll probably help. It'll be slower, but unless you arrange to have that new signal you added hardware-driven it's safer.
Hi T,So you've done what I suggested back in posts #23 and #34. That's a good first start. Congratulations!
If you like, post both sides of the code... if not done properly there are still multiple ways for this to go south.
Does the master set SS low and then high around each byte or does it just do it once around the whole block of 35 bytes?
Hi T,On the slave side you've changed the order of operations and you're now reading the SSPBUF before BF is set to indicate there's data to be read.
Which is how this thread and all the others on all the different forums you post on about the same issue get to be so long and convoluted.I try all sorts of things that probably wouldn't be the accepted way.
In this case, I probably moved lines around till it worked.
I certainly wouldn't read a register before the hardware told me it had valid data.How would you do it?
Hi T,Which is how this thread and all the others on all the different forums you post on about the same issue get to be so long and convoluted.
'working' appears to be a relative term here.
I certainly wouldn't read a register before the hardware told me it had valid data.
If you swap the order then you're going to complain that the transfers are 'off by one' because you don't understand how an SPI transfer works. Write and read happen at the same time... as the master sends a byte it reads the data that's already sitting in the slave's SSPBUF. When the slave receives a byte what it loads into the SSPBUF as a response will get transferred to the master on the NEXT incoming byte.
That means that either:
- you preload the SSPBUF with the first byte BEFORE the master starts a transmission (which means that you have to know in advance what the master wants to read),
or
- the master sends a dummy byte, knowing that the response will always be one byte out-of-step. The slave has to know about the dummy transfer so that it doesn't think it's real data from the master.
Since you now have a line that goes back to the master to say "I'm ready", when the master lowers the SS the slave can load the SSPBUF with the first byte before it raises the 'ready' line letting the master know it can continue.
The slave should have the SS input enabled in the init_spi routine. That way when the master sets SS high the slave bit counter will reset. You might also consider exiting the slave 'While Not SSPSTAT.BF - WEND' and FOR-NEXT loops if it sees the SS high... that's an indication something bad happened and you didn't get all the bytes you were expecting.
Hi T,On the slave side, as long as you don't care what the master's sending (which seems to be the case here), I suppose it doesn't matter if the slave reads garbage. You don't even need the m2s() array... you could replace that with 'WREG = SSPBUF' and it should give the same result. You do need to read SSPBUF so that it clears the BF flag, but you don't need to do anything with the result.
The 'delayms' call on the master side all depends on what else the slave might be doing. If there are no interrupts then that could be reduced to just a few usecs. If the slave is using interrupts (for something else) then that delay call would have to be as long as the worst-case interrupt execution time.
==============================MASTER ==========================================
slave4431_cs = 0 'CS ON
For spipsn = 0 To 35 'spipsn To 35=36 BYTES including 1x DUMMY BYTE-GPS=31 $-W-QEI=2-BATVOLT=1-SPARE DATA=1
While Not s2m_ack 'Wait for SLAVE to set its SSPBUF with valid S2M buffer data
Wend
SSPBUF = m2s(spipsn) 'Transfer M2S(spipsn) BYTE into SSPBUF
While Not SSPSTAT.BF 'Wait for M2S BYTE to fill buffer
Wend
s2m(spipsn) = SSPBUF 'Transfer SSPBUF BYTE into S2M(spipsn)
waitus 10
Next spipsn
slave4431_cs = 1 'CS OFF
=========================== SLAVE ====================================================
' be sure to set the ack output low as part of the setup code
s2m_ack = 0
If slave4431_cs = 0 Then 'if chip select on do the code otherwise skip
For spipsn = 0 To 35 'GPS=30 $-W INC, QEI=2 BATVOLT=1 SPARE DATA=1
SSPBUF = s2m(spipsn) 'Transfer S2M(spipsn) into SSPBUF
s2m_ack = 1 'Tell MASTER that SLAVE is ready
While Not SSPSTAT.BF 'Wait for M2S(spipsn) BYTE to transfer into SSPBUF
If slave4431_cs = 1 Then ' this should not happen, but if it does error
Exit For
Endif
Wend
s2m_ack = 0 'Set S2M_ACK off till next loop
m2s(spipsn) = SSPBUF 'Transfer M2S(spipsn) BYTE from SSPBUF into M2S(spipsn)
Next spipsn
Endif 'slave4431_cs
Hi T,Try this and see what happens.
With this one the master and slave use the READY/ack signal around each byte, which is what I think you were trying to do. It shouldn't need any dummy bytes. I also added an exit on the slave side in case something goes wrong and the master raises the CS in the middle of the transfer.
There's still a possible race condition in this...
Code:==============================MASTER ========================================== slave4431_cs = 0 'CS ON For spipsn = 0 To 35 'spipsn To 35=36 BYTES including 1x DUMMY BYTE-GPS=31 $-W-QEI=2-BATVOLT=1-SPARE DATA=1 While Not s2m_ack 'Wait for SLAVE to set its SSPBUF with valid S2M buffer data Wend SSPBUF = m2s(spipsn) 'Transfer M2S(spipsn) BYTE into SSPBUF While Not SSPSTAT.BF 'Wait for M2S BYTE to fill buffer Wend s2m(spipsn) = SSPBUF 'Transfer SSPBUF BYTE into S2M(spipsn) waitus 10 Next spipsn slave4431_cs = 1 'CS OFF =========================== SLAVE ==================================================== ' be sure to set the ack output low as part of the setup code s2m_ack = 0 If slave4431_cs = 0 Then 'if chip select on do the code otherwise skip For spipsn = 0 To 35 'GPS=30 $-W INC, QEI=2 BATVOLT=1 SPARE DATA=1 SSPBUF = s2m(spipsn) 'Transfer S2M(spipsn) into SSPBUF s2m_ack = 1 'Tell MASTER that SLAVE is ready While Not SSPSTAT.BF 'Wait for M2S(spipsn) BYTE to transfer into SSPBUF If slave4431_cs = 1 Then ' this should not happen, but if it does error Exit For Endif Wend s2m_ack = 0 'Set S2M_ACK off till next loop m2s(spipsn) = SSPBUF 'Transfer M2S(spipsn) BYTE from SSPBUF into M2S(spipsn) Next spipsn Endif 'slave4431_cs
Supposedly it does, but I can't check it...Does [ Exit for ] mean Exit the 'for next' LOOP?
Exit For statement provides a way to exit a For-Next loop. It transfers control to the statement following the Next statement.
In SPI mode there's WCOL and SSPOV, neither of which should occur if the software is written properly.I'm looking at other SPI error checks in the D/S, in case they should be added.
Hi T,Supposedly it does, but I can't check it...
In SPI mode there's WCOL and SSPOV, neither of which should occur if the software is written properly.
SSPOV means the slave missed receiving a byte, and since every byte now has a 'ready' handshake around it that should never happen. That said, defensive programming is always a good thing.
One thing to watch out for is the slave 'ready/ack' signal doesn't get lowered until the BF 'while-wend' loop exits. If the slave is busy with other things (ie interrupts) that can still be an issue.
One way around that is to have the ready/ack signal driven by hardware so that it automatically gets cleared when it detects an SPI CLK. To do that I typically use a TMR + CCP module in compare mode to count external SPI clocks... connect SPI CLK -> TMR external input, and CCP out -> ready signal.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?