I'm wondering if it is possible to use port manipulation for only one pin and digitalRead/Write for the other pins. Everything I've read leads me to believe that you can only use port manipulation only on an entire port, not individual pins.
I want to use port manipulation on pin 0 where I have an IR led used as a remote (standalone 328, no Serial used). Can I do this?
Here's the applicable code.
//Sample program to trigger camera via IR
//Circuit: IR LED from pin 0, to 150 Ohm resistor, to ground
int IRpin = 0;
void setup(){
pinMode(IRpin, OUTPUT);
FireIR(7330);
}
void loop(){}
void FireIR(int IRdelay){
//send first 16 bursts
//for (int j=0; j<2; j++){
for(int i=0; i<16; i++) {
digitalWrite(IRpin, HIGH);
delayMicroseconds(10);
digitalWrite(IRpin, LOW);
delayMicroseconds(10);
}
delayMicroseconds(IRdelay);
//send second 16 bursts
for(int i=0; i<16; i++) {
digitalWrite(IRpin, HIGH);
delayMicroseconds(10);
digitalWrite(IRpin, LOW);
delayMicroseconds(10);
}
}
Use Bitwise-AND to set the pins you want low. Use Bitwise-OR to set the pins you want HIGH. The mask determines which bit changes.
Use PORTD as an example (Uno Pins 0 to 7). You want to only change Arduino Pin 3, which is PORTD bit 3.
To set the pin high you would do this:
PORTD = PORTD | 0x08
(the mask is: 0000 1000)
Any pins already set to a 1 will stay a 1. Pin 3 / Bit 3 will be force High no matter what.
To set the pin low you would do this:
PORTD = PORTD & 0xF7
(the mask is: 1111 0111)
Don't worry about whether some of the pins on the port are set to Input. PORTD is used to determine if the internal pull-up resistor is turned on or not. So these operations will have no affect on them.
John_S:
PORTB |= _BV(PB5); //write port B5 HIGH
PORTB &= ~_BV(PB5); //write port B5 LOW
Can that just be simply substituted for a digitalWrite command?
Yes it can. Which would make me wonder why you want to do port maniuplation if you are okay with using digitalWrite().
John_S:
Can I use a pinMode(IRpin, OUTPUT) in setup as normal? or do I need to set the pinMode with Port Manipulation for that one pin?
Port Manipulation isn't a special mode. It is just a faster way to do what digitalWrite() and digitalRead() does. If you look at the code for those functions, you'll see they are using direct port manipulation themselves.
pinMode() sets the appropriate DDRx bits for which direction the bit / pin is going to be. Since this usually isn't a time critical function it is normal to see people set the direction with pinMode() while accessing the bits directly.
Which would make me wonder why you want to do port maniuplation if you are okay with using digitalWrite().
I'm having a hard time tweaking the IR code using digitalWrite. Sometimes it works, sometimes it doesn't. I think writing to the ports will allow more accurate timing.
So, I wrote a short blink sketch. I used #define to set the hex values, now using them in the program is easy.
This compiles to 846 bytes (IDE 0023) but using digitalWrite() to do the same thing compiles to 1034 bytes. After seeing this, it's hard to think of a good reason to use digitalWrite anymore XD
#define D13high | 0x20; //hex code to write Digital Pin 13 HIGH
#define D13low & 0xDF; //hex code to write Digital Pin 13 LOW
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
for(int i = 0; i < 10; i++)
{
PORTB = PORTB D13high; //set Digital 13 HIGH
delay(100);
PORTB = PORTB D13low; //set Digital 13 LOW
delay(100);
}
while(1);
}
John_S:
So, I wrote a short blink sketch. I used #define to set the hex values, now using them in the program is easy.
This compiles to 846 bytes (IDE 0023) but using digitalWrite() to do the same thing compiles to 1034 bytes. After seeing this, it's hard to think of a good reason to use digitalWrite anymore XD
#define D13high | 0x20; //hex code to write Digital Pin 13 HIGH
#define D13low & 0xDF; //hex code to write Digital Pin 13 LOW
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
for(int i = 0; i < 10; i++)
{
PORTB = PORTB D13high; //set Digital 13 HIGH
delay(100);
PORTB = PORTB D13low; //set Digital 13 LOW
delay(100);
}
while(1);
}
int LEDpin = 13; //set LED pin
void setup()
{
pinMode(LEDpin, OUTPUT); //set LEDpin as output
}
void loop()
{
for(int i = 0; i < 10; i++)
{
portWrite(LEDpin, HIGH); //Write LEDpin HIGH
delay(100);
portWrite(LEDpin, LOW); //Write LEDpin LOW
delay(100);
}
while(1);
}
void portWrite(int pin, int state){
if (state == 1){ //write HIGH
switch (pin){
case 0: PORTD = PORTD | 0x01; break;
case 1: PORTD = PORTD | 0x02; break;
case 2: PORTD = PORTD | 0x04; break;
case 3: PORTD = PORTD | 0x08; break;
case 4: PORTD = PORTD | 0x10; break;
case 5: PORTD = PORTD | 0x20; break;
case 6: PORTD = PORTD | 0x40; break;
case 7: PORTD = PORTD | 0x80; break;
case 8: PORTB = PORTB | 0x01; break;
case 9: PORTB = PORTB | 0x02; break;
case 10: PORTB = PORTB | 0x04; break;
case 11: PORTB = PORTB | 0x08; break;
case 12: PORTB = PORTB | 0x10; break;
case 13: PORTB = PORTB | 0x20; break;
case 14: PORTC = PORTC | 0x01; break;
case 15: PORTC = PORTC | 0x02; break;
case 16: PORTC = PORTC | 0x04; break;
case 17: PORTC = PORTC | 0x08; break;
case 18: PORTC = PORTC | 0x10; break;
case 19: PORTC = PORTC | 0x20; break;
}
} else {// write low
switch (pin){
case 0: PORTD = PORTD & 0xFE; break;
case 1: PORTD = PORTD & 0xFD; break;
case 2: PORTD = PORTD & 0xFB; break;
case 3: PORTD = PORTD & 0xF7; break;
case 4: PORTD = PORTD & 0xEF; break;
case 5: PORTD = PORTD & 0xDF; break;
case 6: PORTD = PORTD & 0xBF; break;
case 7: PORTD = PORTD & 0x7F; break;
case 8: PORTB = PORTB & 0xFE; break;
case 9: PORTB = PORTB & 0xFD; break;
case 10: PORTB = PORTB & 0xFB; break;
case 11: PORTB = PORTB & 0xF7; break;
case 12: PORTB = PORTB & 0xEF; break;
case 13: PORTB = PORTB & 0xDF; break;
case 14: PORTC = PORTC & 0xFE; break;
case 15: PORTC = PORTC & 0xFD; break;
case 16: PORTC = PORTC & 0xFB; break;
case 17: PORTC = PORTC & 0xF7; break;
case 18: PORTC = PORTC & 0xEF; break;
case 19: PORTC = PORTC & 0xDF; break;
}
}
}
edit: I just ran a speed test, and the portWrite command is 30% faster than the digitalWrite command, but almost 8 times slower than the straight port manipulation.
Thanks again James. The digitalWriteFast beats all the other options!
Time for digitalWrite(): 4060
Time for true c command: 348
Time for true c command using #define: 348
Time for portWrite(): 2744
Time for digitalWriteFast(): 288