|
|
View previous topic :: View next topic |
Author |
Message |
congbinhdbk
Joined: 27 Aug 2013 Posts: 1 Location: Việt Nam
|
Bit banging SPI |
Posted: Tue Aug 27, 2013 9:18 pm |
|
|
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
|
|
Posted: Tue Aug 27, 2013 11:04 pm |
|
|
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: 19515
|
|
Posted: Wed Aug 28, 2013 3:59 am |
|
|
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 |
|
|
|
|
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
|