Created Sun, 10 Feb 2013 17:11:49 +0000 by tsalzmann
Sun, 10 Feb 2013 17:11:49 +0000
Is there any way of changing the digital outputs voltage to 5V?
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
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
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
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
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.
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