|
|
View previous topic :: View next topic |
Author |
Message |
domdom
Joined: 06 Sep 2006 Posts: 29
|
SPI master and slave |
Posted: Mon Mar 19, 2007 3:29 am |
|
|
I have two pics 16f877a. i am trying to communicate them with spi.
But the code seems not working. Below are my code for master and slave
master_spi.c
Code: |
#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOPUT,NOBROWNOUT
#use delay(clock=20000000)
#endif
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7)
#zero_ram
#define slave_cs PIN_A5
#define slave_time 100
//function
int readslave(void);
void main(void)
{
//variable defination
int data;
//configure pin direction, port x,pin 7 -- pin 0; 1 as input, 0 as output
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
set_tris_a(0b00000000);//RC5/SDO = 0(output)
set_tris_b(0b00000000);//RC4/SDI = 1(input)
set_tris_c(0b00001000);//RC3/SCK=0(output)
set_tris_d(0b00000000);//RA5/SS=0(Output)
set_tris_e(0b00000000);
//trist port before run
//Initially set all spi chip selects to disable
output_high(slave_cs);//cs is active low
//setup the spi port
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
while(1)
{
data=readslave();
printf("This is the data from slave: %d\n",data);
delay_us(100);
}
return;
}
int readslave(void)
{
int slavedata;
output_low(slave_cs); //select the slave to begin aquisition of data from external source
delay_us(slave_time);//wait and delay
slavedata = spi_read(0);//aquire the data from slave by sending out a clock
output_high(slave_cs);//disable the slave
return slavedata;
}
|
slave_spi.c
Code: |
#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOPUT,NOBROWNOUT
#use delay(clock=20000000)
#endif
#zero_ram
#byte PORTA = 5
#define slave_cs PIN_A5
void main(void)
{
//variables
int slavedata;
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
set_tris_a(0b00100000);//RC5/SDO = 0(output)
set_tris_b(0b10000000);//RC4/SDI = 1(input)
set_tris_c(0b00011000);//RC3/sck = 1(input)
set_tris_d(0b00000000);//RA5 = 1(input)
set_tris_e(0b00000000);
//portd = 0 --- as input
//setup the spi port
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_4);
while(1)
{
if(input(slave_cs)==0)
{
slavedata = PORTA;
spi_write(slavedata);
}
else
{
delay_cycles(1);
}
}
return;
}
|
I suppose my window hyperterminal going to display something. but end up nothing . Appreciate if someone can point out my error. |
|
|
mskala
Joined: 06 Mar 2007 Posts: 100 Location: Massachusetts, USA
|
|
Posted: Mon Mar 19, 2007 9:57 am |
|
|
A few things:
1) 'SPI_CLK_DIV_4' is not supposed to be used for slave since slave doesn't generate the clock.
2) You are using the hardware SS pin, so you cannot toggle this pin by hand and check for it on the slave. This will happen automatically when setup_spi() is done.
3) But mainly, it doesn't look like you understand what SPI transactions are. When the clocking occurs, whatever the master is sending is clocked to the slave, and at the exact same time whatever is in the slave's buffer is clocked to the master. So if you want to send the slave something and command it to return data to you related to the command, you need two transactions.
Do a search, there was some standard code in an earlier thread. |
|
|
domdom
Joined: 06 Sep 2006 Posts: 29
|
|
Posted: Tue Mar 20, 2007 7:39 am |
|
|
Sorry, i just new to pic.
So in short
I just need to remove the
Code: |
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_16);
|
to
Code: |
setup_spi(SPI_SLAVE | SPI_L_TO_H);
|
|
|
|
mskala
Joined: 06 Mar 2007 Posts: 100 Location: Massachusetts, USA
|
|
Posted: Tue Mar 20, 2007 11:13 am |
|
|
No there is more to do than that. Don't do anything with the SS pin after setting up SPI, that will be used automatically.
For example, if you know what you want to send from slave to master always, you could use this for slave:
Code: |
int8 dummy;
int8 value_to_send;
value_to_send=0xAA; // or whatever
while (1) {
dummy=spi_read(value_to_send); // This waits for master to send clocks
}
|
With this code the slave will wait and not do anything else.
If SSP interrupt is enabled, you don't have to wait around, _BUT_ realize that the interrupt happens _after_ the transaction, so you must load the slave's buffer beforehand. Others on this board showed me these:
Code: |
#if define (__PCH__)
#byte SSPBUF = 0xFC9
#byte SSPCON = 0xFC6
#byte I2CBUF = 0xFC8
#byte SSPSTAT = 0xFC7
#else
#byte SSPBUF = 0x13
#byte SSPCON = 0x14
#byte I2CBUF = 0x93
#byte SSPSTAT = 0x94
#endif
// Now the SSP handler code.
#DEFINE READ_SSP() (SSPBUF)
#DEFINE WAIT_FOR_SSP() while((SSPSTAT & 1)==0)
#DEFINE WRITE_SSP(x) SSPBUF=(x)
#DEFINE CLEAR_WCOL() SSPCON=SSPCON & 0x3F
|
If you load the buffer
Code: |
WRITE_SSP(value_to_send);
|
Then your interrupt will happen and tell you that it was sent, and you can load the buffer again with something else for next time. |
|
|
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
|