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

SPI interface and I/O
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

SPI interface and I/O
PostPosted: Fri Oct 27, 2006 5:33 am     Reply with quote

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
Code:
setup_spi (FALSE);


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

View user's profile Send private message

PostPosted: Fri Oct 27, 2006 6:16 am     Reply with quote

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 :

Code:
setup_spi (FALSE);
Christophe



Joined: 10 May 2005
Posts: 323
Location: Belgium

View user's profile Send private message

PostPosted: Mon Oct 30, 2006 9:04 am     Reply with quote

anyone? pls
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 1:03 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 1:56 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 2:06 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 2:24 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 2:39 am     Reply with quote

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







PostPosted: Tue Oct 31, 2006 7:30 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 7:43 am     Reply with quote

What way is faster/uses less ROM ?
Ttelmah
Guest







PostPosted: Tue Oct 31, 2006 7:59 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 9:09 am     Reply with quote

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







PostPosted: Tue Oct 31, 2006 9:17 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Oct 31, 2006 9:26 am     Reply with quote

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







PostPosted: Tue Oct 31, 2006 10:21 am     Reply with quote

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
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 1, 2  Next
Page 1 of 2

 
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