|
|
View previous topic :: View next topic |
Author |
Message |
custom_elect
Joined: 15 Dec 2007 Posts: 13
|
SPI byte order inconsistent between software and hardware |
Posted: Sat Jan 19, 2008 6:19 pm |
|
|
Im just moving some working code from a software SPI:
#use spi (MASTER, DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, BITS=16)
to use the internal hardware SPI:
#use spi(SPI1, MASTER, BAUD=1000000, BITS=16)
I may be going loopy, but it looks like the byte order gets swapped.
In the software case, spi_xfer (0x800F) sends 0x80 then 0x0F as expected
In the hardware case, spi_xfer (0x800F) sends 0x0F then 0x80
Is this expected? or am I doing something wrong?
Any help greatly appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jan 19, 2008 9:28 pm |
|
|
Post the PIC and the compiler version. |
|
|
custom_elect
Joined: 15 Dec 2007 Posts: 13
|
|
Posted: Wed Jan 23, 2008 12:11 pm |
|
|
The PIC is 16F877A
The compiler "CCS PCM C Compiler, Version 4.063, 41607"
The platform is "PICDEM 2 Plus" |
|
|
ECACE
Joined: 24 Jul 2006 Posts: 94
|
|
Posted: Wed Jan 23, 2008 12:36 pm |
|
|
Have you tried playing with the LSB/MSB_First option of #use spi? I'm not sure if that is valid for HW and SW or just SW spi. It may be a case of by default the software spi did LSB first, and the HW spi sending MSB first or visa-versa. Not sure, but may be worth looking into. _________________ A HW Engineer 'trying' to do SW !!! Run!!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jan 23, 2008 1:36 pm |
|
|
I installed your compiler version. Here's the first test program, using
the hardware SPI module.
Code: |
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use spi(SPI1, MASTER, BAUD=1000000, BITS=16)
//=================================
void main()
{
spi_xfer(0x800F);
while(1);
}
|
From this portion of the .LST file, we can see that the upper byte
is put into 0x22, and the lower byte is put into 0x21.
Code: |
....... spi_xfer(0x800F);
0038: MOVLW 80
0039: MOVWF 22
003A: MOVLW 0F
003B: MOVWF 21
003C: MOVLW 10
003D: MOVWF 23
003E: GOTO 004
|
// Here's the part where the bytes are sent. It shows that
// the lower byte is sent first. This is for the Hardware SPI
// method.
Code: |
... #use spi(SPI1, MASTER, BAUD=1000000, BITS=16)
0004: MOVF 13,W
0005: MOVF 21,W // Get the lower byte (0x0F)
0006: MOVWF 13 // Put it in SSPBUF (transmit it)
0007: BSF 03.5
0008: BTFSS 14.0
0009: GOTO 008
000A: BCF 03.5
000B: MOVF 13,W
000C: MOVWF 78
000D: MOVF 22,W // Get the upper byte (0x80)
000E: MOVWF 13 // Put it in SSPBUF (transmit it)
000F: BSF 03.5
0010: BTFSS 14.0
0011: GOTO 010
0012: BCF 03.5
0013: MOVF 13,W
0014: MOVWF 79
0015: BCF 0A.3
0016: BCF 0A.4
0017: GOTO 03F (RETURN) |
Now let's make a 2nd test program that uses the software SPI method:
Code: |
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use spi (MASTER, DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, BITS=16)
//=======================
void main()
{
spi_xfer(0x800F);
while(1);
}
|
Again, it puts the upper byte into 0x22, and the lower byte into 0x21.
This is for the software SPI.
Code: | ... spi_xfer(0x800F);
004E: MOVLW 80
004F: MOVWF 22
0050: MOVLW 0F
0051: MOVWF 21
0052: MOVLW 10
0053: MOVWF 23
0054: GOTO 004
|
// This code for the software SPI, shows that it sends bit 0 of the
// lower byte first. All bits in the 16-bit word are shifted right and
// come out of Bit 0 of the lower byte.
Code: | ... #use spi (MASTER, DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, BITS=16)
0004: BSF 20.4
0005: MOVF 20,W
0006: BSF 03.5
0007: MOVWF 07
0008: BCF 03.5
0009: BCF 20.5
000A: MOVF 20,W
000B: BSF 03.5
000C: MOVWF 07
000D: BCF 03.5
000E: BCF 20.3
000F: MOVF 20,W
0010: BSF 03.5
0011: MOVWF 07
0012: BCF 03.5
0013: BCF 07.3
0014: MOVF 23,W
0015: MOVWF 24
0016: BSF 07.3
0017: BTFSS 21.0 // Test bit 0 of the lower byte.
0018: BCF 07.5 // Set the DO pin based on the bit value.
0019: BTFSC 21.0
001A: BSF 07.5
001B: RRF 22,F // "Rotate right" the upper byte.
001C: RRF 21,F // Rotate it into the lower byte.
001D: BCF 07.3
001E: RRF 79,F
001F: RRF 78,F
0020: BTFSS 07.4
0021: BCF 79.7
0022: BTFSC 07.4
0023: BSF 79.7
0024: DECFSZ 24,F
0025: GOTO 016
0026: MOVF 23,W
0027: SUBLW 10
0028: BTFSC 03.2
0029: GOTO 02F
002A: MOVWF 24
002B: RRF 22,F
002C: RRF 21,F
002D: DECFSZ 24,F
002E: GOTO 02B
002F: BCF 0A.3
0030: BCF 0A.4
0031: GOTO 055 (RETURN) |
So, in each case, the lower byte (0x0F in your example) is shifted out
first. But the hardware SPI module shifts out the bits MSB first.
In other words, bit 7 of each byte is shifted out first. The software
module shifts out bit 0 first. That's what you're seeing.
In your original post you implied that some kind of byte swap is going on,
but that's not true. ECACE has a good solution. Add a parameter to
the software SPI declaration to change the bit order of transmission.
Then I believe you can make the two methods match each other.
If you do want to shift out Bit 0 first with the hardware SPI module,
this post has links to bit swapping routines.
http://www.ccsinfo.com/forum/viewtopic.php?t=27812&start=11
http://www.ccsinfo.com/forum/viewtopic.php?t=27812&start=11 |
|
|
|
|
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
|