Synchronized SPI communication

I am trying to implement interrupt based SPI communication between two Atmel microcontrollers. The data has to be transmitted from slave to master.

In master i continuously sends 0xff to the slave and master expects data from slave on each transfer.

char SPI_MasterTransfer(char cData) { uint8_t a; PORTB &= ~(_BV(PB4)); // Slave select a = SPDR; SPDR = cData; while(!(SPSR & (1

Reply to
Vivek B
Loading thread data ...

I didn't look at your problem in detail, but before you go any further try your code with a different data pattern than 0xFF. Choose say 0x10 or 0x08. FF is a bad test case because you can't see if you are missing bits in between bytes.

Reply to
larwe

[snip]

Both controllers are running from the same clock ? I'd hook up an analyzer to start with.

Rene

Reply to
Rene Tschaggelar

[Snipped]

Because the slave transfers data to the master at the same time the master transfers data to the slave, you have very little time to load the data register on the slave side, if you want to respond based on the data received from the master side. You must iether use defined time slots, so that the slave has enough time to load the data register before the master clocks it back to itself, or you can use handshake lines, with which the slave can indicate to the master that data is ready to be clocked accross.

Regards Anton Erasmus

Reply to
Anton Erasmus

His problem is probably on a per byte basis, not per bit.

I had this - well, as long ago as 1994 was... - when I defined an SPI channel per Nukebus slot (which is a 16-data/8 address bits interface) to have some means to deal with the many infrequently changing bits a device typically has over less wires. Since SPI is host driven the host must poll the slave, and must send new data no faster than the slave can process (or buffer) it. Then the host has no way of knowing whether upon sending a byte what it gets over the same 8 clocks is the byte it has sent in the previous 8 clocks or data which the slave has written to the output register in the meantime. So I defined the protolol as a 7 bit (7 bits per byte, that is). Any data the host sends has bit 7 set 0, and any data the slave sends has bit 7 set to 1; the host uses bit 7 in its input stream to determine whether the slave has output a byte. The host sends a 0 to poll the slave which the slave has to ignore. This has worked ever since. The slave processing speed is defining, it often can be not so fast a protocol as SPI is for driving, say, a DAC or something; the host has to wait between bytes it sends to prevent the slave from missing a byte due to receiver overrun.

Dimiter

------------------------------------------------------ Dimiter Popoff Transgalactic Instruments

formatting link

------------------------------------------------------

Reply to
Didi

Nope.. Both Atmels are running at different clocks!!

Reply to
Vivek B

To introduce new handshake lines is the last method i would prefer (just because the hardware need to be changed a lot). Do you have an idea of what the master Data register would get when it try SPI transfer and the slave is within the Interrupt Service Routine for the previous SPI transfer interrupt.

say..

Master transfers 0x50 - Now the slave SPDR = 0x50 and it enters the interrupt service routine. before the slave leaves the ISR the master sends 0x60 and 0x70. Now how is it suppossed to behave? Does the SPDR of the slave get affected?

regards

Vivek

Reply to
Vivek B

Thank you larwe.. i wished it works but it did'nt ..

Reply to
Vivek B

The master must wait for(or timeout) the expected response from the slave before issuing another write to the slave.

Reply to
Ivanna Pee

From the AVR datasheet: The system is single buffered in the transmit direction and double buffered in the receive direction. This means that bytes to be transmitted cannot be written to the SPI Data Register before the entire shift cycle is completed. When receiving data, however, a received character must be read from the SPI Data Register before the next character has been completely shifted in. Otherwise, the first byte is lost.

If you do not want to add handshake lines, then you would either have to add a delay as other people have proposed, or you can do a 3 byte transfer from the master for every one byte transfer from the slave.

The master transfers the first byte. As soon as the byte has been clocked in, the slave will generate an interrupt. While this is happening the master clocks in the second byte. The slave reads byte1, and based on this loads the Data register. The slave must do this in the time it takes to shift in the second byte. On the third transfer the master gets the requested data from the slave.

From the master point of view it transfers valid data during the first transfer, and the slave ignores the second and third transfer. The slave transfers valid data on the third transfer to the master, and the master ignores the first two transfers.

Regards Anton Erasmus

Reply to
Anton Erasmus

"The slave must do this in the time it takes to shift in the second byte."

What if the slave has much heavier ISR routine?? The whole thing fails, right?

So, i guess the only solution is to have dedicated hardware handshaking lines.. :-(

Anyways, thank you..

Reply to
Vivek B

The way I look at SPI, is the slave replies with whatever was previously loaded - so slave TX is one load behind the Slave RX.

If you send multiple bytes, the Slave needs to keep up with the data rate, and a lot of SPI HW is poor at helping with this. The Atmel 89LP series have buffered TX, but most do not - so that implies a sufficent inter-byte pause, to get everything ready for the next clock burst.

Do you have a 4 wire SPI connection - if so, you could time-share a handshake system, between the SPI bursts ?

-jg

Reply to
Jim Granville

Right. You need to wait longer than the slave needs to process a byte. There are also other issues you will have to adress after you move past this step, I explained them all in my previous post. Basically, you cannot simplify the protocol I described over SPI.

Apart from waiting - and having the slave fast enough - yes. But then this will no longer be SPI. Notice that if your slave has an input FIFO you will be able to send bursts of bytes at full speed, this can dramatically improve the overall speed.

Dimiter

------------------------------------------------------ Dimiter Popoff Transgalactic Instruments

formatting link

------------------------------------------------------

Reply to
Didi

Yup, i am using a 4 wire SPI connection

-TX

-RX

-SCK (clock)

-CS (chip select)

And , i didnt really understand by "time-share a handshake system" ..

thank you

Vivek

Reply to
Vivek B

"Basically, you cannot simplify the protocol I described over SPI. "

I wanted to make that sure.. And i guess it's turning out to be!

Reply to
Vivek B

As an example, that means using one line for two tasks. viz: Config CS as OpenDrain, lightish pullups send a byte as CS=L, 8 CLKS+DATA CS=H, and then enable an INT =\_ on the CS line, and wait until the slave pulses it LOW, to say it has the next reply ready. Then the master sends as before.

So you have a simple pacing system, where the slave 'keeps up' as best it can, but any longer pauses are handled.

-jg

Reply to
Jim Granville

I would like to tell you these points with respect to SPI:

  1. To read data from Slave by Master, it is necessary to transfer a dummy byte ( 0xFF in your case) from Master to Slave.
  2. On interrupt at Master (after transferring the a byte) you simply read the byte in the SPI buffer into a variable.
  3. Now to get the next byte, repeate the step 1 and 2 till all the bytes are read.

HTH

-Dk

Reply to
dk

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.