|
|
View previous topic :: View next topic |
Author |
Message |
The_Duck Guest
|
SPI slave mode not working on 18f4520 |
Posted: Sun Feb 08, 2009 10:47 pm |
|
|
Hi all,
I'm trying to get one-way SPI communication working between two PIC 18f4520's and failing miserably. I'd appreciate any help you guys can give. I have a master and slave running the following code. The slave fails to receive almost all the messages sent by the master, though occasionally a byte of the form <some zeros><some ones> (like 0b00111111) will make it through.
I have hooked an oscilloscope up to the master's clock and data outputs and the waveforms look exactly like what I expect, given what I have read about SPI. Interestingly, however, if I use mode 0 or mode 2, the master doesn't give any output on the data line (clock output is still fine)! Only mode 1 and mode 3 seem to work; this confuses me because the 18f4520 data sheet claims that all 4 SPI modes are supported. The oscilloscope also shows the slave select line working as intended (going low before a message and high again after a message).
I'm reasonably sure the wiring is correct, especially since the occasional message makes it through to the slave. I'm confused as to how the slave can simply fail to receive most of the messages--doesn't that mean it must be seeing less than 8 clock pulses before it's deselected? How can that be? And why do only certain forms of messages make it through? Why is 0b00001111 sometimes received while 0b10101010 is never received?
Is there anything wrong with my code? Failing that, how can I debug this? This has caused a lot of frustration over the past few days.
Thanks for any help you can give.
Master code:
Code: | #include <18f4520.h>
#fuses HS,NOLVP,NOWDT,NOPROTECT
#use delay(clock=40000000)
#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)
#define SS_PIN PIN_B0
void main() {
unsigned int val;
setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_64);
output_high(SS_PIN);
val = 0; //val is the byte to send over SPI
while(true) {
delay_ms(100);
val += 1; //we cycle through all possible messages
//select the slave
output_low(SS_PIN);
delay_us(10);
spi_write(val); //send the message
output_d(val); //display what we're sending on some LEDs
//deselect the slave
delay_us(10);
output_high(SS_PIN);
}
} |
Slave code:
Code: | #include <18f4520.h>
#fuses HS,NOLVP,NOWDT,NOPROTECT
#use delay(clock=40000000)
#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() {
unsigned int val;
setup_spi(SPI_SLAVE | SPI_MODE_3);
while(true) {
if(spi_data_is_in()) {
val = spi_read();
output_d(val); //display what we got on some LEDs
}
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 09, 2009 12:56 am |
|
|
1. Post a list of SPI connections between the two PICs. Post the pin
numbers, not just the pin names. Post the package type that you're
using (DIP, TPQFP, etc.).
2. What is the distance between the two PICs ? Are they are on the
same board or different boards ? If two boards, is there is a ground
connection between the boards ?
3. What is the Vdd voltage for each PIC ? Does it come from a voltage
regulator or regulated power supply ?
4. Describe your oscillator circuit. What components are used ?
What frequency is specified on the components ?
5. Post your compiler version. |
|
|
The_Duck Guest
|
|
Posted: Mon Feb 09, 2009 1:37 am |
|
|
Disclaimer: the components are not in front of me right now so there may be inaccuracies below but I think I've got these right:
PCM programmer wrote: | 1. Post a list of SPI connections between the two PICs. Post the pin
numbers, not just the pin names. Post the package type that you're
using (DIP, TPQFP, etc.). |
Both master and slave are DIP packages. Here are the connections in the format master->slave:
RB0(33)->A5(7) [slave select]
RC3(17)->RC3(17) [clock]
RC5(24)->RC4(23) [master output, slave input]
RC4(23)->RC5(24) [master input, slave output (not used)]
PCM programmer wrote: | 2. What is the distance between the two PICs ? Are they are on the
same board or different boards ? If two boards, is there is a ground
connection between the boards ? |
They're on separate boards connected by a few inches of wire. The grounds are connected.
PCM programmer wrote: | 3. What is the Vdd voltage for each PIC ? Does it come from a voltage
regulator or regulated power supply ? |
Both are being supplied 5V from separate identical regulated power supplies.
PCM programmer wrote: | 4. Describe your oscillator circuit. What components are used ?
What frequency is specified on the components ? |
It's a 40MHz crystal oscillator supplied 5V and connected to pin 13 of the PIC. The oscillator is a CTX748-ND or something very similar.
I don't understand how the oscillator works; the PIC boards were assembled from instructions. I believe the timers and such work as expected for a 40MHz oscillator--I think this part of the circuit is fine.
PCM programmer wrote: | 5. Post your compiler version. |
I'm pretty sure it's 4.041. |
|
|
Ttelmah Guest
|
|
Posted: Mon Feb 09, 2009 8:34 am |
|
|
A few comments:
Change your oscillator fuse to EC. HS should work, but will result in significantly more power consumption. Basically, with HS selected, the incoming clock signal, is amplified, and echoed 'out' on the second clock pin. The ampliflier here is only rated to 25MHz, and it's consumption rises as it is clocked faster. Use the correct fuse, rather than 'pushing' the incorrect setting...
Second, try adding a line to disable the comparator. This is multiplexed with the SS pin, and might cause a problem.
What smoothing have you got _close_ to the PICs?. A surprising number of PIC problems result from noise at the PIC supply, especially at higher frequencies.
What silicon revision, are your 4520's?. If these are early chips (the A1 revision), they have probably the largest set of errata for the MSSP, of any PIC ever launched....
Are you sure that the MCLR pin is properly pulled up?. What you describe could result if this was floating.
Best Wishes |
|
|
The_Duck Guest
|
|
Posted: Mon Feb 09, 2009 1:10 pm |
|
|
Ttelmah wrote: | A few comments:
Change your oscillator fuse to EC. HS should work, but will result in significantly more power consumption. Basically, with HS selected, the incoming clock signal, is amplified, and echoed 'out' on the second clock pin. The ampliflier here is only rated to 25MHz, and it's consumption rises as it is clocked faster. Use the correct fuse, rather than 'pushing' the incorrect setting...
Second, try adding a line to disable the comparator. This is multiplexed with the SS pin, and might cause a problem.
What smoothing have you got _close_ to the PICs?. A surprising number of PIC problems result from noise at the PIC supply, especially at higher frequencies.
What silicon revision, are your 4520's?. If these are early chips (the A1 revision), they have probably the largest set of errata for the MSSP, of any PIC ever launched....
Are you sure that the MCLR pin is properly pulled up?. What you describe could result if this was floating.
Best Wishes |
The power supply plugs into an adapter just an inch or two from the PIC pins it's connected to, and there's no other load on the supply except for I guess the oscillator? I put an oscilloscope across pins 11 and 12 (Vdd and Vss) and it looks pretty steady. I've no experience with power noise so I'm not sure what I would be looking for here.
There's a little circled "B3" on the PIC packages--I guess that's the revision?
Pin 1 (MCLR) is high.
I changed the HS fuse to EC on both master and slave, and I added lines to disable the comparator and the ADC on the slave, but to no avail--I'm getting the exact same behavior.
Code: | setup_comparator(NC_NC_NC_NC);
setup_adc_ports(NO_ANALOGS); |
I appreciate the help--is there anything else I can try? |
|
|
Ttelmah Guest
|
|
Posted: Mon Feb 09, 2009 1:33 pm |
|
|
Being plugged in close to the PIC, is _not_ good enough. You need a small (something like 0.1uF) decoupling capacitor, with good HF performance really close to the PIC pins. HF problems will not be visible on a typical scope. I am talking about switching transients of a few nSec.
Put capacitors onto the PICs.
Best Wishes |
|
|
Guest
|
|
Posted: Mon Feb 09, 2009 2:29 pm |
|
|
Ttelmah wrote: | Being plugged in close to the PIC, is _not_ good enough. You need a small (something like 0.1uF) decoupling capacitor, with good HF performance really close to the PIC pins. HF problems will not be visible on a typical scope. I am talking about switching transients of a few nSec.
Put capacitors onto the PICs.
Best Wishes |
Oh! In fact there is a 1uF capacitor between pins 31 and 32 (which are the same as 12 and 11). |
|
|
Guest
|
|
Posted: Sun Mar 01, 2009 8:33 am |
|
|
hi, the_duck
i have the same behavior between 2 16f877a.
do you solve this riddle??? |
|
|
The_Duck Guest
|
|
Posted: Tue Mar 10, 2009 12:44 pm |
|
|
It got a lot better when instead of doing
Code: | while(true) {
if(spi_data_is_in()) {
val = spi_read();
}
} |
I used
Code: | while(true) {
val = spi_read(0);
} |
but it still wasn't perfect. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|
|
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
|