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

How to use #pin_select

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

Joined: 07 Apr 2014
Posts: 1

View user's profile Send private message

How to use #pin_select
PostPosted: Thu Apr 21, 2016 5:30 pm     Reply with quote

In my project in setting I2c through CCS WIZARD I have this error when compiling.....

Option invalid. Wrong pin for H/W.

This my code:
file I2C.h

#include <16LF1704.h>
#device ADC=10
#use delay(internal=32MHz)

#define Device_SDA PIN_C1
#define Device_SLC  PIN_C0

#use i2c(Slave,Slow,sda=Device_SDA,scl=Device_SLC,address=0x10)

file I2C.c

#include <I2C.h>

void main()

      //TODO: User Code

PCM programmer

Joined: 06 Sep 2003
Posts: 20759

View user's profile Send private message

PostPosted: Thu Apr 21, 2016 8:47 pm     Reply with quote

Put this above the #use i2c() statement:
#pin_select SCL1OUT = PIN_C0
#pin_select SCL1IN  = PIN_C0

#pin_select SDA1OUT = PIN_C1
#pin_select SDA1IN  = PIN_C1

Joined: 11 Mar 2010
Posts: 14611

View user's profile Send private message

PostPosted: Fri Apr 22, 2016 4:33 am     Reply with quote

This is one that is approaching 'FAQ' status. Perhaps ought to be a sticky at the top of the forum. It is now!... Smile

PIC's have three different ways of selecting pins that peripherals go to:

The first (oldest), is in some cases individual peripherals can be set to two different sets of pins using a fuse. So you have chips with fuses like 'ALTI2C1', that sets the I2C1 peripheral to use the alternate pins.
Then there were chips with the 'first generation' re-mappable peripherals, where there is a single configuration bit that moves a peripheral to another set of pins (exactly like the fuse, but accessible in software).
Then there is the latest version 'Peripheral Pin Select' (PPS).

It is 'PPS' chips that #PIN_SELECT is for.

On these there are a number of pins, that support 're-mappable peripherals' (normally shows as 'RP...' in the pin diagrams, and a number of peripherals that can be moved to these. On these, you must tell the compiler what pins the peripheral is using before setting the peripheral up.

Just to expand on PCM_programmer's answer, I'd also suggest using the peripheral name, rather than the pins in the #use statement. So:

#include <16LF1704.h>
#device ADC=10
#use delay(internal=32MHz)

#pin_select SCL1OUT = PIN_C0
#pin_select SCL1IN  = PIN_C0

#pin_select SDA1OUT = PIN_C1
#pin_select SDA1IN  = PIN_C1

#use i2c(Slave,I2C1,address=0x10)

So this sets the peripheral I2C1 SCL I/O functions to go to PIN_C0 and the SDA to go to PIN_C1.
Then the #use I2C, can talk to the hardware peripheral (I2C1), and it's external connections will be to these pins.

As a comment to the poster at the start of this thread, get rid of 'slow'. A _slave_ does not have a speed in general. The speed is controlled and settable in the master only. Can cause issues in the configuration.

Now to expand for other devices. What I/O devices can use this?.

This depends on your chip. Data sheet, and look at the header file for the chip. So (for instance), the chip header may well say something like:

////////////////////////////////////////////////////////////////// PIN_SELECT
// #pin_select function=pin
// Valid Pins:
//    PIN_B10,PIN_B11,PIN_B12,PIN_B13,PIN_B14,PIN_B15,PIN_A0,PIN_A1
// Input Functions:
// Output Functions:

So this chip has a huge array of peripherals that can be used this way (four interrupt pins, four CCP's, Uart1, Uart2, SSP2 etc., and a lot of pins that can be used.

To setup the UART for pins B11 (RX) and B10 (TX), the syntax is:

#USE RS232 (UART1, BAUD=115200, ERRORS)
//You should always use 'ERRORS' unless you are adding code to
//handle hardware ERRORS yourself

In addition to this, it is possible if required to 'dynamically' change the mapping later 'in code'. This is only needed if you have some specific reason to 'change things'. So (perhaps) you want to do a serial receive on another set of pins for a little while, and want the hardware UART on these.

Things needed:

1) Map the peripherals to the 'default' setting in the setup as shown.
2) Have the fuse NOIOL1WAY. This allows the settings to be used more than once after the chip boots.
3) Then you can change mappings 'in code', so (for instance) to move the above UART to pins B12, and B13:

    //Inside your code when wanted
    putc('X'); //this will be using the default pins
    delay_ms(50); //ensure byte has finished sending.

    pin_select("U1RX", PIN_B12, TRUE, FALSE);
    pin_select("U1TX", PIN_B13, FALSE, TRUE);

    //Now sent using B13

The 'TRUE' and 'FALSE' stuff is to do with unlocking the pin. Basically if you are doing a number of changes, then unlock on the first command, and lock up again on the last one. The 'TRUE' on the first command unlocks, then the 'FALSE says "don't lock back up", while on the next command the pins are already unlocked (so 'FALSE' for the unlock), but then lock back up when finished (final 'TRUE'). Keeping the pins locked when not being changed, avoids accidental unwanted changes..... Very Happy

The default if these are omitted is to unlock and re-lock every time, but this takes longer.

There are sometimes some oddities that need to be carefully watched for.
An example here is the clock shown in the I2C setup, where there is both an 'in' and 'out' separated internally, and both have to be mapped to the single SCL pin if the peripheral is to work as expected. This is mentioned in the data sheet, so 'beware' and make sure you know what has to be mapped where....

One 'caveat' to add to this, applies with bootloaders.
If you have a bootloader, and it uses a PPS peripheral (so maps anything
with PPS), you need to ensure the NOIOL1WAY fuse is selected. Otherwise
your main code will not be able to change the pin settings.
The IOL1WAY fuse means that things can be set only once. Problem is if
the bootloader is setting them, then the 'main' code can't set them again....
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