View previous topic :: View next topic |
Author |
Message |
Hanzala Hussain
Joined: 10 Apr 2008 Posts: 2
|
SPI |
Posted: Thu Apr 10, 2008 2:49 am |
|
|
How can I interface two 16F877A through SPI? |
|
|
Matro Guest
|
|
Posted: Thu Apr 10, 2008 3:12 am |
|
|
Connect SCK of both together, and SDI of each with SDO of the other.
Choose which part is the master and which one is the slave.
That's done.
Matro. |
|
|
Guest
|
|
Posted: Thu Apr 10, 2008 7:48 am |
|
|
I'm doing exactly the same, making a bidirectional link and have made these connections.
Is it then a case of simply using spi_read() and spi_write()? Are there any good intro websites to SPI that apply to CCS c code? |
|
|
Matro Guest
|
|
Posted: Thu Apr 10, 2008 8:07 am |
|
|
Basically, just a correct and appropriate use of spi_write() and spi_read() is enough to make both PIC communicate.
No idea for a website...
Matro. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Apr 10, 2008 8:14 am |
|
|
Also have a look at the CCS provided example files: Quote: | EX_SPI.C
Communicates with a serial EEPROM using the H/W SPI module
EX_SPI_SLAVE.C
How to use the PIC's MSSP peripheral as a SPI slave. This example will talk to the ex_spi.c
example. |
|
|
|
Hanzala Hussain
Joined: 10 Apr 2008 Posts: 2
|
|
Posted: Thu Apr 10, 2008 9:16 am |
|
|
This is the code I am trying but not getting the desired result on both ends(both on master and slave)
Code: |
// I ma using
//RC6 = clock
//RC5 = Data out
//RC4 = Data in
//for both master as well as slave.
// Master Program
#include <16F877A.h>
#fuses NOWDT,NOPROTECT,XT,NOLVP,PUT
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
int8 data = 0;
void main()
{
setup_spi( SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 );
while(1)
{
spi_write(0x01);
If(!spi_data_is_in());
data = spi_read();
printf("\n\rdata = %u",data);
}
}
|
//SLAVE program
#include <16F877A.h>
#fuses NOWDT,NOPROTECT,XT,NOLVP,PUT
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
int8 value = 0;
void main( )
{
setup_spi( SPI_SLAVE | SPI_L_TO_H | SPI_SS_DISABLED );
output_high( PIN_C4 );
while( 1 )
{
if (!spi_data_is_in());
value = spi_read( );
spi_write(0x55);
printf( "\n\r data = %u", value );
}
}
Help me |
|
|
Guest
|
|
Posted: Thu Apr 10, 2008 9:30 am |
|
|
Yep, that's what I came up with, and mine doesn't work either!
Do we need to toggle a CS pin and poll for that change?
The reciever (master)
while(true)
{
printf("\tWaiting for data .. \n\r");
delay_ms(1000);
if(spi_data_is_in())
{
printf("\tData here!\n\r");
data_in = spi_read();
printf("%c\n\r", data_in);
}
}
And the transmitter (slave)
while(true)
{
printf("\tEnter character:\n\r");
while(flag == 0)
{
delay_us(1); //wait for user
}
printf("\t%c\n\r", data_in);
printf("\tWriting .. \n\r");
spi_write(data_in);
printf("\tDONE!\n\r");
delay_ms(20);
flag = 0;
}
}
#INT_EXT
void RS232_receive(void)
{
data_in = getc();
flag = 1;
} |
|
|
Matro Guest
|
|
Posted: Thu Apr 10, 2008 9:48 am |
|
|
You especially need a "#use spi" line to configure your SPI.
Add this line with correct parameters (report to help or reference manual) and it should be definitely better.
Matro. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Apr 10, 2008 11:02 am |
|
|
Matro wrote: | You especially need a "#use spi" line to configure your SPI.
Add this line with correct parameters (report to help or reference manual) and it should be definitely better. | #use spi is new in the v4 compilers. In the code above the older function setup_spi() is called which is less versatile but will do the job.
In the above code the main problem is in the master. Remember that in SPI data is being sent and received at the same time. So when the master sends a byte it will receive a byte at the same time, that's why calling the function spi_data_is_in() on the master makes no sense; after every transmission this function will return TRUE.
Another gotcha is that on the master you can call the spi_read() function in two different ways:
- With parameter: the passed value will be clocked out and the data received will be returned.
- Without parameter: returns the last received value. Note that no clock generated and it doesn't wait for a slave response !!
If you want to receive data from the slave but the master has nothing to send, then pass a dummy 0 value.
On a slave calling spi_read() without parameter will wait until a character is received.
The master code could then look something like: Code: | while(1)
{
spi_write(0x01); // Send command to slave
delay_ms(1); // Allow slave time to process the command
data = spi_read(0); // Get slave response. Note the dummy 0 parameter to generate the clock signal
printf("\n\rdata = %u",data);
delay_ms(1000);
} |
One remaining problem is that there is no mechanism present to detect synchronization problems. What will happen if the slave misses a byte? How to get it back in sync?
The easiest solution here is to implement a Chip Select signal which goes active at the start of communication and inactive when finished. The slave hardware does have this input. On the master you can choose any output pin and toggle it from software. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Apr 10, 2008 11:08 am |
|
|
Another problem: Make sure the master and slave use the same SPI mode configuration. Now the master uses SPI_H_TO_L and the slave SPI_L_TO_H. |
|
|
Guest
|
|
Posted: Fri Apr 11, 2008 2:34 am |
|
|
Thanks, will try today.
I'm used to assembly programming for the PIC, is there any way to know which registers are being set by CCS c-compiler function? The Microchip datahseets are excellent for an assembly programmer, I don't see the same detail for the compiler - it makes things less certain. |
|
|
Matro Guest
|
|
Posted: Fri Apr 11, 2008 2:37 am |
|
|
Look at the .lst file that is generated at compilation.
That is the ASM code produced by the compiler.
Matro. |
|
|
Guest
|
|
Posted: Fri Apr 11, 2008 2:45 am |
|
|
Yep, just found it. Thanks! |
|
|
|