CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SPI slave response

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tom.ayars



Joined: 23 Jun 2008
Posts: 14

View user's profile Send private message

SPI slave response
PostPosted: Thu Jul 17, 2008 10:52 am     Reply with quote

Can someone point me to an example of a master device sending data then waiting some time before the slave sends a response back to the master?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 17, 2008 11:26 am     Reply with quote

Typically this would be done by the master polling a status register
in the SPI slave. It waits until the "busy" bit goes low. Then the
master does a read to the slave's data register. Or, the slave might
also provide an interrupt to the master (on a dedicated \INT pin
coming from the slave and connected to the EXT INT pin on the master).
tom.ayars



Joined: 23 Jun 2008
Posts: 14

View user's profile Send private message

PostPosted: Thu Jul 17, 2008 11:40 am     Reply with quote

So the master would receive an interrupt saying there is data available in the slave's register and at that point the master would do a in=spi_read() and would the slave do a spi_write(data) or would it do a garbage=spi_read(data)?

thanks
Ttelmah
Guest







PostPosted: Thu Jul 17, 2008 1:09 pm     Reply with quote

When the master, writes to the slave, it receives _back_ the data already in the SPI data register on the slave PIC.
All actual transfers have to be performed by the master.
You write a byte into the slave data register, set a signal on the slave to say 'I have something to send', and when the master writes a byte to the slave (dummy byte), it receives back, the waiting byte.
You can do it without having a separate signal, by regularly 'polling' with the master, but using a line, gives the faster trigger.

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 17, 2008 2:27 pm     Reply with quote

You had a question about the difference between spi_write and spi_read
when used in slave code. To check this, make a test program:
Code:
#include <16F877.H>
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay (clock=4000000)
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

//=================================
void main()
{
setup_spi(SPI_SLAVE | SPI_MODE_0);

spi_read(0x55);

spi_write(0x55);

while(1);
}


Then look at the .LST file. Here's part of it:

Code:
... spi_read(0x55);
0026:  BCF    03.5
0027:  MOVF   13,W  // Read SSPBUF into W   
0028:  MOVLW  55
0029:  MOVWF  13  // Load SSPBUF with 0x55
002A:  BSF    03.5
002B:  RRF    14,W  // Rotate BF bit into CY
002C:  BTFSS  03.0  // Wait in loop until BF = 1
002D:  GOTO   02B
... 
... spi_write(0x55);
002E:  BCF    03.5
002F:  MOVF   13,W  // Read SSPBUF into W
0030:  MOVLW  55
0031:  MOVWF  13  // Load SSPBUF with 0x55
0032:  BSF    03.5
0033:  RRF    14,W  // Rotate BF bit into CY
0034:  BTFSS  03.0  // Wait in loop until BF = 1
0035:  GOTO   033
...
 

Conclusion: They do the same thing.

Here's the code where it puts the return value
into a variable. It does the same thing as above
but it also does a read of SSPBUF at the end.
Code:
... c = spi_read(0x55);
002E:  BCF    03.5
002F:  MOVF   13,W  // Read SSPBUF into W
0030:  MOVLW  55
0031:  MOVWF  13  // Load SSPBUF with 0x55
0032:  BSF    03.5
0033:  RRF    14,W  // Rotate BF bit into CY
0034:  BTFSS  03.0  // Wait in loop until BF = 1
0035:  GOTO   033

0036:  BCF    03.5
0037:  MOVF   13,W  // Read SSPBUF into W
0038:  MOVWF  21  // Put W into 'c' variable
tom.ayars



Joined: 23 Jun 2008
Posts: 14

View user's profile Send private message

PostPosted: Mon Jul 28, 2008 8:30 am     Reply with quote

Thanks for the help guys. I now have another question maybe one of you can help me with. I have a pic set up as a slave device on the line and a separate device acting as the master. I am using the spi_read() command inside the SSP interrupt and I am having success reading data coming in. The problem arises when I go to read from the MISO line on the other device, all I can see is 0xFF. I have hooked up a probe to the MISO line and can confirm this. Also, I look at the SSPBUF register and the data is there.

I guess my question is, what exactly is happening in the SSPSR shift register when I issue a spi_read() command that would cause me to only be able to see 0xFF on the MISO line?
Ttelmah
Guest







PostPosted: Mon Jul 28, 2008 8:52 am     Reply with quote

Nothing....
However, if you have glance at some other threads, you will find, that I am 'not alone', in preferring to use my own code, for the SPI. The CCS code, is poorly documented, with regards to how it does work, and unnecessarily complex, when using the SPI, especially in interrupt driven environments.
For myself, on a 18 chip, I use:
Code:

