I/O Control with help of Interrupt!

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

Hi, I try to find any tutorial about I/O control with help of interrupt, but the best ting I found was
"Newbie's Guide to AVR Interrupts" , I read it.. and write som code out of this..

I try just to learn how Interrupt works! That is all, so this program have no point without my experience in interrupt subject..

I write this code, if PD2 (INT0) make any change (High or Low) so turn off or turn on the LED, just to see this works.. But nothing happend when i run this..

I use: Atmega8

int status = 0;

int main(void){
	setOutput(&DDRC, 0);
	setLow(&PORTC, 0);

	//give status, give sign for any logical
	setLow(&MCUCR, ISC01);
	setHigh(&MCUCR, ISC00);
	//enable INT0, PortD.2
	setHigh(&GIMSK, INT0);
	
	sei(); //Enable global Interrupt


	while(1){
	}

}


ISR(INT0_vect) 
{ 
	if(status == 0){
		setHigh(&PORTC, 0);
		status = 1;
	}else{
		setLow(&PORTC, 0);
		status = 0;
	}
	
}

Very simple..
1- choose output for LED and normaly off
2- Out of datasheet I can choose 2situation, bit ISC01(low) and ISC00(high) on Register MCUCR is means run event with every logical change... no matters high or low..
3- Enable Interrupt for INT0 bit INT0 on GIMSK Register
4- Enable Global Interrupt..

NB! setHigh and setLow is just function i have write for myself, and they WORKS!

One more time, I just try to learn how interrupt works.. So if you have any idea what is wrong here, or something i should know, let me know :=)

Thanks

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

First off, say which AVR you are using. My crystal ball says ATtiny2313.

Then download the relevant data sheet and look up the register description for MCUCR, GIMSK etc.

Make sure that you have got the right bits in the right special function register.

Otherwise, your code looks fairly sensible. However I would use the 'internal pull-up' on your INT0 pin. (unless you promise me that you already have an external resistor --- pull-up or pull-down)

It is worth posting your setlow() function. It is a strange way of doing things.

David.

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

If you're using some form of switch to trigger the interrupt (including just poking a wire onto Vcc or GND) you're going to get multiple interrupts each time from contact bounce. If you toggle on each interrupt the effect will be that sometimes the interrupts seem to work and other times they don't.

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

David:
I use Atmega8, and Im sure about datasheet and Regiser..
because i use name and not number of pin, and I read datasheet for Atmega8
Yes - I dont understand why I put setLow(), maybe just for be sure to I have low on the ICS01 (yes I know about defualt value is 0)..

kk6gm:
I think you have right.. I dont use any kind of button,
I just connect the input pin to VCC and GND..
But I think I got your point.. You means the event runs a lot of times
Is that any way to just declare event just runs one time?
Or should I connect this to button?
What do you think should I do for use I/O (button) and dont get multiple interrupts?

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

It depends on how 'clean' your INT0 signal is. e.g. the output from a switch is likely to bounce.

You will interrupt immediately. (INT0 is highest IRQ priority).

So you can disable further INT0 interrupts in your ISR().

If you are reading a switch, you possibly just debounce in software. There is seldom any need for a very fast response.

David.

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

Quote:

setHigh(&GIMSK, INT0);

Are you sure that you are building for and using a Mega8? My datasheet shows no I/O register with that name on a Mega8.

Lee

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

arian88 wrote:
kk6gm:
I think you have right.. I dont use any kind of button,
I just connect the input pin to VCC and GND..
But I think I got your point.. You means the event runs a lot of times
Is that any way to just declare event just runs one time?
Or should I connect this to button?
What do you think should I do for use I/O (button) and dont get multiple interrupts?

Connecting to a button won't fix the problem, since buttons bounce too - see this scope pic for an example:

http://hackaday.com/2010/10/13/o...

The solution is to add the time element into the signal detection. There are many ways to do this. A simple way is to delay a certain amount after first detecting a "push" before looking again, giving the button time to finish bouncing. If the "push" is still active after this time delay, it's a valid push.

For switches/buttons, this delay is typically between 20 and 30 ms (others may offer other numbers, it depends a lot on the physical construction of the switch/button).

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

the new code:

int status = 0;

int main(void){
	setOutput(&DDRC, 0);
	setLow(&PORTC, 0);

	//give status, give sign for any logical
	setHigh(&MCUCR, ISC00);
	//enable INT0, PortD.2
	setHigh(&GICR, INT0);
	//Enable global Interrupt
	sei();
	
	while(1){
	}

}


ISR(INT0_vect) 
{ 
	//delat in 50milliSec
	_delay_ms(50);

		if(status == 0){
			setHigh(&PORTC, 0);
			status = 1;
		}else{
			setLow(&PORTC, 0);
			status = 0;
		}
	
}

Lee:
You had right, I have read a lot of tutorials from different places and about different mC and that make me confused, but now after see in the Atmega8 datasheet I found we have GICR insted of GIMSK, and register GICR have a bit name of INT0, and this make INT0 enable, right? I have fix this in new code...

kk6gm:
I write new code, and in this when ISR runs, then we meet a delay in 50milliS..
and then turn on or off the LED, but still nothing happens when i run this code..
I think everytime I use _delay_ms in ISR (the same as timer interrupt), the program dont works as the should

Attachment(s):