Bear with me here, I'm going to write a paragraph from the SPI Operation section 4.6.1.1 from the book "Arduino Microcontroller Processing for Everyone! Part 1". After that, I'm going to write down an order of operations, so to speak, that I plan on using....I just want to know if I understand SPI operation to it's fullest extent.
"SPI transmission is initiated by loading a data byte into the master configured SPDR. At that time, the SPI clock generator provides clock pulses to the master and also to the slave via the SCK pin. A single bit is shifted out of the master designated shift register on the MOSI microcontroller pin on every SCK pulse. The data is received at the MOSI pin of the slave designated device. At the same time, a single bit is shifted out of the MISO pin of the slave device and into the MISO pin on the master device. After eight master SCK clock pulses, a byte of data has been exchanged between the master and slave designated SPI devices. Completion of data transmission in the master and data reception in the slave is signaled by the SPIF in both devices. The SPIF flag is located in the SPSR of each device. At that time, another data byte may be transmitted."
So, with that being said, here's how I want to approach conducting an SPI transmit/receive between this LabView project and the Arduino Mega 2560.
A little background first, my main goal is taking a temperature value (achieved via an LM35 sensor wired to the Arduino - acting as the slave) and putting it into my LabView software - the master. For now, I'm treating it as an integer data type. I have a volatile global variable that stores this temperature value every 5 seconds (using the Timer.h library.) This is done via my timer-based function obtainTemp().
- In
obtainTemp(), I set the SPDR to the byte 10000000.
- LabView triggers transmit/receive, so the byte 00100000 gets transmitted to Ard., and 10000000 gets received in LabView. 00100000 gets stored in a global volatile variable called
incoming.
- SPIF is now 1, so interrupt ISR routine is triggered.
This is the part that gets me: if the transaction happens simultaneously, I feel like that implies the SPDR register should have data in it before the Arduino receives any byte at all.
- Inside ISR, I set the SPDR with the temperature data. When I transmit the second byte from LabView, it'll store it in a local variable called
byte b and, I assume at the same time, receive the temperature data from the previously set SPDR.
ISR (SPI_STC_vect)
{
if (bitRead(incoming, 5)) { // I evaluate that 6th bit to see if LV wants to read data
SPDR = temp; // get the buffer ready for transaction
byte b = SPDR; // receive data from LabView...hopefully the temp data gets exchanged
// other stuff
} else {
// other situation irrelevant to post
}
}
If any of you are wondering why I don't just send the temp data immediately upon request, instead of sending two bytes (10000000 and the temp byte) I'll explain that now.
In LabView, I am not using any definitive pre-built SPI functionalities, I'm doing everything hard-pulsed. I have noticed that if I add even one line extra in my Arduino code, signals will be thrown off by 1 ms. My clock pulses are 2 ms periods (1 ms up, 1 ms down)....and there is no way to get these two separate machines in sync with each other. However, I created this process in LV that allows me to receive the byte 10000000 as sort of an initial timer pulse to time when the next byte gets received (the temp byte.) This might not be without it's errors, but it can compensate for the unknowable lines of code that I may or may not add in the future.
So in terms of my ISR routine and how I'm treating this exchange process, is this the correct way to do it?