#byte   SSPBUF = 0xFC9
#byte   SSPCON = 0xFC6
#byte   SSPSTAT = 0xFC7
#bit BF = SSPSTAT.0
/* Now the SSP handler code. Using my own, since the supplied routines test the wrong way round for my needs */
#DEFINE READ_SSP()   (SSPBUF)
#DEFINE   WAIT_FOR_SSP()   while(!BF)
#DEFINE   WRITE_SSP(x)   SSPBUF=(x)
#DEFINE   CLEAR_WCOL()   SSPCON=SSPCON & 0x3F

In the interrupt handler, I can just use 'READ_SSP' at the start of the handler, when I want to read the SSPBUF register, and 'WRITE_SSP', when I want to load it.
One thing that could cause your problem though is just how slow the slave can be. The interrupt is only called once the byte has sent. The slave then takes typically perhaps about 40 instructions (even if it is not in another interrupt to actually 'reach' the handler. If the handler puts the read byte into a buffer, you can easily be talking another 20 to 30 instructions to do this, If yor byte you want to write back, itself comes from an array, you can easily be talking the same again, before it is actually loaded into the buffer register. Easily over 100 instruction times, before the master can start to clock data, and actually get back what is expected. If the slave is already in another interrupt, it gets even worse...
0xFF, is though an unusual combination. You would normally expect to get back the last byte transferred, even if it has been read. Are you sure something else is not changing the TRIS on the SPI line, or setting this high?.

Best Wishes
bright



Joined: 24 Apr 2011
Posts: 14

View user's profile Send private message

this is not a reply merely just a question
PostPosted: Tue May 03, 2011 1:44 pm     Reply with quote

PCM programmer I have seen the ccs program and also the assembly programs that you have posted, I have just 1 question from your assembly program for spi_write function, the last two lines don't they make this assembly code stay in an infinite loop. It is just that I have tried to use this function in my program and it seems as if when my program reaches this line it goes into an infinite loop, even took your code and simulated it with MPLAB SIM and it does the same thing.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 03, 2011 1:53 pm     Reply with quote

1. Post a very short test program that shows the problem. The program
should be 10 lines of code or less. It must compile without errors if
I copy and paste it into MPLAB.

2. Post your compiler version.

3. Post a description of how you know it's in an infinite loop.
What test are you doing, to prove that it happens ? Describe the test.
Describe the test setup (hardware board, RS-232 link to a terminal
program on the PC, etc.).
bright



Joined: 24 Apr 2011
Posts: 14

View user's profile Send private message

PostPosted: Tue May 03, 2011 2:14 pm     Reply with quote

This is the code I have written to test my spi if it works:
Code:

#include <16F690.H>
#use delay (clock=8000000)
 
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

//=================================
void main()
{
   setup_spi(SPI_SLAVE | SPI_MODE_0);
   spi_write(0x67);
   OUTPUT_BIT(PIN_C0, 1);
}

I am using the CCS_PICC_CP_4084 version.

To answer your third question, I went to debugger menu and then selected then went to select tool and then from there I chose the MPLAB SIM to check what happens to my code line by line, then I kept on pressing F7 on my keyboard to keep on moving from 1 line to another until I got to the line: spi_write(0x67); and then no matter how many times I pressed F7 it just stood there.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 03, 2011 2:43 pm     Reply with quote

I already explained that the SSP module is not simulated by MPSIM
in your previous thread, here:
http://www.ccsinfo.com/forum/viewtopic.php?t=45342

In case you don't believe me, or MPLAB help, here are some threads
on the Microchip forum that I just searched for, just now:
http://www.microchip.com/forums/m95266-print.aspx

Here is one post, near the end, where he suggests to set the BF bit
manually when using MPSIM:
http://www.microchip.com/forums/m492843-print.aspx
bright



Joined: 24 Apr 2011
Posts: 14

View user's profile Send private message

1 more question
PostPosted: Wed May 04, 2011 7:17 am     Reply with quote

I am sorry for being a nuisance but can I ask you 1 more question. If want to change few lines from the assembly code that you have given for spi_write function, how can I achieve that with the version I am using?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 04, 2011 11:53 am     Reply with quote

I assume you want to get rid of the test at the end of the spi_write() code.
You can do it as shown below. For a debugging session, just uncomment
the "#define DEBUG" line as show below. This will enable the macro
replacement for spi_write(), which is also shown below. This macro does
not have the test at the end. It only loads SSPBUF with a value. I think
this is what you want for your MPLAB simulator testing.

Just remember that when you're done running it in the simulator and
you're ready to test it in real hardware, to comment out the "#define
DEBUG" line, so the normal code will be put back in your program.
And re-compile it, of course.
Code:

#include <18F452.h>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)

#define DEBUG

#ifdef DEBUG
#byte SSPBUF = getenv("SFR:SSPBUF")
#define   spi_write(x) SSPBUF=(x)
#endif

//======================================
void main(void)
{

spi_write(0x55);

while(1);
}
bright



Joined: 24 Apr 2011
Posts: 14

View user's profile Send private message

PostPosted: Wed May 04, 2011 2:32 pm     Reply with quote

Ok thank you PCM programmer, you have been a great help.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group