Duemilanove max pin speed

Hello all,

I wrote this little test sketch to see how fast a digital pin could change states. It was running at about 128KHz, so about 256Kbits/sec is the max output speed I figure.

Does anyone know if that really is the max speed of any one IO pin or whether that can be improved? Obviously, the introduction of any additional code will slow it down from this measurement. I'll check the datasheet too.

Cheers!

void setup() {
}
void loop(){
   digitalWrite(13,HIGH);
   digitalWrite(13,LOW);
}

Give this a gander... http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230286016

Here is the fastest I've come up with while still using the Arduino C environment while still having a close high/low 50% ratio. It's based on a little know pin toggle trick I was told about over at AVR freaks (it's also mentioned in the posted link above), but it's only available on the newer AVR mega chips, not for instance a mega 8.

int ledPin =  13;    // LED connected to digital pin 13

// The setup() method runs once, when the sketch starts

void setup()   {                
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);     
}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop()                     
{
  PINB = 0x20;
}

Lefty

void loop()
{
  PINB |= (1 << PINB5); //toggles the state of digital pin 13
}

Retrolefty,
Does my code posted above also toggle the pin state much the same way yours did?

I came across this the other day when reading the datasheet. Refer to section 13.2.2 for more details.

Edit:
Further reading in section 13.4.4 shows that what you’re doing and what I’m doing in fact the same thing, you’re simply achieving this with zero bitwise operations.

Does my code posted above also toggle the pin state much the same way yours did?

Well it certainly uses the pin toggle instruction, but by your using a 'or' function (|=) it adds a cycle, so it's about 20% slower then the one I showed. I checked them both on a scope.

Lefty

lefty,

You might squeeze out a little more speed this way:

void loop()                    
{
  for (;;)
    PINB = 0x20;
}

My theory is that looping in a for() loop is faster than calling loop() and returning to the calling routine each iteration. I’d be interested in knowing if this makes any difference.

Regards,

-Mike

My theory is that looping in a for() loop is faster than calling loop() and returning to the calling routine each iteration. I'd be interested in knowing if this makes any difference.

I tried both methods of looping and it resulted same size compiled (1018 bytes) and no difference in speed seen on the scope.

Lefty

I never realized how much 'stuff' is wrapped up into the Arduino IDE commands. On the thread linked in by Coding Badly, they talked about pin speeds of around 1/4 the clock speed with raw C statements (?). But with the overhead of the Arduino IDE, it's around 1/62 the clock speed.

I'm not complaining since I can barely even hang on when reading C code. :)

Incidentally, the code samples above don't seem to toggle the pin as expected for me. It may be that my little handheld scope is not up to the task too, since it maxes out at 5us/div. But all I get with the last few examples is a 6.25us low state every 1.025ms. I'll have to check it on my good scope.

since it maxes out at 5us/div

I'm using a Tektronics 2213 analog scope. Showing 2usec high and 2usec low bit toggle, so 4usec period = 250khz square wave.

Lefty

Incidentally, the code samples above don't seem to toggle the pin as expected for me. It may be that my little handheld scope is not up to the task too...

There is a significant difference in performance between pins that support PWM and pins that do not. In my case, a PWM pin was not suitable for generating sound while a "generic" pin was.

To truly test the differences, you will need to test digitalWrites to a PWM capable pin, digitalWrites to a "generic" pin, and the code posted by retrolefty.

[edit]Small change to try to make the paragraph above comprehensible.[/edit]

void loop()
{
  PINB |= (1 << PINB5); //toggles the state of digital pin 13
}

The statement as written above is really something one should avoid. The issue here is that PINB serves two purposes. On read it returns the input state of port B pins while on write it will toggle the output state. When combined (using |= implies read first, then write) as above it will always toggle the output state of pin B5, but it will also toggle output of any other pin on port B that happends to read high on input and this is probably not what you want.

Port B includes pins used for SPI communication as well as connections to XTAL1/XTAL2 (resonator/osccilator). If the respective pins are configured for input, you may incidentally activate/deactivate the pullup resistor for these pins.

  for (;;) {
    delayMicroseconds(10); // optional delay to control frequency
    PINB = _BV(PINB5); // B5 is LED pin on digital 13
  }

The above however is both safe and useful as it will allow for a high speed symmetrical waveform output on the pins of your choice.

Excellent observation BenF. Good catch

Which is faster? Is one seen as “better coding” than the other?

  1. PORTD |= (1 << PD5) //set digital pin 5 to HIGH
  2. PORTD |= _BV(PD5) //set digi pin 5 as HIGH

If you mean to ask is there any difference from using (1 << PD5) or
_BV(PD5), then no, they both generate the same 8 bit constant value, it’s a compiler shorthand thing, not a run time execution thing.

Lefty