ATtiny817 External Interrupt Generation

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

I am using PORTA PIN6 of ATtiny817 as input pin (source of external interrupt), I have a connected external momentary push button with external pull up resistor making it as default high . When the running following code I am not able to get any interrupt.But with polling method I am able to detect the change in state of the Pin.Why not with interrupt?


#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint8_t LEDupdtFlg;

ISR(PORTA_PORT_vect)
{
	LEDupdtFlg = 1;
	PORTA.INTFLAGS = PIN6_bm;
}

int main(void)
{
	PORTA.DIRCLR = PIN6_bm;
	PORTC.DIRSET = PIN2_bm;
	PORTA.PIN6CTRL |= 0X5 ;
 
    while (1) 
    {
		if(LEDupdtFlg){
			LEDupdtFlg = 0;
			PORTC.OUTSET = PIN2_bm;
		}
		else
			PORTC.OUTCLR = PIN2_bm;
	}
}

 

 

Thanks,

Jaivvignesh | Associate Firmware Developer

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

Just to say, before you go any further, that because of  http://www.ganssle.com/debouncing.htm using "momentary" buttons on external interrupts is a REALLY bad idea (point being that "momentary" actually mean 10..50 times in a few milliseconds)

 

Anyway the first thing I spot in that code is actually the thing I DON'T spot and that is an "sei()". If you don't turn on the global interrupt system you are never going to get any interrupts!

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

Jaivvignesh wrote:

PORTA.PIN6CTRL |= 0X5 ;

Sorry I'm not familiar with these new 1 series AVR's yet, but your use of a hex constant seems odd, usually both nibbles are specified, i.e. 0x05 or 0x50.

Also the uses of magic numbers is discouraged, best to use bit names so code is self documenting...

I also do not see where you enable interrupts in the code, usually with a sei() macro or similar.

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

 

Jim, the mysterious 0x05 (I had to look it up) is the "LEVEL" entry in this:

 

 

I do kind of wonder if maybe the .h file doesn't already have defines for INTDISABLE, BOHTEDGES etc.

 

EDIT: quick dip into header reveals:

/* Input/Sense Configuration select */
typedef enum PORT_ISC_enum
{
    PORT_ISC_INTDISABLE_gc = (0x00<<0),  /* Interrupt disabled but input buffer enabled */
    PORT_ISC_BOTHEDGES_gc = (0x01<<0),  /* Sense Both Edges */
    PORT_ISC_RISING_gc = (0x02<<0),  /* Sense Rising Edge */
    PORT_ISC_FALLING_gc = (0x03<<0),  /* Sense Falling Edge */
    PORT_ISC_INPUT_DISABLE_gc = (0x04<<0),  /* Digital Input Buffer disabled */
    PORT_ISC_LEVEL_gc = (0x05<<0),  /* Sense low Level */
} PORT_ISC_t;

So I guess he meant PORT_ISC_LEVEL_gc rather than just the anonymous looking 0x05 ?

 

The next mystery is why he used |= with the 0x05 rather than the more obvious = assignment operator ?

Last Edited: Fri. Oct 11, 2019 - 02:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, I posted duplicate info ( need for sei() ) and cannot delete the post, so I'll change it to something more useful.

 

The sei() will get you going in the right direction. One thing to keep in mind on these pin interrupts, is if you invert the pin, you get the opposite of what you are expecting. You can have a level interrupt for the high condition if you invert the pin, for example. In my pin drivers, I set the invert bit when I want inverted use (low=on), so I can then treat them all the same (1=on).

 

A simple test below. Since I define the switch as being low=on, I invert it so .ison() will return true when pin is low, but when using a pin interrupt I still have to use the opposite pin interrupt level (which more code could solve).

 

//ATTiny 416 Xplained Nano
#include <stdint.h>
#include <stdbool.h>
#include "Port.hpp"
#include "Cpuint.hpp"

 

#define F_CPU 3333333ul
#include <util/delay.h>

 

PB5_OUTL_t led; //ouput, low is on
PB4_INLPU_t sw; //input, low is on, pullup
volatile bool sw_triggered = false;

 

int main(){

    //falling edge - (pin is inverted)
    sw.in_mode(Pins::RISING);

    Cpuint::set_func( Cpuint::PORTB_INT,
        [](){
            sw_triggered = true;
            sw.flagclr();
        }
    );
    Cpuint::on( true ); //global irq on

 

    for(;;){
        if( not sw_triggered ) continue;

 

        led.on();
        _delay_ms(200);
        led.off();
        sw_triggered = false;
    }
}

Last Edited: Sat. Oct 12, 2019 - 12:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
The next mystery is why he used |= with the 0x05 rather than the more obvious = assignment operator ?

 

The worst part is that, if the objective was to preserve the other bits, this is not the right way because we are talking about a bit group, not a single bit.

 

The correct way to preserve other bits would be:

PORTA.PIN6CTRL = (PORTA.PIN6CTRL & ~PORT_ISC_gm) | PORT_ISC_LEVEL_gc;

 

Though I don't think "level" is the way to go, probably "both edges" and then the ISR sets the flag accordingly.