Modifying Elliot William's hellointerrupt.c from Interrupt0 to Interrupt1

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working my way through Elliot Williams' "Make: AVR Programming" book.

 

My strategy has been to compile the examples, flash them to a breadboard with 328 PU processor, and after correcting my wiring mistakes, play with the code until I understand it.

 

I'm looking at helloInterrupt.c on page 159.

 

It works fine as written.  Light on LED0 blinks at speed and when button pushed, light on LED1 goes on and LED0 continues to flash at speed.

 

If I change references to Interrupt0 to interrupt1, LED0 flashes erratically--sometimes at speed, sometimes very slowly.  Pushing the button lights up LED1 as you would expect and LED0 stays flashing, but at variable speed.

 

Here's the code-- my changes are to add ISR(INT1_vect) and initInterrupt1(void), and call that initialization instead of initInterrupt0(void) from main.

I thought INT1 and INT0 were basically the same.  Can someone set me straight, please?

 

/*

Demo of using interrupts for doing what they do best --
two things at once.

Flashes LED0 at a fixed rate, interrupting whenever button is pressed.

 */

// ------- Preamble -------- //
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "pinDefines.h"

/* working */
ISR(INT0_vect) {         // Run every time there is a change on button 
  if (bit_is_clear(BUTTON_PIN, BUTTON)) {
    LED_PORT |= (1 << LED1);
  }
  else {
    LED_PORT &= ~(1 << LED1);
  }
}

/* problems */
ISR(INT1_vect) {         /* Run every time there is a change on button */
  if (bit_is_clear(BUTTON_PIN, BUTTON)) {
    LED_PORT |= (1 << LED1);
  }
  else {
    LED_PORT &= ~(1 << LED1);
  }
}

void initInterrupt0(void) {
  EIMSK |= (1 << INT0);                                 /* enable INT0  -- works */
  EICRA |= (1 << ISC00);                /* trigger when button changes */
  sei();                          /* set (global) interrupt enable bit */
}

/* switching from the 0 to 1 defines doesn't work */
void initInterrupt1(void) { // was 0
  EIMSK |= (1 << INT1);                                 /* enable INT1 -- problems */
  EICRA |= (1 << ISC01);                /* trigger when button changes */ 
  sei();                          /* set (global) interrupt enable bit */
}

