My SPI communication is taking a long time... can't figure out why. I am measuring elapsed time
Mahonroy
Posts: 175
in Propeller 1
Hey guys,
I am measuring elapsed time over various functions and displaying it through the Parallax Serial Terminal.
I noticed that my SPI functionality is taking a long time (it takes 105 milliseconds to execute the SPI function below).
Here is my method for measuring elapsed time:
Inside the ReadPayload function I started commenting stuff out so I could see what is taking so long, turns out the "Read RX Payload" part is what takes 105 milliseconds! Both the "Low(SPI_Ce)" and the "High(SPI_Ce)" take only 82 us (microseconds) each to execute.
So I dug into the "SpiReadWrite" function:
So I don't understand what the problem is here? Shouldn't this be executing like a 100 times faster? Thanks and any help is greatly appreciated!
I am measuring elapsed time over various functions and displaying it through the Parallax Serial Terminal.
I noticed that my SPI functionality is taking a long time (it takes 105 milliseconds to execute the SPI function below).
Here is my method for measuring elapsed time:
Time := -cnt 'Functions to time go here nRF.ReadPayload Time += cnt - 544 PST.Str(string(13,"Time to read payload: ")) PST.Dec(Time / (clkfreq / 1000)) 'Display in milliseconds
Inside the ReadPayload function I started commenting stuff out so I could see what is taking so long, turns out the "Read RX Payload" part is what takes 105 milliseconds! Both the "Low(SPI_Ce)" and the "High(SPI_Ce)" take only 82 us (microseconds) each to execute.
PUB ReadPayload | idx, fifoRegister 'Stop receiving Low(SPI_Ce) 'Read RX payload Low(SPI_Csn) SpiReadWrite(R_RX_PAYLOAD) repeat idx from 0 to 31 payload[idx] := SpiReadWrite(NOOP) High(SPI_Csn) 'Start receiving High(SPI_Ce)
So I dug into the "SpiReadWrite" function:
PUB SpiReadWrite(byte_out) : byte_in | bit {{ SPI read-write procedure (8-bit SPI mode 0) Read and write are synced, i.e. for each byte in it is one byte out For deatails see: http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus }} byte_in := byte_out repeat bit from 0 to 7 'Write MOSI on trailing edge of previous clock if (byte_in & $80) High(SPI_Mosi) else Low(SPI_Mosi) byte_in <<= 1 'Half a clock cycle before leading/rising edge TIME.PauseUSec(1) High(SPI_Sck) 'Half a clock cycle before trailing/falling edge TIME.PauseUSec(1) 'Read MISO on trailing edge byte_in |= Read(SPI_Miso) Low(SPI_Sck) return byte_in PUB PinDelay(Pin) if Pin == SPI_Ce waitcnt(clkfreq / CE_DELAY + cnt) 'CE_DELAY = 100_000 elseif Pin == SPI_Csn waitcnt(clkfreq / CSN_DELAY + cnt) 'CSN_DELAY = 100_000 PUB High(Pin) dira[Pin]~~ outa[Pin]~~ PinDelay(Pin) PUB Low(Pin) dira[Pin]~~ outa[Pin]~ PinDelay(Pin) PUB Read(Pin) dira[Pin]~ return ina[Pin]
So I don't understand what the problem is here? Shouldn't this be executing like a 100 times faster? Thanks and any help is greatly appreciated!
Comments
It would also be worth moving the contents of High and Low into your read/write function, and only setting dira[Pin]~~ once, instead per iteration in the loop.
So it looks like I really need to get my hands on a SPI object thats written in assembly, and use that in place of my functions? I'm still shocked that its that much slower... so even the wait instructions are probably not accurate either.
EDIT:
So if I am reading the datasheet correctly for the nRF24L01+, it looks like it can handle an 8Mhz SPI clock speed.
I found the SPI_Asm.spin object, but I am a little confused what value to use for start(Delay,state). So state should be 0 so the Clock starts low.... but what is an appropriate delay to use? So 8 mhz is 0.125 microseconds correct? it says if I use a delay of 5 that is 500 nanoseconds, and a delay of 15 is 1000 nanoseconds. So it seems I could use the smallest delay e.g. 1 for the fastest speed?
Thanks again for the advice!
If you want, I will post some code that just increments. It's only one byte at a time but it has no delays.
Sure that sounds good. So you are saying the CE or CNS does not need a delay? I was under the impression that it did. The CE is cycled high then low to trigger the nRF to transmit.
If that's too short, turn the pin on two or three times, without turning it off, just to waste time.
Whenever csn goes low sck cycles high and low eight times. In mode zero data is read(clocked in) when sck is high. Then there will be a short pause before the next byte begins.
The four spi pins are mosi, miso, csn and sck.
Irq signals that data has been sent or received and ce controls the radio.
There is no 'Shockburst' since it slows things down noticeably.