chipKIT® Development Platform

Inspired by Arduino™

Change 14 pins all at once - pic32

Created Mon, 01 Jun 2015 03:24:48 +0000 by djgardn2


Mon, 01 Jun 2015 03:24:48 +0000


Most of the time you would simply toggle one pin at a time on a microcontroller, but each pin takes its own small amount of time to be turned on. Using the code below you can change the state of 14 pins at the same time with a max frequency of 5Mhz all at one time on the PIC32MX250F128B. Other PIC32 versions might have the ability to control 16 all at once too.

If you want the fastest way to turn on a pin see the following code below. This simultaneously turns on 14 pins and then off 14 pins using a PIC32MX250F128B microcontroller.

// PIC32MX250B128F microcontroller
//using DP32 board setting in MPIDE or UECIDE

void setup() {   
  // sets pins 0-8 as outputs and turned low
  for(int i = 0; i<9; i++)
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);    
  // sets pins 11-14 as outputs and turned low
  for (int i =11; i<15; i++)
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  // pin 17
  pinMode(17, OUTPUT);


void loop() {
    LATB |= 0xEFBF;
    LATB &= 0x0000;

Below is a screenshot using a logic analyzer to see all 14 pins changing at the same time on the PIC32MX250F128B microcontroller. This was taken using the Analog Discovery™ using WaveForms™. [attachment=1]14-Pins-At-Once-PIC32.jpg[/attachment] [attachment=0]5Mhz-Frequency.jpg[/attachment]


Mon, 01 Jun 2015 09:52:55 +0000

Yes, the larger PIC32 chips have some ports that are a complete 16-bit port (usually port B) which can be used as a single atomic IO port.

Two functions you may find useful for working like this are:

uint32_t digitalPinToPort(int pin);
uint32_t digitalPinToBitMask(pin);

The first returns the port "number" (A = 1, B = 2, etc), and the second returns the "mask" value (i.e., 1<<bit) to use on that port.

Using those you could scan through all the available digital IO pins [for (int i = 0; i < NUM_DIGITAL_PINS; i++) { ... }] and find which pins are on which port to build up a picture of what is available. For instance, if you want to use all of port B, but you don't know how many of port B are actually available, you could do something like this:

uint32_t mask = 0;
for (int i = 0; i &lt; NUM_DIGITAL_PINS; i++) {
    if (digitalPinToPort(i) == 2) {
        pinMode(i, OUTPUT);
        mask |= digitalPinToBitMask(i);

That then sets all the available PORTB pins to output and builds up a total "mask" value (say 0b0011101100111011) for all the PORTB pins that are actually available on your board.

If you want higher speed access to pins that aren't all in the same port there is another handy function which gets you a pointer to the port's register structure for a pin:

p32_ioport *portRegisters(portno);

That takes the value returned by "digitalPinToPort" and returns a handy structure representing everything the port can do (a direct 1:1 overlay on the registers in memory). Each entry in the returned struct is itself a struct with each of the 4 sub-registers for value, clear, set, and invert in there. So you could:

uint32_t port = digitalPinToPort(3);
uint32_t mask = digitalPinToBitMask(3);
p32_ioport *reg = portRegisters(port);

reg-&gt;lat.set = mask;
reg-&gt;lat.clr = mask;
reg-&gt;lat.inv = mask;

... etcetera.

You can also check the return of digitalPinToPort against the macro "NOT_A_PORT" and the return value of digitalPinToBitMask against "NOT_A_PIN" to make sure they are valid pins (some boards have "holes" in their pin lists).

But of course for proper high speed, low latency, parallel port access you can't beat the PMP (Parallel Master Port). I use that on the Picadillo's TFT driver to give blisteringly quick DMA driven data transfers.


Mon, 01 Jun 2015 23:29:57 +0000

Very nice, I believe I came across seeing that code before but didn't look into it much.

Thanks for the nice description it is much clearer now and I will be sure to test those functions out more.

I appreciate the extra details, Thanks.