CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

how to transmit data in spi slave mode?
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 2:27 am     Reply with quote

How much time this loop will take if I am running processor at 20Mhz? My controller is 18f252.
Code:

b0=GetByte(value1,0);
b1=GetByte(value1,1);
b2=GetByte(value1,2);
b3=GetByte(value1,3);
     
spi_write(b0);
spi_write(b1);
spi_write(b2);
spi_write(b3);


At the receiver side if I use interrupt then the data received in SSPBUF buffer. I have to save that data in a variable which takes some time, so how much delay is required between two spi_write commands in order that I can transfer data from SSPBUF to variable?
Ttelmah



Joined: 11 Mar 2010
Posts: 12622

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 2:51 am     Reply with quote

Impossible to answer. Speed depends on how fast you are clocking the SPI.
However, the 'GetByte' routine is horribly inefficient. Use 'make8', or a union instead. Using a pointer, and adding an offset to get a byte, takes perhaps about a dozen machine cycles. Make8, or the union, take just a couple....
Again impossible to answer about the receiver. Depends how fast it is clocking. Typically takes 30 instructions to get into the interrupt, and perhaps a handful (if the code is well written), to get the byte from the SSP register. Say 40 instructions. At 4MHz, 40uSec, but at 40Mhz, just 4.

Best Wishes
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 6:09 am     Reply with quote

make8 function works for int16 and int32 bits.how i can set it to work with floating numbers?
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 6:19 am     Reply with quote

union function is like that

Code:

union convert
    {
     int8 b[4];
     float fval;
    }
    val;
   
    val.fval=value1;
   
    b0=val.b[3];
    b1=val.b[2];
    b2=val.b[1];
    b3=val.b[0];
Ttelmah



Joined: 11 Mar 2010
Posts: 12622

View user's profile Send private message

PostPosted: Tue Mar 08, 2011 9:10 am     Reply with quote

Yes, I personally use, and prefer unions, since they are supported in other C's. However you can also get the same effect, and use 'make8', using the #byte directive.
Code:

float val;
int32 int_valversion;
#byte int_valversion=val;

val=1.2345;
make8(int_valversion,0);


This tells the compiler to put the int32 variable 'int_valversion', at the same location in memory, as 'val' - exactly the same thing that the union does, and then 'make8', returns the first byte of this. make32, can be used to go the other way.
If you check the .sym file, you will find the two variables are in the same memory location.

Best Wishes
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Wed Mar 09, 2011 2:57 am     Reply with quote

I tried to make a spi routine but unfortunately it is not working
Interrupt is not generating
here is my code

Master
Code:

#include <18f252.h>
#fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect                               
#use delay(clock=20000000)                               
#use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)

#define SSP_SS PIN_B5

#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)

float value1;
int b0,b1,b2,b3;

void main()
{
 output_high(SSP_SS);
 
 setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
 
 while(1)
 {
  value1=12.34;//value which has to be sent
  //break the floating value to seperate bytes and then send through SPI.
  {
   union convert
   {
    int data[4];
    float number;
   }
   val;
   
   val.number=value1;
   b0=val.data[3];
   b1=val.data[2];
   b2=val.data[1];
   b3=val.data[0];
  }
  output_low(SSP_SS);
  spi_write(b0);//sending first byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  output_low(SSP_SS);
  spi_write(b1);//sending 2nd byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  output_low(SSP_SS);
  spi_write(b2);//sending 3rd byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  output_low(SSP_SS);
  spi_write(b3);//sending 4th byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  delay_ms(500);//after 0.5 sec repeat the process again.
 }
}


Slave
Code:

#include <18f252.h>
#fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect                               
#use delay(clock=20000000)                               
#use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)

#byte SSPBUF = 0xFC9//register value for 18f252

#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)

int data[4],x=0,flag=0;
float recive;
int32 data32;

#int_ssp
void ssp_isr(void)
{
 data[x]=SSPBUF;
 x++;
 if(x>=4)
 {
  x=0;
  flag=1;
 }
}

void main()
{
 setup_spi(SPI_MASTER | SPI_MODE_0);
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
  if(flag==1)
  {
   data32=make32(data[0],data[1],data[2],data[3]);
   //function for making int32 to float
   {
    union convert
    {
     int32 y;
     float fval;
    }
    val;
    val.y=data32;
    recive=val.fval;
   }
   printf("%f\r\n",recive);//display the result.
   flag=0;
  }
 }
}


