chipKIT® Development Platform

Inspired by Arduino™

Digital pins with an output voltage of 5V

Created Sun, 10 Feb 2013 17:11:49 +0000 by tsalzmann


tsalzmann

Sun, 10 Feb 2013 17:11:49 +0000

Is there any way of changing the digital outputs voltage to 5V?


Jacob Christ

Tue, 12 Feb 2013 16:55:35 +0000

Some pins on the PIC32 may be open drain, in which case you could just pull them up to 5V. Others you would need to add a buffer IC or transistor.

Here is a discussion on sparkfun regarding this topic:

https://forum.sparkfun.com/viewtopic.php?f=14&t=20395

Jacob


RobertCarlRice

Wed, 13 Feb 2013 01:02:26 +0000

You can't get a 5 volt output directly from the PIC µP because the chip does not have a 5 volt input. It runs entirely on 3.3 volts.

I think that all chipKip digital outputs can be set to a 5 volt tolerant open-collector output except for the 12 analog input capable pins. The problem is that it's not easy to set open-collector output mode because the Arduino compatible software doesn't support it - the 5 volt processors don't have a need for open-collector output mode.

I see that the INPUT_PULLUP constant was recently added to for the pinMode command. I need help adding an OUTPUT_OPEN_COLLECTOR constant to the library to support the low voltage processors. It's not easy to convert a sketch to reference the port registers directly.

Thanks, Bob Rice


mikes

Wed, 13 Feb 2013 02:06:46 +0000

If you look in the Board_Data.c file for your board variant mpide-0023-windows-20111221\hardware\pic32\variants\Uno32\Board_Data.c in my case find the pin you want

_IOPORT_PE, // 32 RE6 PMD6/RE6 _IOPORT_PE, // [color=#FF0000]33 RE7[/color] PMD7/RE7 _IOPORT_PD, // 34 RD5 PMRD/CN14/RD5

so pin 33 is on RE7 port E pin 7 Check a data sheet to make sure your pin is 5 volt tolerant ODCxSET where x is your port pin 7 = 0x80 = 0b10000000 //the seventh bit to the left starting with zero

void setup()
{
  pinMode(33,OUTPUT);
  ODCESET = 0x80; //
}
void loop()
{
  digitalWrite(33,HIGH);
  delay(1000);  
  digitalWrite(33,LOW);
  delay(1000);  
}

And you need a pull-up resistor


RobertCarlRice

Wed, 13 Feb 2013 23:08:18 +0000

Like I said, the current solution is tacky using a mix of chipKit pins and PIC port mappings. I think some readers, who need configurable pin support, will find the following code useful:

// volatile unsigned int* TRISvector[5] = { &TRISB, &TRISC, &TRISD, &TRISE, &TRISF }; volatile unsigned int* TRISSETvector[5] = { &TRISBSET, &TRISCSET, &TRISDSET, &TRISESET, &TRISFSET }; volatile unsigned int* TRISCLRvector[5] = { &TRISBCLR, &TRISCCLR, &TRISDCLR, &TRISECLR, &TRISFCLR };

// volatile unsigned int* ODCvector[5] = { &ODCB, &ODCC, &ODCD, &ODCE, &ODCF }; volatile unsigned int* ODCSETvector[5] = { &ODCBSET, &ODCCSET, &ODCDSET, &ODCESET, &ODCFSET }; volatile unsigned int* ODCCLRvector[5] = { &ODCBCLR, &ODCCCLR, &ODCDCLR, &ODCECLR, &ODCFCLR };

volatile unsigned int* PORTvector[5] = { &PORTB, &PORTC, &PORTD, &PORTE, &PORTF };

// volatile unsigned int* LATvector[5] = { &LATB, &LATC, &LATD, &LATE, &LATF }; volatile unsigned int* LATSETvector[5] = { &LATBSET, &LATCSET, &LATDSET, &LATESET, &LATFSET }; volatile unsigned int* LATCLRvector[5] = { &LATBCLR, &LATCCLR, &LATDCLR, &LATECLR, &LATFCLR };

#define PIN_MASK 0x0F #define ACTIVE_HIGH 0x80 #define OPEN_COLLECTOR 0x100

void setPinModeToOutput( int pin ) { int port = pin >> 4 & 7; unsigned int mask = 1 << ( pin & PIN_MASK );

(*TRISCLRvector[ port ]) = mask;

if ( pin & OPEN_COLLECTOR ) (*ODCSETvector[ port ]) = mask; // Open Collector else (*ODCCLRvector[ port ]) = mask; };

void setPinModeToInput( int pin ) { // Default setting after reset int port = pin >> 4 & 7; unsigned int mask = 1 << ( pin & PIN_MASK );

(*TRISSETvector[ port ]) = mask; };

void setPin( int pin, boolean state ) // Can be called at interrupt level { int level = state ? ACTIVE_HIGH : 0;

int port = pin >> 4 & 7; unsigned int mask = 1 << ( pin & PIN_MASK );

if ( level ^ pin & ACTIVE_HIGH ) (*LATSETvector[ port ]) = mask; else (*LATCLRvector[ port ]) = mask; };

