View previous topic :: View next topic |
Author |
Message |
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
SPI interface and I/O |
Posted: Fri Oct 27, 2006 5:33 am |
|
|
Hello,
I'm using the SPI master configuration in my application:
Code: | /********************** BRAILLE DISPLAY CLEAREN *****************************//
//Er worden allemaal '0'-en geschreven naar het BRAILLE-DISPLAY
#SEPARATE
void BR_CLEAR ()
{
if ( LEESREGEL )
{
int8 j;
Cursor_Timer = 255;
setup_spi ( SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4 );
for ( j = 0 ; j < 40 ; j++ )
{
spi_write (0x00);
}
output_high (BR_STROBE); // STROBE PULS
output_low (BR_STROBE);
setup_spi (FALSE);
}
} |
So my SPI interface has :
RC5 = SDO
RC4 = SDI - I'm not using this pin as SPI, I'm using it as Output. It is actually the BR_STROBE line.
RC3 = SCK
OK, now what is the question/issue?
Well I want to know what happens with RC5 pin after you state
Is it set as an input or output?
I'm confused as I measure 3V on some PICs and 0V on other PICs.
I don't want it be high ( = 3V) as current leaks in the slave device when that is disabled.
What can I do to fix this?
tks in advance
Ps: I'm using PIC16LF877A 4Mhz Xtal |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Fri Oct 27, 2006 6:16 am |
|
|
got some interesting text from the datasheet:
Quote: | 9.3.3 ENABLING SPI I/O
To enable the serial port, SSP Enable bit, SSPEN
(SSPCON<5>), must be set. To reset or reconfigure
SPI mode, clear the SSPEN bit, re-initialize the
SSPCON registers and then set the SSPEN bit. This
configures the SDI, SDO, SCK and SS pins as serial
port pins. For the pins to behave as the serial port function,
some must have their data direction bits (in the
TRIS register) appropriately programmed. That is:
• SDI is automatically controlled by the SPI module
• SDO must have TRISC<5> bit cleared
• SCK (Master mode) must have TRISC<3> bit
cleared
• SCK (Slave mode) must have TRISC<3> bit set
• SS must have TRISC<4> bit set
Any serial port function that is not desired may be
overridden by programming the corresponding data
direction (TRIS) register to the opposite value. |
However, what does the compiler with the I/O (DDR) do when
Code: | setup_spi ( SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4 ); |
same question :
|
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Mon Oct 30, 2006 9:04 am |
|
|
anyone? pls |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 31, 2006 1:03 am |
|
|
Look at the .LST file. I compiled a test program for the 18F452, using
PCH vs. 3.249. Here is the generated code:
Code: |
.... setup_spi(FALSE);
0028: BCF SSPCON1.5 // SSPEN bit = 0
002A: BCF TRISC.5 // Pin C5 = output
002C: BSF TRISC.4 // Pin C4 = input
002E: BCF TRISC.3 // Pin C3 = output
0030: MOVLW 00
0032: MOVWF SSPCON1
0034: MOVWF SSPSTAT
|
I don't think that 'FALSE' is a valid parameter for the Setup_spi() function.
It's not listed in the 18F452.H file. I don't think CCS has a legitimate
way to disable the SPI port by using the setup_spi() function.
Look at the code generated when you setup the SPI port. It's basically
the same. The function just writes the LSB of the parameters to the
SSPCON1 register and the MSB to SSPSTAT.
Code: |
.... setup_spi ( SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4 );
0036: BCF SSPCON1.5
0038: BCF TRISC.5
003A: BSF TRISC.4
003C: BCF TRISC.3
003E: MOVLW 20
0040: MOVWF SSPCON1
0042: MOVLW 40
0044: MOVWF SSPSTAT
|
You can make a function that will disable the SPI port, and also make
all the SPI pins into inputs. Example:
Code: |
// These addresses are for the 18F452.
#byte SSPSTAT = 0xFC7
#byte SSPCON1 = 0xFC6
#bit SSPEN = SSPCON1.5
void disable_SPI(void)
{
SSPEN = 0; // Disable the SSP module
// Set the three SPI pins to be inputs.
output_float(PIN_C3); // SCLK
output_float(PIN_C4); // SDI
output_float(PIN_C5); // SDO
} |
Or, I suppose that you could just use the setup_spi(FALSE) statement
and just put the output_float() statements after it, to set the pins as
inputs. |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Tue Oct 31, 2006 1:56 am |
|
|
thx for the input on the LST file. Then you can see what actually happens in that function.
edit:
what is the SSEN bit cleared on the second setup_SPI function? Shouldn't it be set to enable it? |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Tue Oct 31, 2006 2:06 am |
|
|
How can I find the adress for the SSPCON1.5 register? I don't seem to find it in my header file.
Last edited by Christophe on Tue Oct 31, 2006 2:26 am; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 31, 2006 2:24 am |
|
|
Is there a reason to post the whole header file ?
The address is in the data sheet, not the header file. |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Tue Oct 31, 2006 2:39 am |
|
|
I'm sorry I did. I've allready deleted it.
I've found it's on adress 14h
Quote: | REGISTER 9-2: SSPCON1: MSSP CONTROL REGISTER 1 (SPI MODE) (ADDRESS 14h)
R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0 R/W-0
WCOL SSPOV SSPEN CKP SSPM3 SSPM2 SSPM1 SSPM0
bit 7 bit 0 |
After learning from this topic my own function would now be:
Code: | #define SSPCON1 0x14
void disable_SPI (void)
{
#ASM
BCF SSPCON1.5
#ENDASM
// Set the three SPI pins to be inputs.
output_float(PIN_C3); // SCLK
output_float(PIN_C4); // SDI
output_float(PIN_C5); // SDO
} |
could you check this? |
|
|
Ttelmah Guest
|
|
Posted: Tue Oct 31, 2006 7:30 am |
|
|
A 'simpler' way, is not to use assembler, but instead the bit/byte operations. So:
Code: |
#byte SSPCON1=0x14
#bit SSPEN=SSPCON1.5
//Then to disable the SPI
SSPEN=FALSE;
//or to enable it
SSPEN=TRUE;
|
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Tue Oct 31, 2006 7:43 am |
|
|
What way is faster/uses less ROM ? |
|
|
Ttelmah Guest
|
|
Posted: Tue Oct 31, 2006 7:59 am |
|
|
should be Identical.
The 'SSPEN=FALSE' instruction, codes as a bit clear, while the 'SSPEN=TRUE'. codes as a bit set. The 'disable_SPI' function as shown, should code as 'inline' (otherwise this will have an extra overhead of a call/return). If you want to use 'disable_SPI' as a syntax, then:
Code: |
#byte SSPCON1=0x14
#bit SSPEN=SSPCON1.5
#define disable_SPI() SSPEN=FALSE
#define enable_SPI() SSPEN=TRUE
|
Will allow you code 'disable_SPI();', and 'enable_SPI();', and will each use just one instruction.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Tue Oct 31, 2006 9:09 am |
|
|
what is the difference between 1. (define) and 2. using byte
1.
Code: | [b]#define[/b] SSPCON1 0x14
void disable_SPI (void)
{
#ASM
BCF SSPCON1.5
#ENDASM
// Set the three SPI pins to be inputs.
output_float(PIN_C3); // SCLK
output_float(PIN_C4); // SDI
output_float(PIN_C5); // SDO
} |
2.
Code: | [b]#byte [/b]SSPCON1 0x14
void disable_SPI (void)
{
#ASM
BCF SSPCON1.5
#ENDASM
// Set the three SPI pins to be inputs.
output_float(PIN_C3); // SCLK
output_float(PIN_C4); // SDI
output_float(PIN_C5); // SDO
} |
edit: doesn't seem to bold in code tags.. |
|
|
Ttelmah Guest
|
|
Posted: Tue Oct 31, 2006 9:17 am |
|
|
With '#define', all you are doing is creating a 'macro' replacement, that happens during the compile. So where the text 'SSPCON1' is found, it is replaced by the text '0x14'. To actually 'access' this location, you have to either add assembler (as you are doing), or treat the definition as a pointer.
#byte, creates a variable, that is physically mapped at the location given. So the first #byte, now gives an 8bit variable called 'SSPCON1', which you can write values to, or read values from. Then the #bit declaration, gives a one bit variable mapped as bit 5 of this. You can then use standard C code to access this variable, and the compiler will generate the required bit access to talk to it.
Best Wishes |
|
|
Christophe
Joined: 10 May 2005 Posts: 323 Location: Belgium
|
|
Posted: Tue Oct 31, 2006 9:26 am |
|
|
So:
Code: | #ASM
BCF 0X14.5
#ENDASM |
is clearing bit 5 of the content of the 8 bit register that is located on adress 0X14h ?
That seems more comprehensible than the #byte and #bit statements to me. |
|
|
Ttelmah Guest
|
|
Posted: Tue Oct 31, 2006 10:21 am |
|
|
In which case you might as well not use C at all.
At the end of the day, anyone looking at the code latter, is going to have to go and look at the data sheet to work out that register 14, is SSPCON, and then that bit 5 is the SSP ENABLE, and then work out that this code disables the SSP.
The whole point of symbolic names, is that they should help to make clear what is going on. The assembly line would need a good comment, saying something like 'turn off the SSP enable bit', if the code is to be comprehensible in the future. Conversely the bit define, followed by:
SSPEN=0;
Is largely self documenting.
Also, the direct access form, brings potentially more work latter if you decide to move to another chip. If the register definitions used, are all placed together at the head of an include file, in the form:
#byte SSPCON1=0x14
etc., then if latter the code has to move to another processor, you only need to change these defines, and not look into the rest of the code at all.
Best Wishes |
|
|
|