Give me some suggestions how it will work.
Ttelmah



Joined: 11 Mar 2010
Posts: 12622

View user's profile Send private message

PostPosted: Wed Mar 09, 2011 3:15 am     Reply with quote

First, shift your union declarations to the start of the function. C traditionally only allows declarations at the start of the functions. Latter versions allow them at the start of any code block. CCS, 'tries' to allow them inline to some extent, but they are much more reliable if you use the traditional declarations. The inline versions have a 'habit' of resulting in variables overlapping one another. So _keep to standard C syntax_.
Second, your slave SPI port, needs to be a slave, not a master. Something like:

setup_spi(SPI_MODE_0 | SPI_SS_ENABLED);

Since you are sending a slave select in the master.

Best Wishes
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Wed Mar 09, 2011 3:32 am     Reply with quote

Thanks Ttelmah
I compiled after your given suggestions but it gives me error at this line
Code:

setup_spi(SPI_MODE_0 | SPI_SS_ENABLED);


Quote:
Undefined identifier SPI_SS_ENABLED


Slave
Code:

#include <18f252.h>
#fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect                               
#use delay(clock=20000000)                               
#use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)

#byte SSPBUF = 0xFC9//register value for 18f252

#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)

int data[4],x=0,flag=0;
float recive;
int32 data32;


union convert
{
 int32 y;
 float fval;
}
val;
   

   
#int_ssp
void ssp_isr(void)
{
 data[x]=SSPBUF;
 x++;
 if(x>=4)
 {
  x=0;
  flag=1;
 }
}

void main()
{
 setup_spi(SPI_MODE_0 | SPI_SS_ENABLED);
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
  if(flag==1)
  {
   data32=make32(data[0],data[1],data[2],data[3]);
   //function for making int32 to float
   val.y=data32;
   recive=val.fval;
   printf("%f\r\n",recive);//display the result.
   flag=0;
  }
 }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 12622

View user's profile Send private message

PostPosted: Wed Mar 09, 2011 3:59 am     Reply with quote

Look in the 18F252.h, for the legal syntax. Unfortunately, CCS has the habit of changing their defines between compiler versions and chips. The default is for slave select to be enabled, so just using:

setup_spi(SPI_MODE_0 | SPI_SLAVE);

Should give slave operation with slave select, but some chips have the select as a separate option...

Best Wishes
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Wed Mar 09, 2011 6:18 am     Reply with quote

My code is not working. Whats wrong with this?

Master
Code:

#include <18f252.h>
#fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect                               
#use delay(clock=20000000)                               
#use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)

#define SSP_SS PIN_B5

#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)

float value1;
int b0,b1,b2,b3;

union convert
{
 int data[4];
 float number;
}
val;
   
void main()
{
 output_high(SSP_SS);
 
 setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
 
 while(1)
 {
  value1=12.34;//value which has to be sent
  //break the floating value to seperate bytes and then send through SPI.
  {
   val.number=value1;
   b0=val.data[3];
   b1=val.data[2];
   b2=val.data[1];
   b3=val.data[0];
  }
  output_low(SSP_SS);
  spi_write(b0);//sending first byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  output_low(SSP_SS);
  spi_write(b1);//sending 2nd byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  output_low(SSP_SS);
  spi_write(b2);//sending 3rd byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  output_low(SSP_SS);
  spi_write(b3);//sending 4th byte
  output_high(SSP_SS);
  delay_ms(1);//some delay
 
  delay_ms(500);//after 0.5 sec repeat the process again.
 }
}


Slave
Code:

#include <18f252.h>
#fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect
#use delay(clock=20000000)             
#use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)

#byte SSPBUF = 0xFC9//register value for 18f252

#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)

int data[4],x=0,flag=0;
float recive;
int32 data32;

union convert
{
 int32 y;
 float fval;
}
val;

   
#int_ssp
void ssp_isr(void)
{
 data[x]=SSPBUF;
 x++;
 if(x>=4)
 {
  x=0;
  flag=1;
 }
}

void main()
{
 setup_spi(SPI_SLAVE | SPI_MODE_0);
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
  if(flag==1)
  {
   data32=make32(data[0],data[1],data[2],data[3]);
   //function for making int32 to float
   val.y=data32;
   recive=val.fval;
   printf("%f\r\n",recive);//display the result.
   flag=0;
  }
 }
}
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Sun Mar 13, 2011 10:54 pm     Reply with quote