boolean readPin( int pin ) { if ( pin == 0 ) return false;

int port = pin >> 4 & 7;
boolean state = (*PORTvector[ port ]) >> ( pin & PIN_MASK ) & 1;

return pin & ACTIVE_HIGH ? !state : state; };

void fmtPin( int pin ) { if ( pin & ACTIVE_HIGH ) Serial.print( "-" ); char c = 'B' + ( pin >> 4 & 7 ); Serial.print( c ); Serial.print( pin & PIN_MASK ); if ( pin & OPEN_COLLECTOR ) Serial.print( "oc" ); };

Using these routines, I map the chipKit pins to PIC port/bit in my host software using the following Ruby table:

UNO32pinMap = [
  0x42, #  0 34 U1RX/SDI1/RF2
  0x43, #  1 33 U1TX/SDO1/RF3
  0x28, #  2 42 IC1/RTCC/INT1/RD8
  0x20, #  3 46 OC1/RD0
  0x41, #  4 59 RF1
  0x21, #  5 49 OC2/RD1
  0x22, #  6 50 OC3/RD2
  0x29, #  7 43 IC2/U1CTS/INT2/RD9
  0x2A, #  8 44 IC3/PMCS2/PMA15/INT3/RD10
  0x23, #  9 51 OC4/RD3
  0x24, # 10 52 or 8 (PMWR/OC5/IC5/CN13/RD4) or (SS2/PMA2/CN11/RG9)
  0x58, # 11  6 or 5 (SDO2/PMA3/CN10/RG8) or (SDI2/PMA5/CN8/RG7)
  0x57, # 12  5 or 6 (SDI2/PMA5/CN8/RG7) or (SDO2/PMA3/CN10/RG8)
  0x56, # 13  4 SCK2/PMA5/CN8/RG6
  0x02, # 14 14 C2IN-/AN2/SS1/CN4/RB2
  0x04, # 15 12 C1IN-/AN4/CN6/RB4
  0x08, # 16 21 U2CTS/C1OUT/AN8/RB8
  0x0A, # 17 23 TMS/CVREFOUT/PMA13/AN10/RB10
  0x0C, # 18 27 or 36 (TCK/PMA11/AN12/RB12) or (SDA1/RG3)
  0x0E, # 19 29 or 37 (PMALH/PMA1/U2RTS/AN14/RB14) or (SCL1/RG2)
  0x03, # 20 13 C2IN+/AN3/CN5/RB3
  0x05, # 21 11 C1IN+/AN5/CN7/RB5
  0x09, # 22 22 PMA7/C2OUT/AN9/RB9
  0x0B, # 23 24 TDO/PMA12/AN11/RB11
  0x0D, # 24 28 TDI/PMA10/AN13/RB13
  0x0F, # 25 30 PMALL/PMA0/AN15/OCFB/CN12/RB15
  0x30, # 26 60 PMD0/RE0
  0x31, # 27 61 PMD1/RE1
  0x32, # 28 62 PMD2/RE2
  0x33, # 29 63 PMD3/RE3
  0x34, # 30 64 PMD4/RE4
  0x35, # 31  1 PMD5/RE5
  0x36, # 32  2 PMD6/RE6
  0x37, # 33  3 PMD7/RE7
  0x25, # 34 53 PMRD/CN14/RD5
  0x2B, # 35 45 IC4/PMCS1/PMA14/INT4/RD11
  0x26, # 36 54 CN15/RD6
  0x27, # 37 55 CN16/RD7
  0x46, # 38 35 U1RTS/BCLK1/SCK1/INT0/RF6
  0x44, # 39 31 PMA9/U2RX/SDA2/CN17/RF4
  0x45, # 40 32 PMA8/U2TX/SCL2/CN18/RF5
  0x01, # 41 15 PGC1/AN1/VREF-/CVREF-/CN3/RB1
  0x00, # 42 16 PGED1/PMA6/AN0/VREF+/CVREF+/CN2/RB0
  0x40, # 43 58 RF0
  0x59, # 44  8 PMA2/SS2/CN11/RG9
  0x53, # 45 36 SDA1/RG3
  0x52  # 46 37 SCL1/RG2
]

Bob Rice


mikes

Thu, 14 Feb 2013 14:42:30 +0000

I was just looking at the Core to see how easy it would be to implement and found that it already was :shock:.

pinMode(14, OPEN);     //OPEN makes it an open drain output

Still needs a pull up resistor.


RobertCarlRice

Thu, 14 Feb 2013 20:53:22 +0000

Thanks,

Has that OPEN constant made it into documentation anywhere?

Now that I've changed my sketch to reference the registers directly, I probably won't change it back.

Referring to my above logic, I had to add AD1PCFG to my setPinModeToInput routine:

void setPinModeToInput( int pin ) { // Default setting after reset except for analog capable int port = pin >> 4 & 7; unsigned int mask = 1 << ( pin & PIN_MASK );

(*TRISSETvector[ port ]) = mask; if ( port == 0 ) AD1PCFG |= mask; // Set for digital input. Analog pins align with digital port B };

Bob Rice