I would bet that it doesn't set imediatly, but that it is setting after the first transfer takes place. It appears imediate because you are stepping.
When stepping through the code, after I put the first byte into the SPDR, the SPRF flags sets immediatly . . .
I suspect that, because you are stepping, the debugger is reading the registers in order to display them, and that is clearing the receive flag.
. . . but no matter what the next line of code is, the SPRF clears without my Rx interrupt being serviced.
Hello Tomahawk,
It is not clear what baud rate divisor you are using, but I suspect you would be using either 2 or 8. If this is so, I think that it is inappropriate to be using the SPI interrupt. Here is the reason -
In this case, there would be insufficient time to process several bytes, so later received data would be missed, particularly with two bytes in the SPI send buffer.
The solutions -
I would probably opt to not use interrupts - it would ultimately be quicker and simpler. For master operation, the SPI interurrupt is really only useful for slow baud rates where other useful processing can occur during the SPI transaction.
You can easily test whether this is the cause of your problem by reducing the baud rate, and seeing if data is still missed.
Regards,
Mac
Message Edited by bigmac on 2006-08-23 10:05 PM
bigmac wrote:Hello Tomahawk,
It is not clear what baud rate divisor you are using, but I suspect you would be using either 2 or 8. If this is so, I think that it is inappropriate to be using the SPI interrupt. Here is the reason -
[snip]
I would probably opt to not use interrupts - it would ultimately be quicker and simpler. For master operation, the SPI interurrupt is really only useful for slow baud rates where other useful processing can occur during the SPI transaction.
You can easily test whether this is the cause of your problem by reducing the baud rate, and seeing if data is still missed.
Regards,
Mac
Message Edited by bigmac on 2006-08-23 10:05 PM
Mac,
I am using a baud rate divisor of 2. I will try out a couple of things you suggest.
Thanks,
Tomahawk
rocco wrote:
Hi, Tomahawk:
I totally agree with Mac that you don't need interrupts, and that you could probably get it done faster with in-line code, and a clock-divider of 2 (assuming the C code is fast enough).
To do this double buffered, you just need to think of the transmitter as being two bytes ahead of the receiver. Here is an outline:
1) Write a byte to the transmitter.
2) Wait for transmitter-empty.
---
3) Write a another byte to the transmitter.
4) Wait for receiver-full.
5) Read the byte from the receiver.
6) Loop back to step-3.
Note that you only need to check for transmitter-empty when you start double buffering.
The transmitter will be an extra byte ahead, so you will need to skip step-3, and go to step-4 instead, after you receive your second-to-last byte. In other words, you will get TWO received bytes after you write your last transmitter byte.
Hope that helps.
So, for a two-byte transaction I should:
1) Write a byte to the transmitter.
2) Wait for transmitter-empty.
---
3) Write a another byte to the transmitter.
4) Wait for receiver-full.
5) Read the byte from the receiver.
6) Wait for receiver-full again
7) Read the byte from the receiver again.
Right?
Thanks,
Tomahawk
rocco wrote:
I have scanned everything, and have to say it is very easy to read.
BTW, rocco, thanks for the compliment. I try.
In other news, my timing requirments have changed slightly, so I can probably do away with using interrupts. So, even with my baud rate divisor of 2, can I use the double-buffered scheme, or should I just avoid it?
Thanks again,
Tomahawk
Hello Tomahawk,
The double buffering could probably be utilised provided you disable interrupts for the duration of the SPI transaction. However, as I have previously said, the total number of cycles would not be significantly reduced because you still need to receive the two bytes before the read process is complete.
Regards,
Mac
Message Edited by bigmac on 2006-08-24 02:36 AM
Hello Tomahawk,
I think I should clarify my .last post -
bigmac wrote:
The double buffering could probably be utilised provided you disable interrupts for the duration of the SPI transaction. However, as I have previously said, the total number of cycles would not be significantly reduced because you still need to receive the two bytes before the read process is complete.
I meant that all interrupts would need to be disabled using the in-line assembly instruction sei , and then re-enabled using cli instruction when the transactions are complete. I had actually assumed that you would not be using an ISR for the SPI.
The reason is that, once the second character is loaded to the send buffer you have no control over when the second transaction occurs, and you have a 16 cycle window to read the first byte from the receive buffer, before the second byte is received. So you cannot afford for any interrupt to delay reading the first byte. This critical timing occurs because there is double buffering for send, but not for receive.
If you send only a single byte at a time (you wait until the first byte is read before commencing the second byte) the timing becomes non-critical, so you would not need to disable interrupts. The timing penalty would only be the few cycles necessary to write the second byte to the send buffer.
If your data acquisition requirements are time critical to this extent, there may be more advantage to use in-line assembly for all SPI operations, rather than to utilise the double buffered send.
Regards,
Mac
bigmac wrote:Hello Tomahawk,
The double buffering could probably be utilised provided you disable interrupts for the duration of the SPI transaction. However, as I have previously said, the total number of cycles would not be significantly reduced because you still need to receive the two bytes before the read process is complete.
Regards,
Mac
Message Edited by bigmac on 2006-08-24 02:36 AM
Mac,
I have no problem completely disabling SPI interrupts and doing everything from main code. The slave part I'm communicating with requires 16 bit (two byte) transactions anyway, so I believe I will get some benefit out of using the double-buffered scheme. The problem is how to do it in C. Any suggestions/code snippets/etc.?
Thanks,
Tomahawk
rocco wrote:
Hi, Tomahawk:
I have scanned everything, and have to say it is very easy to read. I have only looked at the below routine closely, and I have commented it. It may have the answer, but I'm not sure. I will look at the ISR next.
rocco,
Thanks for looking at that routine, but the I don't really care about the about the init routine, it's the regular read routines where I want to make use of the double-buffering.
-Tomahawk