View Single Post
Old 08-30-2013, 05:17 PM   #25 (permalink)
t vago
MPGuino Supporter
 
t vago's Avatar
 
Join Date: Oct 2010
Location: Hungary
Posts: 1,807

iNXS - '10 Opel Zafira 111 Anniversary

Suzi - '02 Suzuki Swift GL
Thanks: 828
Thanked 708 Times in 456 Posts
Quote:
Originally Posted by nickdigger View Post
We've got a one-for-three match:
Code:
  EIMSK= (1<<INT0);
  EICRA= (0<<ISC01) | (1<<ISC00);
Why are you shifting a zero?

Quote:
Originally Posted by nickdigger View Post
I have nothing for EIFR. Atmel says EIFR is always cleared (set to 1) when INT0 is config'd as a level interrupt. Nothing for EIFR in the dual-pin setup either, and it works. Not sure if you typo'd the (1 < INTF0) in your code, or just a cut+paste typo.
It would, of course, help to not assume that I just make typos and other errors.



Kindly take note of that last sentence - This flag is always cleared when INT0 is configured as a level interrupt. As I am configuring INT0 as a change interrupt, not a level interrupt, this last sentence does not apply. Also, we don't want the interrupt to immediately fire off once a sei() instruction is executed to re-enable interrupts. Therefore, it is imperative to clear any pending interrupt condition for a given interrupt, prior to enabling said interrupt. You just don't know what you're going to get, otherwise.

Quote:
Originally Posted by nickdigger View Post
The ISC00 and ISC01 would be 11 for RISING, 10 for FALLING, 01 for CHANGE, 00 for LOW.. You seem to be... setting yours to 00 ?
Let's go over my logic for EICRA, shall we?

The term takes something in parentheses, then logic-ORs it with another term. This result is then written back to EICRA.

From elementary mathematics, the stuff in parentheses has priority over the other stuff. The innermost parentheses term gets evaluated first. That would be:

The below term shifts a 1 leftward by a value determined by the constant ISC01. It happens to evaluate to 2, or 0b00000010.

Code:
(1 << ISC01)
Next, that term is ones-complemented by the ~ operator. This turns the value into 253, or 0b11111101.

Code:
~(1 << ISC01)

or

~(0b00000010)
Then, the value is logic-ANDed with whatever is in EICRA. This has the effect of turning off bit 1 in the value stored in EICRA.

Code:
(EICRA & ~(1 << ISC01))

or 

(EICRA & 0b11111101)
There's another term in parentheses - this one:

Code:
(1 << ISC00)
As ISC00 is a constant 0, this term happens to evaluate to 1 << 0, or 1, or 0b00000001.

So, moving onto the expression, we have:

Code:
(EICRA & ~(1 << ISC01)) | (1 << ISC00)

or

(EICRA & 0b11111101) | 0b00000001
We logic-OR the (1 << ISC00) with the modified value. Finally, the modified value is written back to EICRA.

This technique has the effect of modifying only the lowest two bits in EICRA, leaving the other bits alone. This is standard practice whenever hardware registers are modified at the bit level. It ensures that only the desired bits are messed with, and leaves the other bits alone.

This technique avoids all sorts of subtle bugs that are caused by brute-force writing a value to a hardware register that controls more than one hardware feature. This would include features that aren't being used, or that are used for something else in your program, or are not yet implemeted in the hardware you're testing the program in.

This technique also lets everyone else who is reading your code know that you meant explicitly to set the bits as you have. It avoids ambiguity caused by something like (0 << ISC01), which otherwise makes no sense.
Attached Thumbnails
Click image for larger version

Name:	20130830 - AtMega8-168-328p72.png
Views:	409
Size:	33.2 KB
ID:	13697  
  Reply With Quote