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 CCS Technical Support

Bit banging SPI

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
congbinhdbk



Joined: 27 Aug 2013
Posts: 1
Location: Việt Nam

View user's profile Send private message AIM Address

Bit banging SPI
PostPosted: Tue Aug 27, 2013 9:18 pm     Reply with quote

Hi all!
I'm working with SPI by Software. I'm coding for slave with PIC18F4620 and have a problems. I receive data from master is ok but i can't transmit data from slave to master. Please help me!
Code:

int spi_io_read(int data_out) {
   int data_in=0;
   signed int i;
   
   sdo=0;
   for(i=7;i>=0;i--) {
      //set data to SDO
      if(bit_test(data_out,i)==1) sdo=1;
      else  sdo=0;
      //waiting for clock
      cnt=0;
      while((sck==0)&&(cnt<=100)) {
         cnt++;
      }
      while((sck==1)&&(cnt<=200)) {
         cnt++;
      }
      //read data in SDI
      if(sdi==1) bit_set(data_in,i);
      else bit_clear(data_in,i);
   }
   return   data_in;
}
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Tue Aug 27, 2013 11:04 pm     Reply with quote

Your sample data on the opposite edge from writing data to the bus. This all depends on your setup. See http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus for full description.

You sample and write on the same edge.

Also much more efficient code to do it as below
Code:
 
for (i=0; i <8 ; i++) {
  if (bit_test(data_out,7) sdo=1;
  else sdo = 0;
  data_out <<=1;
}


Compiler can work out bit position at compile time instead of run time which involves more instructions.

Regards
Alan
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Wed Aug 28, 2013 3:59 am     Reply with quote

Given that both the input byte, and output byte will be handling the same 'bit' at a time, I'd say it'd be more efficient, to use a single mask. So something like:
Code:

int spi_io_read(int data_out) {
   int8 data_in=0;
   int8 mask=0x80; //MSb first
 
   sdo=0;

   do
   {
      //wait for the first falling edge
      cnt=0;
      while((sck==1)&&(cnt<=100)) {
         cnt++;
      }
      //set data to SDO
      if(data_out & mask) sdo=1;
      else  sdo=0;
      //read data in SDI
      if(sdi) data_in &=mask; //data_in is already zero, so you only need
      //to handle the 1's.
      //waiting for rising edge
      while((sck==0)&&(cnt<=200)) {
         cnt++;
      }
      mask/=2;
   } while(mask); //finishes when eight bits transfered
   return   data_in;
}

However the big problem on the read, is that you are doing it a whole clock too late. Think about it. You preload the output value, then wait for a complete clock cycle, and read the input, and load the next output value. One bit late....
If your clock idles 'high', then the version I show will wait for the first falling edge, and then perform both transfers. However this will be the wrong way round if the clock idles low.

Using '/2' on the mask, codes as a rotation _through the carry_. So the bottom bit gets discarded each time, and after the eighth rotation, mask will be zero.

Bit_test, with a variable, is very inefficient. The compiler has to generate a mask, and rotate this the number of bits specified each time. Using your own single mask, just one rotation, for both bits.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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