Go Down

Topic: Arduino - Coding without delays using program Ticks (Read 2035 times) previous topic - next topic

mixania

I like how this post became into a "hot" post  :P  :)
Arduino Uno R3
Mac OSX Lion

westfw

Quote
Code: [Select]
PINB = PINB | _BV (5);
What if input zero is already high?  We end up with this...
  :
...which toggles two pins!

This is actually a really interesting question.
Code: [Select]
PORTB |= _BV(5);
is well-known to compile down to a single "set bit in IO register" (sbi) instruction.  If it didn't, the assembler-lovers would gloat too much.
The sbi instruction, theoretically, does a read-modify-write of the bytewide port, down at the hardware level (which is why it takes two cycles rather than just one.)
But the datasheet EXPLICITY says that "the SBI instruction can be used to toggle one single bit in a port", so it's not quite as straightforward as that.
PROBABLY, the statement above will compile to a single sbi instruction (at least with optimization on), and probably it will only toggle the single bit.

But wait - not all of PINx registers are reachable by "sbi."  If you were working with PINL on a MEGA, the compiler would have to generate a read, or, and out instructions.  And it would behave DIFFERENTLY...

What fun!

Coding Badly

What fun!


No doubt!

So, to illustrate the problem on an Uno we need to cripple the optimizer.  This may do it...
Code: [Select]
#define ALT_PINB  (*((uint8_t volatile *)0x23))
...
  ALT_PINB = ALT_PINB | _BV(5);


Coding Badly

I've been searching my history for where I got that "  PINB |= _BV (5) is better than PINB = _BV (5) " technique from.


It is not a question of which is better.  It is a question of which is correct.  This is simply not correct...
Code: [Select]
PINB |= _BV (5);

As @westfw described, that it works at all is an accident (a side-effect of the compiler's optimization, the AVR instruction set, and the location of the PIN register in the I/O space).

Go Up