View previous topic :: View next topic |
Author |
Message |
bwhiten
Joined: 26 Nov 2003 Posts: 151 Location: Grayson, GA
|
Retrieving a value from Slave using SPI |
Posted: Thu Jul 17, 2008 7:02 pm |
|
|
I am struggling to finish this piece of code. I am using the Master PIC, 18F67J50 to send multiple bytes of data to the Slave PIC, 16F887 without problems.
In the Slave I capture the SPI data using the interrupt and a buffer:
Code: | #int_ssp
void ssp_isr(void) {
spi_buffer[next_in] = spi_read(buffer[10]);
next_in++;
if(next_in >= BUFFER_SIZE)
next_in = 0;
}
|
In the Master I send the data like this.
Code: | void spi_send(int8 data) {
delay_ms(1);
buffer[7] = spi_read(data);
delay_ms(1);
}
|
I would expect buffer[7] in the Master to take the value of buffer[10] from the Slave during the write from Master to Slave but this is not happening correctly. It appears the interrupt routine is hanging unless I remove the buffer[10] from the spi_read(.....) statement. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: Retreiving a value from Slave using SPI |
Posted: Thu Jul 17, 2008 8:56 pm |
|
|
I don't think spi_read(data) is meant to be using inside an interrupt routine. The int_ssp interrupt occurs after the transfer is over. By then it is too late to load the buffer[10] value into the SPI data register. I think spi_read(data) is meant to be used from non-interrupt code. As such, it probably starts out by clearing the very condition that caused the interrupt. On the other hand, I think spi_read() with no argument is just a read of the current value of the SPI data register, and as such it cannot hang. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
bwhiten
Joined: 26 Nov 2003 Posts: 151 Location: Grayson, GA
|
|
Posted: Thu Jul 17, 2008 9:06 pm |
|
|
Any recommendations on how to efficiently get rid of the interrupt routine? It does work well on capturing incoming data. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Fri Jul 18, 2008 5:40 am |
|
|
I don't generally use the built-in functions for SPI, so I would probably talk directly to the hardware registers. The slave needs to write buffer[10] to the SSPBUF register before the interrupt occurs. Then when the interrupt occurs, it can read SSPBUF to get the data that was sent from the master, then it must again write buffer[10] (or whatever data you want the slave to send on the next SPI transaction) to the SSPBUF register.
The CCS library function, spi_write() may do more than just write to the SSPBUF register. I can't tell from the documentation. That is why I am reluctant to use the library functions for this. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
Ttelmah Guest
|
|
Posted: Fri Jul 18, 2008 7:06 am |
|
|
Hurrah!...
Agree wholeheartedly on using the inbuilt functions. Especially if going interrupt driven.
Have posted my own macros for SPI here in the past for exactly this reason.
The documentation for the inbuilt functions is also poor, so you have to do things like PCM's test, to find out what they do.
Best Wishes |
|
|
bwhiten
Joined: 26 Nov 2003 Posts: 151 Location: Grayson, GA
|
|
Posted: Fri Jul 18, 2008 7:34 pm |
|
|
Alright, without rewriting code I paid to use, how can I do a single read, with the Master, to get a value from the Slave, outside the interrupt routine? I am also using the Slave Select pin. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Sat Jul 19, 2008 5:25 am |
|
|
It is no big loss to throw away the SPI library code, and you will have the advantage of knowing exactly what is happening if you write your own code. But, OK, let's use the library code.
Initially, the master calls, for example,
setup_spi(spi_master |spi_l_to_h | spi_clk_div_16 );
and the slave calls:
setup_spi(spi_slave |spi_l_to_h | spi_clk_div_16 );
Now, before any SPI transaction takes place, the slave needs to load its buffer[10] into the SSPBUF register so that it will be sent back to the master the next time the master issues an SPI transaction. I think that spi_write(buffer[10]) will do that, even though the documentation says it generates 8 clocks, I think it only does that if you are the master.
Then the master issues an SPI transaction by lowering the output that goes to the SS input and calling
buffer[7] = spi_read(data);
This will send "data" to the slave and receive "buffer[10]" from the slave and put it in buffer[7]. (Raise the SS pin now.)
Now to get ready for the next SPI transaction, the slave needs to recognize that a transaction has already taken place. It can use the function spi_data_is_in(). When this function returns TRUE, then the slave can write another buffer[10] into the SSPBUF register using spi_write(). The use of spi_read(buffer[10]) by the slave is fairly useless because it hangs the slave indefinitely.
That's my best guess on how to use the library functions to accomplish SPI between a master and a slave. But if I were talking directly to the SPI registers, I would not have to guess. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
|