digitalWrite() Instruction takes quite long

Hey everyone,

I have an Arduino Mega 2560 with 16MHz clock. I launched a simple program consisting but of the following code:

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

void loop()
{
digitalWrite(5, HIGH);
digitalWrite(5, LOW);
}

I viewed the signal on Pin 5 with an oscilloscope and found that the HIGH phase is 6.5us and the LOW phase is 7.1us, as shown in the picture below.
How can a simple instruction like digitalWrite() take several microseconds on a CPU with 16MHz? If I'm not mistaken, 16MHz means 16 machine instructions per microsecond and digitalWrite should take - just a guess - 1 up to 4 machine instructions?
Does anyone have an idea?

Thanks, M1cr0M4n

There is quite a lot of code in this function of you look at it. It does things like check to see if the pin is doing PWM and if so turns it off.
If you want it quicker then look up direct port manipulation I'm the referance section.
There are one to two cycles per machine code instruction.

How can a simple instruction like digitalWrite() take several microseconds on a CPU with 16MHz?

What makes you think its simple?

Mark

means 16 machine instructions per microsecond and digitalWrite should take - just a guess - 1 up to 4 machine instructions?

Why guess?
You have the source - take a look at it.

M1cr0M4n:
I viewed the signal on Pin 5 with an oscilloscope and found that the HIGH phase is 6.5us and the LOW phase is 7.1us, as shown in the picture below.

What picture?

M1cr0M4n:
If I'm not mistaken, 16MHz means 16 machine instructions per microsecond and digitalWrite should take - just a guess - 1 up to 4 machine instructions?

digitalWrite takes a variable as an argument. Translating that variable into a port number and a bit number takes a few machine instructions. Try the digitalWriteFast library.

http://code.google.com/p/digitalwritefast/

What picture?

This one: http://G:/ARD.jpg

Oh, that one:

http://g/ARD.jpg

Server not found

Firefox can't find the server at g.

Where is "g" when you want it?

Right between "F" and "H".

M1cr0M4n:
I have an Arduino Mega 2560 with 16MHz clock. I launched a simple program consisting but of the following code:

What useful thing does this program do?

ohhh, so everything here has to have a "use" that clears that up then lol

@Grumpy_Mike:
Thanks, I tried direct port manipulation and now the HIGH phase is 68ns an the LOW phase is 937ns.

[quote author=Nick Gammon link=topic=179928.msg1333590#msg1333590 date=1375095026]
What useful thing does this program do?

it's part of the debugging for a program that drives an open drain output with a capacitor in order to simulate a sensor signal.

I'm sorry for the picture. I thought I could upload it from a location on my computer. It's just an image of a rectangular signal (with narrow overshoots) for those who are curious.

I'm sorry for the picture. I thought I could upload it from a location on my computer. It's just an image of a rectangular signal (with narrow overshoots) for those who are curious.

Ok I'm imagining that in my mind then ...
If you want fast port manipulation use PORTX register to manipulate it

Thanks, I tried direct port manipulation and now the HIGH phase is 68ns an the LOW phase is 937ns.

You could put the pair of instructions inside their own "while (1)" loop - that should even things up.

AWOL:

Thanks, I tried direct port manipulation and now the HIGH phase is 68ns an the LOW phase is 937ns.

You could put the pair of instructions inside their own "while (1)" loop - that should even things up.

Better - put a block of HIGH/LOW pairs inside the while loop - then you can see how fast the port toggle is, and how much time is taken to loop back to the start.

cjdelphi:
ohhh, so everything here has to have a "use" that clears that up then lol

Ah well, if "useful" isn't a criteria ... :stuck_out_tongue:

Try this sketch:

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

void loop()
{
while (true)
  PINE = _BV (3);
}

2.6 MHz frequency. That's toggling its little heart out, but it still takes 4 clock cycles to do it.

00000246 <loop>:
 246:   88 e0           ldi     r24, 0x08       ; 8   (1)
 248:   8c b9           out     0x0c, r24       ; 12   (1)
 24a:   fe cf           rjmp    .-4             ; 0x248 <loop+0x2>   (2)

Seriously though, for getting a high frequency out with a good wave-form, use the hardware timers. This sort of loop will always have glitches, when interrupts fire.

Extensively discussed here: Maximum pin toggle speed - Frequently-Asked Questions - Arduino Forum