|
|
View previous topic :: View next topic |
Author |
Message |
thibow
Joined: 11 Apr 2012 Posts: 30
|
2 PIC18 can't talk using SPI connection.. |
Posted: Wed Apr 11, 2012 5:33 pm |
|
|
Hello, I'm trying to setup a very basic SPI communication between 2 PIC 18LF2550. I am using PIC-C Compiler from CCS v4.114.
Pin A1 of both PICs are connected to a LED and pin A0 from the slave is also connected to a LED. The Master's LED is blinking every time I send a data (0x12), so it seems to send something every 500ms as asked. I want also the slave A1's pin to be toggled and the LED to blink every time something is in the buffer and read the data. So far everything works great, both LED are blinking synchronously.
However, where I get trouble is when I come to data sent. I send a '0x12' and I ask my slave to toggle pin A0 every time this particular value is received using a if. But it seems to never read this value.
and here are my files :
=========For the MASTER==========
Code: | #include <18F2550.H>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)
void main (void){
//configure the device to be a master, data transmitted on H-to-L clock transition
setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
enable_interrupts(global);
enable_interrupts(INT_SSP);
while(1){
spi_write(0x12);
delay_ms(500);
}
}
#int_SSP
Void Interruption(){
output_toggle(pin_A1);
} |
============For the SLAVE============
Code: | #include <18F2550.H>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)
int8 data;
void main (void){
//configure the device to be a master, data transmitted on H-to-L clock transition
setup_spi(spi_slave | spi_L_to_H );
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
enable_interrupts(global);
enable_interrupts(INT_SSP);
while(1){
while(!spi_data_is_in());
data=spi_read();
}
}
#int_SSP
Void Interruption(){
output_toggle(pin_A1);
if (data==0x12){
output_toggle(pin_A0);
}
} |
Master PIC uses an external 8Mhz Crystal clock.
I wired them like that :
MASTER-------------------------------SLAVE
18 SDO-------------------------------23 SDI
23 SDI-------------------------------18 SDO
22 SCK------------------------------- 22 SCK
according to this configuration :
If you have any guess.. Thank you ! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 11, 2012 6:45 pm |
|
|
Code: | setup_spi(spi_slave | spi_L_to_H );
|
You have the Slave Select enabled (by default) in the statement above,
but your Master code doesn't implement Slave Select, and you don't have
a wired connection for it between the two PICs.
It's recommended that you add the connection, and that you add code to
the Master to set SS low when you transmit a byte. (Set it high initially
in your setup code). |
|
|
thibow
Joined: 11 Apr 2012 Posts: 30
|
|
Posted: Wed Apr 11, 2012 7:11 pm |
|
|
Hello PCM Programmer, thank you very much for your help.
PCM programmer wrote: | Code: | setup_spi(spi_slave | spi_L_to_H );
|
You have the Slave Select enabled (by default) in the statement above,
but your Master code doesn't implement Slave Select, and you don't have
a wired connection for it between the two PICs.
|
I am sorry, I'm not sure to understand: I have the "spi_slave" only on Slave PIC, and the Master PIC has a "setup_spi(spi_master...)"
PCM programmer wrote: |
It's recommended that you add the connection, and that you add code to
the Master to set SS low when you transmit a byte. (Set it high initially
in your setup code). |
Do you mean that I should add "SPI_SS_DISABLED" from setup on both PICs ? I don't get it !
I should then add a wire between both PIC's pin 7 (SS) and set it high manually on start-up, (with output_HIGH(pin_A5); ) then set it low before writing and then high again ?
As there is no function in CCS I am not sure !
Thank you |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Wed Apr 11, 2012 7:44 pm |
|
|
thibow wrote: |
I should then add a wire between both PIC's pin 7 (SS) and set it high manually on start-up, (with output_HIGH(pin_A5); ) then set it low before writing and then high again ?
|
This is correct. You need to add a SS line and manually operate it. Use output_high() and output_low() |
|
|
thibow
Joined: 11 Apr 2012 Posts: 30
|
|
Posted: Wed Apr 11, 2012 8:37 pm |
|
|
Great, thank you, I will then try this (tomorrow) and tell you back if it works ! |
|
|
thibow
Joined: 11 Apr 2012 Posts: 30
|
|
Posted: Thu Apr 12, 2012 8:06 am |
|
|
I've just tried out and it's working ! My second led is blinking !
Thank you very much for your help ! |
|
|
thibow
Joined: 11 Apr 2012 Posts: 30
|
|
Posted: Thu Apr 12, 2012 11:23 am |
|
|
Little problem, I have tried to read, from the master, that's ok, but now I would like to read from the slave as well. I do read from the slave, but one out of 2 reading is wrong: here is the code
=====MASTER=========
Code: | #include <18F2550.H>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C5,bits=8,STOP=1)
void main (void){
//configure the device to be a master, data transmitted on H-to-L clock transition
setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
output_HIGH(pin_A5); // SS initialized
int8 data;
enable_interrupts(global);
enable_interrupts(INT_SSP);
while(1){
output_LOW(pin_A5);
printf("\n\r ecriture ");
spi_write(0x12);
output_HIGH(pin_A5);
delay_us(70);
output_LOW(pin_A5);
printf("\n lecture ");
data=spi_read();
output_HIGH(pin_A5);
delay_us(70);
printf("\n data :%d",data);
output_toggle(pin_A0);
delay_ms(500);
}
}
#int_SSP
Void Interruption(){
output_toggle(pin_A1);
printf("\n\r interrupt");
}
|
=====SLAVE========
Code: | #include <18F2550.H>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)
//#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C5,bits=8,STOP=1)
int8 data;
int i=1;
void main (void){
//configure the device to be a slave, data transmitted on H-to-L clock transition
setup_spi(spi_slave | spi_L_to_H );
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
enable_interrupts(global);
enable_interrupts(INT_SSP);
while(1){
}
}
#int_SSP
Void Interruption(){
data=spi_read();
output_toggle(pin_A1);
if (data==0x12){
spi_write(data+i);
output_toggle(pin_A0);
i++;
}
}
|
Output RS232
Code: | ecriture
interrupt
lecture
data :19
ecriture
interrupt
lecture
data :18
ecriture
interrupt
lecture
data :20
ecriture
interrupt
lecture
data :18
ecriture
interrupt
lecture
data :21
ecriture
interrupt
lecture
data :18
ecriture
interrupt
lecture
data :22
ecriture
interrupt
lecture
data :18 |
As you can see, there is a wrong reading 18, one out of 2 reading.. I can't figure out why.. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 12, 2012 11:37 am |
|
|
Quote: | #int_SSP
Void Interruption(){
output_toggle(pin_A1);
printf("\n\r interrupt");
}
enable_interrupts(global);
enable_interrupts(INT_SSP);
|
Get rid of the #int_ssp routine in the master code. Also get rid of the
lines that enable interrupts for INT_SSP and GLOBAL. You don't need
that routine on the master. And as a general comment, don't put code
that takes a long time to execute in an interrupt routine (such as the
printf statement).
Quote: |
void main (void){
setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
output_HIGH(pin_A5); // SS initialized
int8 data;
|
Don't declare variables within code in CCS. Always declare them at
the top of the function, first thing.
Quote: | output_LOW(pin_A5);
printf("\n lecture ");
data=spi_read();
output_HIGH(pin_A5);
delay_us(70); |
The master needs to generate a clock, in order to receive data from the
slave. To tell the master code to do this, you must put in a parameter in
the spi_read() function. Usually, a parameter of 0x00 is used. Edit your
code to add this parameter. Note: This is only needed in the master
code. Do not add the parameter to the spi_read() in your slave code
in the #int_ssp isr. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Thu Apr 12, 2012 11:51 am |
|
|
also
get into a habit of always adding 'errors' to the USE RS232(......) line.
When using the hardware UART , this will prevent the UART from 'hanging up'.
while you may not be using it in this program, sooner or later , you'll wonder WHY your code 'hangs' on serial input.....
it's second nature to me to always put 'errors' in |
|
|
thibow
Joined: 11 Apr 2012 Posts: 30
|
|
Posted: Thu Apr 12, 2012 12:12 pm |
|
|
Thank's a lot PCM Programmer, you were right, the interrupt messed everything.
I removed Master's interruption, this didn't change anything.. I then allowed a lot of time to the master between the write and read, to let the slave deal with his interruption and let the time to write to the master.. Unfortunately it didn't solve the problem..; Even if I left 1sec in between.
Then I have deleted Slave's interrupt, and do everything in the while loop, and it works the way it should.
One question though: I thought interruption were there to simplify everything, however, it seems not to be working the way it should, finally I won't use them at all.. Why isn't the PIC able to compare a received data and send a data in a 1sec interruption..
Here is the working code :
=====MASTER=====
Code: | #include <18F2550.H>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C5,bits=8,STOP=1)
signed int data;
void main (void){
//configure the device to be a master, data transmitted on H-to-L clock transition
setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
output_HIGH(pin_A5); // SS initialized
while(1){
output_LOW(pin_A5);
spi_write(0x12);
output_HIGH(pin_A5);
delay_ms(500);
data=spi_read();
printf("data :%d\r\n",data);
output_toggle(pin_A0);
output_toggle(pin_A1);
}
}
|
=====SLAVE=====
Code: | #include <18F2550.H>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)
signed int data;
signed int i=1;
void main (void){
//configure the device to be a slave, data transmitted on H-to-L clock transition
setup_spi(spi_slave | spi_L_to_H );
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
while(1){
while(!spi_data_is_in());
data=spi_read();
delay_us(100);
output_toggle(pin_A1);
if (data==0x12){
spi_write(data+i);
delay_us(100);
output_toggle(pin_A0);
i++;
}
}
}
|
=====output=====
Code: | data :19
data :20
data :21
data :22
data :23
data :24
data :25
data :26
data :27
data :28
data :29
... |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 12, 2012 12:21 pm |
|
|
You missed the last part of my post.
The master code needs to have the 0x00 parameter in the spi_read():
To temtronic:
He is using a software UART. The ERRORS statement doesn't do anything
on a software UART. It's ignored by the compiler. |
|
|
thibow
Joined: 11 Apr 2012 Posts: 30
|
|
Posted: Thu Apr 12, 2012 12:29 pm |
|
|
PCM Programmer, I tried to add 0x00 in spi_read() but it messed everything up, the output was:
Code: |
data: 0
data: 0
data: 0
data: -1
data: 0
data: 0
data: 0
data: -1
...
|
Plus, the master PIC should not be able to read what is sent to the slave, the master is never sent 18 by the slave..
There is something wrong with the buffer.. The master seems to be able to read in the slave's buffer.. it's weird |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Thu Apr 12, 2012 12:50 pm |
|
|
You didn't lower your SS pin when you did the read. If you are using SPI you MUST lower the SS line the entire time you are writing/reading to it. The typical transaction is:
lower SS
Write/read as many bytes as you expect
raise SS
You only lower/raise for the first byte (0x12), which is not correct. Without the SS line low, the slave device has no clue you are talking to it at all. SPI is setup to use multiple devices with the individual SS lines telling them which device is currently being talked to.
EDIT: As a note, interrupts do make things simpler. You just weren't using them as they are designed to be used. They are meant to signal to your main code that something happened so that you main code can address them at its leisure. You were tossing in print statements, which take a long time, into places where you are supposed to get in and then out really quickly. I'm not sure about SPI specifically, but most communications interrupts expect you to read the relevant buffer when they trigger. You weren't doing that in your slave interrupt at all (maybe one of the more experienced guys can comment on if that is required for SPI...it is for I2C and UART though if you use those interrupts). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
thibow
Joined: 11 Apr 2012 Posts: 30
|
|
Posted: Thu Apr 12, 2012 1:32 pm |
|
|
to Jeremiah, I tried just to have interrupt on master and use low/high ss for read and write, but I still have 2 answer..
in the slave :
Code: | #int_SSP
void Interruption(){
data=spi_read();
delay_us(100);
output_toggle(pin_A1);
if (data==0x12){
spi_write(data+i);
delay_us(100);
output_toggle(pin_A0);
i++;
}
} |
master:
Code: | while(1){
output_LOW(pin_A5);
spi_write(0x12);
output_HIGH(pin_A5);
delay_ms(500);
output_LOW(pin_A5);
data=spi_read();
output_HIGH(pin_A5);
printf("data :%d\r\n",data);
output_toggle(pin_A0);
output_toggle(pin_A1);
} |
output:
Code: | data :61
data :18
data :62
data :18
data :63
data :18
data :64
data :18
data :65
data :18
data :66
data :18 |
@PCM, I'll have a look thank you.. I really can't figure out what's happening, .. I'll give a shot using spi_read(0) and Low/high as well as some other modification ..
Last edited by thibow on Thu Apr 12, 2012 2:00 pm; edited 1 time in total |
|
|
|
|
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
|