I have modified the PCM programmer code for sending and receiving the data using spi but it is not working as well,

Master
Code:

#include <18f252.h>
#fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect                               
#use delay(clock=20000000)                               
#use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)

#define SPI_SS PIN_B5

#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)

char c;
int result,counter;

void main()
{
 output_high(SPI_SS);
 
 setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_4);
 
 while(1)
 {
  c=getc();
  c=toupper(c);
 
  switch(c)
  {
   case 'A':
   output_low(SPI_SS);
   spi_write(1);
   output_high(SPI_SS);
   delay_us(100);
   output_low(SPI_SS);
   result=spi_read(0);
   output_high(SPI_SS);
   printf("value =%u\r\n",result);
   break;
   
   case 'B':
   output_low(SPI_SS);
   spi_write(2);
   output_high(SPI_SS);
   delay_us(100);
   output_low(SPI_SS);
   result=spi_read(0);
   output_high(SPI_SS);
   printf("value =%u\r\n",result);
   break;
   
   case 'C':
   output_low(SPI_SS);
   spi_write(3);
   output_high(SPI_SS);
   delay_us(100);
   output_low(SPI_SS);
   result=spi_read(0);
   output_high(SPI_SS);
   printf("value =%u\r\n",result);
   break;
  }
 }
}


Slave
Code:

#include <18f252.h>
#fuses HS,NOWDT,NOLVP,PUT,NOBROWNOUT,protect
#use delay(clock=20000000)             
#use rs232(xmit=PIN_C6, rcv=PIN_C7, baud=9600)

//#byte SSPBUF = 0xFC9//register value for 18f252

#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)

int counter;
int buffer;
#int_ssp
void ssp_isr(void)
{
 buffer=spi_read();
 
 int command;
 
 command=SSPBUF;
 
 switch(command)
 {
  case 1:
  SSPBUF=5;
  break;
 
  case 2:
  SSPBUF=46;
  break;
 
  case 3:
  SSPBUF=12;
  break;
 }
 counter++;
}

void main()
{
 setup_spi(SPI_SLAVE | SPI_MODE_0);
 clear_interrupt(INT_SSP);
 enable_interrupts(INT_SSP);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
 
 }
}


Where i am wrong.
PCM programmer



Joined: 06 Sep 2003
Posts: 20135

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 11:43 am     Reply with quote

I didn't really look at the code closely. Post a list of the connections
between the two PICs. There should be 4 wires for the SPI signals,
and a ground connection. Post the pin numbers on each PIC that
are connected to each other for the SPI.
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Mon Mar 14, 2011 11:33 pm     Reply with quote

Quote:

I didn't really look at the code closely. Post a list of the connections
between the two PICs. There should be 4 wires for the SPI signals,
and a ground connection. Post the pin numbers on each PIC that
are connected to each other for the SPI.


I am using two 18f252 pic for spi communication
my connections are

SDI--->SDO
SDO--->SDI
SCK--->SCK
GND--->GND
For SS I am using PIN_A0 on both controller. Before I was using PIN_B5.

my compiler version is 4.093
PCM programmer



Joined: 06 Sep 2003
Posts: 20135

View user's profile Send private message

PostPosted: Tue Mar 15, 2011 12:26 am     Reply with quote

Quote:
For SS I am using PIN_A0 on both controller.

Download the 18F252 data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/39564c.pdf
Look at the pin diagram for the 18F252. What pin is used for \SS
on a SPI Slave PIC ? Hint: It's not Pin A0.

On the SPI Master PIC, you can use pin A0 to drive the Slave Select
signal, because it's done by software, with output_low() and output_high()
functions. But for an SPI slave you must use the correct hardware \SS
pin on the Slave PIC. Read the data sheet to find the correct pin.
hayee



Joined: 05 Sep 2007
Posts: 252

View user's profile Send private message

PostPosted: Tue Mar 15, 2011 12:50 am     Reply with quote

PCM Programmer
Its pin #7 of 18f252. /SS
I have change the hardware from A0 to A5 on slave side, but I am not using that pin in the slave software, so will it work without declaring that pin? Is it necessary to change the pin of master from A0 to A5?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4  Next
Page 2 of 4

 
Jump to:  
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