|
|
View previous topic :: View next topic |
Author |
Message |
Macro
Joined: 10 Jun 2004 Posts: 9 Location: Huntsville, Al
|
|
|
Ttelmah Guest
|
Re: comunicating between two PICs using SPI |
Posted: Fri Jul 23, 2004 10:25 am |
|
|
If the signal is only changing by 0.5v, you need to look again at the wiring. The signals should be good solid logic lines. Disable the master, and see if the line can be pulled high/low by you with somthing like a 4K resistor. If it is resistant to moving, then it is the slave that has the problem. Once you find what is wrong in the hardware, the normal problem with SPI, is speed.
If (for instance), you send a byte to the slave, and receive back whatever was left in the register at this point, then send a second byte, expecting to see a reply, there is a major problem in the time needed. The slave, has to load the 'reply' byte into the output register, before the second transmission starts. The interrupt latency, will depend on what other routines are in use, but on the larger chips, can be as much as perhaps 50 instruction times, from the point where the first byte finishes bing 'sent', to where the reply byte is ready, and worse than this if any other interrupt handlers are present...
The CCS SSP routines, are also not laid out to 'help' with handling waiting for the events efficiently. In the past I have used:
Code: |
#byte SSPBUF = 0xFC9
#byte SSPCON = 0xFC6
#byte SSPSTAT = 0xFC7
#bit SSPREADY=SSPSTAT.0
#bit WCOL=SSPCON.7
#DEFINE READ_SSP() (SSPBUF)
#DEFINE WAIT_FOR_SSP() while(!SSPREADY)
#DEFINE WRITE_SSP(x) SSPBUF=(x)
#DEFINE CLEAR_WCOL() WCOL=0
/* Launch - Used to 'launch' communications */
void ssp_launch(int txt,int mode)
{
int loop;
while (true)
{
/* I loop till the slave responds to the header with a correct reply */
/* This triggers the SPI transmission */
WRITE_SSP(0xAA);
WAIT_FOR_SSP();
loop=READ_SSP(); //Garbage
delay_cycles(80);
/* This ensures the slave has time to enter the interrupt service routine */
WRITE_SSP(mode+txt);
/* At this point the slave should have responded with '55' */
WAIT_FOR_SSP();
/* Since I clocked the write, the character should be waiting for me */
/* I delay in this routine before actually reading, to allow the other end to get ready for the next transfer */
if (READ_SSP()==0x55) break;
}
delay_cycles(30);
}
|
The slave, as soon as it enters the interrupt routine, puts '0x55' into the output register, and then looks at the 'instruction' sent from the master, and puts the first required byte into the output register (the 30uSec delay allows this). the master does not start sending it's data block (and receiving), from the slave, till it sees the '0x55' byte. The slave allways finishes it's packets, with a '0' terminator, so '55' cannot be seen back accidentally. The rate that is required, makes it very difficult to d interrupt driven slave handling (in my case, once the slave is in the 'handler', it stays in the routine for the entire block transfer - normally 16 bytes - it has the memory address worked out for the transfer, just uses 'wait_for_ssp', and as soon as a byte is received, loads the next byte, and processes the received one - this allows the whole transfer to be quite fast once the communication is established).
The shear 'time' involved, is much larger than you expect. The 80cycle delay, allows in my case, the slave to just be ready, if it was in my 'main' routine. However if it was in a serial interrupt handler, the loop will execute twice before the handler starts...
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Jul 23, 2004 11:26 am |
|
|
If the signal of your clock line is not changing at the 0 to 5V levels, then this indicates a hardware problem and not some SPI related problem. Which pins are you using? Very likely one of these pins has an open collector output. |
|
|
Macro
Joined: 10 Jun 2004 Posts: 9 Location: Huntsville, Al
|
Re: comunicating between two PICs using SPI |
Posted: Mon Jul 26, 2004 10:04 am |
|
|
Ttelmah wrote: |
If the signal is only changing by 0.5v, you need to look again at the wiring. The signals should be good solid logic lines. Disable the master, and see if the line can be pulled high/low by you with something like a 4K resistor. If it is resistant to moving, then it is the slave that has the problem. |
I tried this and I was not able to pull the SCK line high using a 10K resistor when slave program is running. So the slave is the problem, what should I try next?
ckielstra wrote: |
If the signal of your clock line is not changing at the 0 to 5V levels, then this indicates a hardware problem and not some SPI related problem. Which pins are you using? Very likely one of these pins has an open collector output. |
Master pins (18F8720 page 5):
pin 44 - RC3/SCK/SCL
pin 45 - RC4/SDI/SDA
pin 46 - RC5/SDO
Slave pins (18F2431 page 4):
pin 15 - RC4/INT1/SDI/SDA
pin 16 - RC5/INT2/SCK/SCL
pin 18 - RC7/RX/DT/SDO
I was unable to find anything in either datasheet about "open collector". How to I find out if a pin has an open collector output? _________________ David Adams |
|
|
Ttelmah Guest
|
Re: comunicating between two PICs using SPI |
Posted: Mon Jul 26, 2004 10:44 am |
|
|
Macro wrote: | Ttelmah wrote: |
If the signal is only changing by 0.5v, you need to look again at the wiring. The signals should be good solid logic lines. Disable the master, and see if the line can be pulled high/low by you with something like a 4K resistor. If it is resistant to moving, then it is the slave that has the problem. |
I tried this and I was not able to pull the SCK line high using a 10K resistor when slave program is running. So the slave is the problem, what should I try next?
ckielstra wrote: |
If the signal of your clock line is not changing at the 0 to 5V levels, then this indicates a hardware problem and not some SPI related problem. Which pins are you using? Very likely one of these pins has an open collector output. |
Master pins (18F8720 page 5):
pin 44 - RC3/SCK/SCL
pin 45 - RC4/SDI/SDA
pin 46 - RC5/SDO
Slave pins (18F2431 page 4):
pin 15 - RC4/INT1/SDI/SDA
pin 16 - RC5/INT2/SCK/SCL
pin 18 - RC7/RX/DT/SDO
I was unable to find anything in either datasheet about "open collector". How to I find out if a pin has an open collector output? |
They don't.
This would only apply with soft SPI. Also if this was th problem, the resistor would still pull the input up fine.
You are aware that the SDO pin on one chip needs to connect to the SDI pin on the other (only the clock connects directly)?. The behaviour you are describing would be exactly what I'd expect if SDO was connected to SDO, instead of SDI. The lines 'cross over' between the chips.
Are you using 'fast_io' in the code?. If so, how are you setting the TRIS register for the pins?.
Best Wishes |
|
|
Macro
Joined: 10 Jun 2004 Posts: 9 Location: Huntsville, Al
|
Re: comunicating between two PICs using SPI |
Posted: Mon Jul 26, 2004 12:36 pm |
|
|
Ttelmah wrote: | They don't.
This would only apply with soft SPI. Also if this was th problem, the resistor would still pull the input up fine.
You are aware that the SDO pin on one chip needs to connect to the SDI pin on the other (only the clock connects directly)?. The behaviour you are describing would be exactly what I'd expect if SDO was connected to SDO, instead of SDI. The lines 'cross over' between the chips.
Are you using 'fast_io' in the code?. If so, how are you setting the TRIS register for the pins?.
Best Wishes |
I used this as my guide to wire up the SPI and I was careful to make sure the master SDO was connected to the slave SDI and the master SDI was connected to the slave SDO. I thought I might have messed up the wiring so I tried swapping the SDO and SDI on the slave side but that didn't work. As for 'fast_io' I have not tried to use it yet. The only setup I'm doing for the chips is:
setup_spi(spi_master | spi_l_to_h | spi_clk_div_64 ); // for the master
setup_spi(spi_slave | spi_l_to_h ); // for the slave
I called Microchip and they thought that my problem most likely software related but they also suggested that I use a 4.7K resistor to pull up the SCK line (which had no effect). They also said I should be able to see a clock pulse when the master SCK is not connected to slave, which I cannot see. When the master is running and the slave in not connected all I see is a constant voltage (~.8V) on the SCK line.
If this is a hardware problem, what should I try next? _________________ David Adams |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Mon Jul 26, 2004 1:10 pm |
|
|
How about writing a simple program to toggle the clock and data lines. That will tell you if the lines are stuck from a hardware fault. Toggle them from low to high Z to exercise the pull-up resistors. Toggle one at a time to be sure they are not shorted together.
If they move under direct software control the problem must be your SPI software. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
Ttelmah Guest
|
Re: comunicating between two PICs using SPI |
Posted: Mon Jul 26, 2004 2:37 pm |
|
|
Macro wrote: | Ttelmah wrote: | They don't.
This would only apply with soft SPI. Also if this was th problem, the resistor would still pull the input up fine.
You are aware that the SDO pin on one chip needs to connect to the SDI pin on the other (only the clock connects directly)?. The behaviour you are describing would be exactly what I'd expect if SDO was connected to SDO, instead of SDI. The lines 'cross over' between the chips.
Are you using 'fast_io' in the code?. If so, how are you setting the TRIS register for the pins?.
Best Wishes |
I used this as my guide to wire up the SPI and I was careful to make sure the master SDO was connected to the slave SDI and the master SDI was connected to the slave SDO. I thought I might have messed up the wiring so I tried swapping the SDO and SDI on the slave side but that didn't work. As for 'fast_io' I have not tried to use it yet. The only setup I'm doing for the chips is:
setup_spi(spi_master | spi_l_to_h | spi_clk_div_64 ); // for the master
setup_spi(spi_slave | spi_l_to_h ); // for the slave
I called Microchip and they thought that my problem most likely software related but they also suggested that I use a 4.7K resistor to pull up the SCK line (which had no effect). They also said I should be able to see a clock pulse when the master SCK is not connected to slave, which I cannot see. When the master is running and the slave in not connected all I see is a constant voltage (~.8V) on the SCK line.
If this is a hardware problem, what should I try next? |
Remove both chips, and verify that the lines do not connect to anything else!...
However a really good session with the DVM, should allow this to be checked. I must admit, I'd be most suspicious of a solder whisker, or some similar problem.
Write a simple program for the slave, that gets rid of the SPI initialisation, and has something like:
#use fast_io(c)
and in the start of the main function, have:
set_tris_d(0xFF);
This will turn the entire port to input.
Then on the master, try:
#use fast_io(c)
and code something like:
int count;
set_tris_d(0);
while (true) {
for (count=0,count<255;count++) {
output_c(count);
delay_us(2);
}
}
Then a scope should show a set of square waves on C0 to C7, with the frequency of each, half that of the one below. If any waveform is distorted, or missing, there is a hardware problem on this line. If some pins are conncted to other hardware, you would need to mask them off (change the value used in the TRIS).
Best Wishes |
|
|
Macro
Joined: 10 Jun 2004 Posts: 9 Location: Huntsville, Al
|
|
Posted: Tue Jul 27, 2004 9:52 am |
|
|
SherpaDoug wrote: | How about writing a simple program to toggle the clock and data lines. That will tell you if the lines are stuck from a hardware fault. Toggle them from low to high Z to exercise the pull-up resistors. Toggle one at a time to be sure they are not shorted together.
If they move under direct software control the problem must be your SPI software. |
Thanks for the idea, I tried this exercise and it worked perfectly on all three lines.
Ttelmah wrote: | Remove both chips, and verify that the lines do not connect to anything else!...
However a really good session with the DVM, should allow this to be checked. I must admit, I'd be most suspicious of a solder whisker, or some similar problem.
|
I thought it might be a wire problem but I removed all unnecessary wires yesterday and checked for solder whiskers but I couldn't find any.
I also tried your code with slight modification (set_tris_c instead of set_tris_d). All the lines that I'm using (RC3, RC4, RC5) worked properly with your test.
I also checked the values of the SSPSTAT, SSPCON1, and TRISC registers and they were as follows:
SSPSTAT: 00000000
Input data sampled at middle of data output time
Transmit occurs on transition from idle to active clock state
receive not complete, SSPBUF is empty
SSPCON1: 00100010
SPI master mode, clock = Fosc/64
Idle state for clock is a low level
Enables serial port and configures SCK, SDO, SDI, and SS as serial port pins
TRISC: 11010111
From what I've read from the 18F8720 datasheet those are the correct settings for those registers but I still cannot see a clock pulse when the master is not connected to the slave. _________________ David Adams |
|
|
Macro
Joined: 10 Jun 2004 Posts: 9 Location: Huntsville, Al
|
Master working |
Posted: Tue Jul 27, 2004 1:48 pm |
|
|
I was able to get the master working alone using this code:
setup_spi(spi_master | spi_l_to_h | spi_clk_div_64 );
while(true)
{
byte2 = spi_read(21); //start swapping bytes
delay_us(50);
}
I was able to see the clock and the SDO acting properly. When I hooked it up to the slave, the SDO line stayed correct but the clock was knocked down to a 0-1V scale. I looked into the TRISC register on the slave and compared it to the 18F2431 datasheet. The port C values (0xDF) were exactly what the document said they would be,
"*SDI must have TRISC<4> set
*SDO must have TRISC<5> cleared
*SCK (Slave mode) must have TRISC<3> set (edit: corrected)"
Unfortunately, the pin diagram contradicts that statement. The pin diagram says that the pin 15 is "RC4/INT1/SDI/SDA", pin 16 is "RC5/INT2/SCK/SCL", and pin 18 is "RC7/RXDT/SDO". That explains why the clock was always being pulled down. The clock pin on the slave was always configured as an output not as an input. I then tried wiring the slave like the TRISC comment said to, which also did not work. I also tried changing the value in TRISC to (7F) which stopped the clock from being pulled down. So now I have the master properly outputting the clock and the SDO to the slave but no response from the slave (constant 5V). _________________ David Adams
Last edited by Macro on Tue Jul 27, 2004 2:17 pm; edited 1 time in total |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Tue Jul 27, 2004 2:07 pm |
|
|
Put this is the slave
Code: |
While(1)
{ x = spi_read(0xAA);
}
|
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Jul 27, 2004 2:10 pm |
|
|
Your statement:
Quote: |
"*SDI must have TRISC<4> set
*SDO must have TRISC<5> cleared
*SCK (Slave mode) must have TRISC<3> cleared"
|
From the datasheet:
Quote: |
• SDI must have TRISC<4> set
• SDO must have TRISC<5> cleared
• SCK (Master mode) must have TRISC<3>
cleared
• SCK (Slave mode) must have TRISC<3> set
• SS must have TRISA<5> set and ADCON must
be configured such that RA5 is a digital I/O |
As you already stated, this section of the datasheet is wrong. The registers given are the more commonly ones used in the other PICs like say PIC18Fxx2's. |
|
|
Ttelmah Guest
|
|
Posted: Tue Jul 27, 2004 3:01 pm |
|
|
Mark wrote: | Your statement:
Quote: |
"*SDI must have TRISC<4> set
*SDO must have TRISC<5> cleared
*SCK (Slave mode) must have TRISC<3> cleared"
|
From the datasheet:
Quote: |
• SDI must have TRISC<4> set
• SDO must have TRISC<5> cleared
• SCK (Master mode) must have TRISC<3>
cleared
• SCK (Slave mode) must have TRISC<3> set
• SS must have TRISA<5> set and ADCON must
be configured such that RA5 is a digital I/O |
As you already stated, this section of the datasheet is wrong. The registers given are the more commonly ones used in the other PICs like say PIC18Fxx2's. |
This is the sort of thing that can give anybody headaches!.
For instance, on the 18Fxx2, when dealing with the UART, the TRIS settings, have to differ between operating on the MicroChip ICE, and the real chips. The ICE follows the data sheet, while the real chip reverses the TRIS settings for these bits...
Looking at both the data sheets for other chips, and the 'errata' entries for similar chips often shows the problem. I'd suspect the CCS code, is following the data sheet, and has not been tested on these chips, and would suggest going 'DIY' on the SPI routines on the receiver, and trying the different possibilities with the TRIS register, and seeing what happens.
Best Wishes |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Jul 27, 2004 5:34 pm |
|
|
Quote: |
For instance, on the 18Fxx2, when dealing with the UART, the TRIS settings, have to differ between operating on the MicroChip ICE, and the real chips. The ICE follows the data sheet, while the real chip reverses the TRIS settings for these bits...
|
Could you explain this a bit more. Are you talking about RC6 and RC7? I use the 252's and 452's with and ICE2000 and ICD2 and don't remember having to do anything different. |
|
|
Macro
Joined: 10 Jun 2004 Posts: 9 Location: Huntsville, Al
|
|
Posted: Wed Jul 28, 2004 10:01 am |
|
|
Neutone wrote: | Put this is the slave
Code: |
While(1)
{ x = spi_read(0xAA);
}
|
|
Using that code on the slave and changing TRISC to 0x7F I was able to get the value of 'x' to be the value the master sent over. Unfortunately, the slave is still not outputting anything (constant 5V). _________________ David Adams |
|
|
|
|
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
|