Fastest Digital Write

Hi,
i have been searching on the forum and could not find my answer so i did a small test using digital output and a scope
The picture is not the best but i can manage to get to 124nano Second or 0.000000124 Second or 0.124 micro second with this code

void setup() {                
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(13, OUTPUT);     
}

void loop() {
  PORTB |= B00100000;
  PORTB &= B11011111;
  delay(10);              // wait for 10ms
}

as per the following typical code

void setup() {                
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(13, OUTPUT);     
}

void loop() {
  digitalWrite(13, HIGH);   // set the LED on
  digitalWrite(13, LOW);    // set the LED off
  delay(10);              // wait for a 10ms
}

The fastest that we could get a output was 5 micro second

All that on a 16MHz Arduino 2009

1 Like

try this, it will affect all lines but it might be faster...

void setup() 
{                
  pinMode(13, OUTPUT);     
}

void loop() 
{
  PORTB = B00100000;
  PORTB = B00000000;
  delay(10);              // wait for 10ms
}
1 Like

Take a look at this:
http://code.google.com/p/digitalwritefast/

--- bill

  PORTB |= B00100000;
  PORTB &= B11011111;

Your code above is as fast it gets on an Arduino. The compiler optimizer will reckognize these as single bit set/clear requests and code each line using a single cycle AVR assembler instruction.

The AVR's also support a toggle bit instruction and you can code for this in C as follows:

PINB = _BV(5);

This will alternately set/clear bit 5 of PORTB (digital pin 13) and is useful when you need symmetry (50% duty cycle). This compiles to a two cycle assembler instruction.

When using a timer, it is possible to generate a 8MHz (F_CPU /2) square wave output on a 16MHz Arduino. There is also an option to output the cpu clock (16MHz) directly on PB0 (digital pin-8 for AtMega328). The latter requires reprogramming a fuse.

1 Like

Looks like you are trying to turn an output pin on for the briefest amount of time. Try this variation:

void setup() {
  pinMode(13, OUTPUT);     
  digitalWrite(13, LOW);  // Make sure the bit is off.
}

void loop() {
  PINB = B00100000;  // Toggle bit 5 on
  PINB = B00100000;  // Toggle bit 5 off again
  delay(10);              // wait for 10ms
}
1 Like

Wow,
i did try
the PINB =
and the PORTB =
without the OR and the AND
as per robtillaart and johnwasser
and this is the result
half the time (both give me the same result) 62nano seconds

One instruction cycle is 62.5 nanoseconds (16 cycles per microsecond) so I don't think you are going to get any better than that. :slight_smile:

so I don't think you are going to get any better than that

overclocking the crystal - with all kind of other trouble.... :wink:

PINB = _BV(5);

I did try this code

void setup() {
  pinMode(13, OUTPUT);     
  digitalWrite(13, LOW);  // Make sure the bit is off.
}

void loop() {
  PINB = _BV(5);
  PINB = _BV(5);
  delay(10);              // wait for 10ms
}

and got the same suprising result of 62nanosecond

1 Like

robtillaart:
overclocking the crystal - with all kind of other trouble.... :wink:

No need to "over"clock to get some improvement, the 328 is rated up to 20Mhz ]:slight_smile:

Patgadget:
got the same suprising result of 62nanosecond

Not too surprising since _BV(5) is just a macro that evaluates to the constant B00100000.

Not too surprising since _BV(5) is just a macro that evaluates to the constant B00100000.

Ok but why does it toggle?

Patgadget:

Not too surprising since _BV(5) is just a macro that evaluates to the constant B00100000.

Ok but why does it toggle?

That is what the PINB register does. Toggling an output pin without changing other bits of an output register is a fairly common thing to want to do. The PINA, PINB, PINC... registers are designed make that easy. You just write a byte with 1's where you want pins toggled and 0's where you don't want the pins to change.

Its PINX not only read?

Dirk

From the datasheet:
14.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the SBI instruction can be used to toggle one single bit in a port.

where x is the port letter (A,B,C, etc) and n is the bit within the port.

Thanks CrossRoads
then this its not ok or i misunderstand this
http://playground.arduino.cc/Learning/PortManipulation

Dirk

It is indeed that page.
Writing a 1 to an input register bit to toggle the output is not discussed tho. What I posted is from the datasheet and definitely works.