int main(void) {
  // -------- Inits --------- //
  LED_DDR = 0xff;                                   /* all LEDs active */
  BUTTON_PORT |= (1 << BUTTON);                              /* pullup */
  //initInterrupt0();
  initInterrupt1();

  // ------ Event loop ------ //
  while (1) {

    _delay_ms(200);
    LED_PORT ^= (1 << LED0);

  }                                                  /* End event loop */
  return 0;                            /* This line is never reached */
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know if this is the problem:

/* switching from the 0 to 1 defines doesn't work */
void initInterrupt1(void) { // was 0
  EIMSK |= (1 << INT1);                                 /* enable INT1 -- problems */
  EICRA |= (1 << ISC10);                /* trigger when button changes */ 
  sei();                          /* set (global) interrupt enable bit */
}

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kujira wrote:
Elliot Williams' "Make: AVR Programming" book

This:

 

http://shop.oreilly.com/product/...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That works better--LED0 continuously blinks at speed.  But the button press is frequently missed.  Hmmm....

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kujira wrote:
But the button press is frequently missed.
Is it missed or does it bounce?

 

To be honest if a book about micros is telling you to use ext-int interrupt sources to read buttons it's actually a very poor book! ext-int is the LAST thing you would want to use to read a button in reality because of "bounce".

 

Hopefully the book will continue on to point out the mistake in this early design and show how it can be corrected by switching the button reading to a polling timer interrupt which is the better solution. If it doesn't do this it really IS a poor book.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think polling timer interrupts are handled later.  This is a first example of external interrupts.  Any idea why the bounce problem, if that is what it is, never shows up with int 0? 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  EICRA |= (1 << ISC10);                /* trigger when button changes */ 

 

That should probably be:

  EICRA |= (1 << ISC11);                /* trigger when button changes */ 

 

Never mind, had a look at the original code.  It was ISC00.  So Greg is right, you want ISC10.

 

Any idea why the bounce problem, if that is what it is, never shows up with int 0? 

Luck.  The mode suggested by @Greg_Muth was toggling on any edge instead of on the falling edge only, which would change the way in which bounce would manifest.  Nevertheless, bounce is an issue with any mode, and must be addressed.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Thu. Nov 23, 2017 - 06:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting.  I'll have to look into this some more.  Am aware about bounce; curious as to why really doesn't seem to happen with int0. Appreciate all the replies.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kujira wrote:
... curious as to ...

 

Get out the 'scope, and look at the signals right on the AVR pins.  Implement code that actually counts the invocations of each ISR.  Show diagrams and pictures of the connections in both cases.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Get out the 'scope, and look at the signals right on the AVR pins. 

+1

 

For example, as Jack Ganssle has done in his article on contact bounce & debouncing: http://www.ganssle.com/debouncing.htm

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm a little confused with the test conditions.

 

OP is going through a worked example from the book, that works with INT0.

 

Now, indeed I might say to myself "I've got this '328 board that I can use for the experiments, but INT0/PD2 isn't available so I'll set it up on INT1/PD3".

 

But OP apparently set up the experiment on PD2, it worked fine, and then decided to switch the trigger circuitry and code over to PD3?  Is that the correct sequence of events?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kujira wrote:
If I change references to Interrupt0 to interrupt1, LED0 flashes erratically--sometimes at speed, sometimes very slowly. Pushing the button lights up LED1 as you would expect and LED0 stays flashing, but at variable speed.

BTW, bouncing doesn't explain the "variable speed", does it?  Unless perhaps the interrupt is being triggered so often/fast that it visibly affects delay_() timing...  Either noise on a floating input, or "low level".  I'd have to examine the code and setup closely.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Nov 24, 2017 - 03:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did not change the circuitry, button is still attached to PD2.  So.............I have now changed code like this:

ISR(INT1_vect) {         /* Run every time there is a change on button */
  //if (bit_is_clear(BUTTON_PIN, BUTTON)) {
  if (bit_is_clear(BUTTON_PIN, BUTTON2)) {

 

and

int main(void) {
  // -------- Inits --------- //
  LED_DDR = 0xff;                                   /* all LEDs active */
  //BUTTON_PORT |= (1 << BUTTON);                              /* pullup */
  BUTTON_PORT |= (1 << BUTTON2);                              /* pullup */

 

and it is working as expected now.  Does this mean int1 cannot be associated with PD2, only PD3?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From the datasheet:

PD2 may be used for INT0 or PCINT18

PD2 may be used for INT1, OC2B or PCINT19

 

elsewhere in the datasheet:

 

 

 

David (aka frog_jr)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kujira wrote:
Does this mean int1 cannot be associated with PD2, only PD3?

Yes.

 

This should be clear from the data sheet, e.g. figures 5-1, 5-2, 5-3 and 5-4. And table 6-1. And (in section 18.3.3 Alternate Functions of Port D) tables 18-9 and 18-11, and first bullet entry on page 112.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah.

 

Notably lacking from the author's code are definitions for BUTTON_PORT and BUTTON.

 

I guess we all just assumed that they had been correctly defined elsewhere.  Everyone except Lee, of course ;-)

 

What I hadn't noticed either is that, as a trivial example, this code doesn't really benefit from debouncing, since the ISR simply reflects the button state in the state of the LED, rather than toggling the LED (or a flag).

 

The problem you were seeing is that the pin associated with INT1 was not connected to the button at all, and was left floating.  As such, it would take on an effectively random value.  The adjacent pin, to which you had connected your button, would be somewhat coupled (capacitively) to the INT1 pin, which would explain why it would respond erratically when you pressed the button.

 

Move the button to the correct pin, and define BUTTON correctly.  It was likely defined as 2 (or PD2, or similar), but should be 3.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I appreciate all of your comments.  Most informative. Obviously a lot to learn for a long-time software guy.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kujira wrote:
Obviously a lot to learn for a long-time software guy.

Yup.

 

I have no knowledge of the book you're reading but am fairly convinced (based on previous experiences, correspondence etc) that you always need the data sheet as the definitive reference. I suggest you download it to your local machine and have a first quick browse through it - just to know roughly what it covers and how it is organized. When you read some specifics in your book, try to make a habit of double-checking if/where/how it is covered and described in the data sheet. Soon you'll know your way around it and it will become very usable.

 

One nice thing is that if/when you move on to another AVR model you will feel quite at home in the new data sheet. They are all similarly organized.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Book actually makes the same point.  Curiously, though, its AVR pinouts diagram that frog_jr posted from the datasheet don't have the INT0, INT1 names after the PCINT18,19 names.  Maybe that's why it says to go to the datasheet!  Old Japanese proverb: Mochi ga, mochi ya (For ricecakes, go to the ricecake maker).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
you always need the data sheet as the definitive reference. 

Absolutely!!

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kujira wrote:
Curiously, though, its AVR pinouts diagram ... don't have the INT0, INT1 names after the PCINT18,19

probably just for brevity/clarity.

 

As you can see, some of the pins have several "alternate" functions - so it can get a bit cluttered & hard to read ...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...