Many newer Microchip PIC® microcontrollers have re-programmable peripheral pins (RP). These pins allow the user to dynamically allocate peripherals to these pins, such as external interrupts, input capture, PWM, serial, timers and more. This offers the designer great flexibility when designing a product since the functionality of these pins can be changed at run-time. The data sheet for a device will list he pin assignments and these pins are denoted as either RPxx or RPIxx, where xx is the RP pin number. Pins that are RPIxx can only be programmed as an input (timer input, serial input, interrupt input, etc), whereas RPxx pins can be programmed either as an input or output (PWM output, serial output, etc).
Static Assignments in C
The static method for assigning I/O pins to a peripheral is the #pin_select directive. The #pin_select directive is a preprocessor directive for assigning I/O pins to peripherals and is executed before main() starts. The syntax for this command is as follows:
A list of functions and pins that can be used with the #pin_select directive is located in the device's header file near the top of the file, opening the device's header file (like 18F25K42.h) and searching for #pin_select is the quickest way to find them. The following is an example of how to assign pins to the UART1 RX and TX pins:
When using RP pins with a peripheral library, such as #use rs232(), the #pin_select must come before the #use directive, for example:
#use rs232(UART1, baud=9600, stream=U1)
There is a special method for assigning the peripheral pins is inside the #use pwm and #use capture directives. Future compiler release may allow this in other #use directives as well. Here is an example:
#use pwm(CCP1, output=PIN_B0)
The above will make the assignment of PIN_B0 as the CCP1 output pin.
Dynamic Pin assignments
In addition to #pin_select the CCS C Compiler also provides the pin_select() function for assigning pins to a peripheral. The pin_select() function can be used to assign, reassign and unassign pins to/from a peripheral at run-time. This allows the flexibility of using the same pin for multiple peripherals or using pins as both peripheral pins and I/O pins. The basic pin_select() function uses the following syntax: pin_select("function", pin);. The functions and pins are the same as what is used with the #pin_select directive, the only difference being that the function is passed as a constant string. The following is an example of how to assign pins to the UART1 peripheral:
To unassign a pin from a peripheral depends on whether it an input peripheral or an output peripheral.
To unassign a pin from an output peripheral is done as follows:
pin_select("NULL", PIN_C6); //unassign PIN_C6 from output peripheral.
To unassign a pin from an input peripheral is done as follows:
pin_select("U1RX", FALSE); //unassign pin from U1RX input peripheral.
Because of how output peripherals are assigned to RP pins it is possible to assign multiple pins to the same output peripheral when using the pin_select() directive. For example the following will assign multiple pins to the CCP1 peripheral:
This method of tying several pins to the same output can only be performed with the pin_select() function, #pin_select cannot be used to do this.
A more advanced form of the pin_select() directive is as follows:
pin_select("function", pin, unlock, lock);
In order to change the pin assignments at run time the pins must be first specifically unlocked to prevent run away code from changing a pin assignment. The optional unlock and lock are used to specify whether to do or not to do the unlock and lock procedures, TRUE does the procedure and FALSE doesn't to the procedure. When the lock/unlock parameters are not specified in the function both are performed by default. These optional parameters are most useful when using the pin_select() function to assign multiple peripheral pins sequentially. For example the following is an example of how to assign the UART1 TX and RX pins at run time:
pin_select("U1TX", PIN_C6, TRUE, FALSE);
pin_select("U1RX", PIN_C7, FALSE, TRUE);
Alternate pin assignments
Before the RP pins came out some chips allowed select peripherals to have multiple (usually just two) pins that can be assigned. This is done either by a fuse (like CCP2B3 and CCP2C1) or using an internal register.
In the case the selection is by fuse the #fuse directive must be inserted in the code and then the compiler will treat that pin as a peripheral. For example:
In the case that the register assignments are made by register the built in functions will have an option for the assignment. See the header file for the device. The UART assignments are made with the #use rs232 by specifying one of the alternate pins.
Like us on Facebook. Follow us on Twitter.
CCS is a leading worldwide supplier of embedded software development tools that enable companies to develop premium products based on Microchip PIC® MCU and dsPIC® DSC devices. Complete proven tool chains from CCS include a code optimizing C compiler, application specific hardware platforms and software development kits. CCS' products accelerate development of energy saving industrial automation, wireless and wired communication, automotive, medical device and consumer product applications. Established in 1992, CCS is a Microchip Premier 3rd Party Partner. For more information, please visit https://www.ccsinfo.com.
PIC® MCU, MPLAB® IDE, MPLAB® ICD2, MPLAB® ICD3 and dsPIC® are registered trademarks of Microchip Technology Inc. in the U.S. and other countries.