Attiny13 and External Interrupt

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

Hello,

The external interrupt INT0 on my Attiny13 doesn't work.
This is the code :

#define F_CPU 1000000UL

#include 
#include 
#include 

#define CAPTEUR PB0
#define SORTIE PB4

void init(void)
{
// config E/S

DDRB &= ~_BV(CAPTEUR);
DDRB |= _BV(SORTIE);

// config Int0

PCMSK = 0x01;
MCUCR = 0x02;
GIMSK = 0x40;
}

int main(void)
{
init();

sei();

while(1)
{

}

return 0;
}

SIGNAL(SIG_INTERRUPT0)
{
PORTB |= _BV(SORTIE);
}

I have tried everything but without result, do you have some ideas ?
Thanks

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

Wasn't the SIGNAL macro deprecated in favor of the ISR macro? Also, make sure that you are using the correct linker scripts. Check to make sure that your vector table is correct by running 'avr-objdump -d' on the resulting ELF file.

Also, use the _BV macro on all of the registers like PCMSK so that others can know what you're setting your registers to without having to dig through the data sheet!

Math is cool.
jevinskie.com

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

Well, that's the result of the command

00000000 <__vectors>:
   0:	09 c0       	rjmp	.+18     	; 0x14 <__ctors_end>
   2:	66 c0       	rjmp	.+204    	; 0xd0 <__vector_1>
   4:	20 c0       	rjmp	.+64     	; 0x46 <__bad_interrupt>
   6:	1f c0       	rjmp	.+62     	; 0x46 <__bad_interrupt>
   8:	1e c0       	rjmp	.+60     	; 0x46 <__bad_interrupt>
   a:	1d c0       	rjmp	.+58     	; 0x46 <__bad_interrupt>
   c:	1c c0       	rjmp	.+56     	; 0x46 <__bad_interrupt>
   e:	1b c0       	rjmp	.+54     	; 0x46 <__bad_interrupt>
  10:	1a c0       	rjmp	.+52     	; 0x46 <__bad_interrupt>
  12:	19 c0       	rjmp	.+50     	; 0x46 <__bad_interrupt>

...

But I'm not sure to understand. How can I check if it's good ? I read the datasheet and the external interrupt is at adresse 0x0001 of the program. :?:

I have also changed SIGNAL to ISR. :wink:

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

That has hooked the right vector. GCC lists the address as "2:" because it uses byte addressing. While Atmel datasheets say address 0x0001 because they talk in terms of word addressing but two time "0x0001" is "2:"

But when you say this doesn't work - how are you determining that? Clearly you are expecting a one time change on PB4 but how are you measuring it - is this an LED or a DVM or a scope or what? (or is this the simulator that doesn't simulate everything totally accurately?)

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

Actually, I'm using a scope on PB4 to see if the interrupt works (change from "0" to "1") and I have a push button on pin PB0 (INT0) to do a falling edge. So when I push the button, the pb4 state should changes but it doesn't :(

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

If it's active on falling edge what are you doing about pulling it up? I'd have thought you'd want a:

PORTB |= (1<<CAPTEUR);

in there somewhere to enable the internal pull-up on that pin. But whether it floats or is tied I guess that doesn't explain the non-existence of the interrupt occurring.

By the way, WHY are you writing to PCMSK? It has nothing to do with INT0 (PCINT0 is a completely different thing) and you are half enabling a different interrupt source (though luckily you didn't also set PCIE)

Oh and I have no doubt you must have already come across:

http://www.ganssle.com/debouncin...

but this will show you why it is a VERY bad idea to put a button on an external interrupting pin - far better to poll it (maybe in a timer interrupt for doing the debounce).

Cliff

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

Thank you for this pdf, it looks pretty cool :)

Basically I want to measure the frequency, so I am counting falling (or rising) edge of the signal. But it doesn't work so far, to debug it I set pin PB4 (SORTIE) to "1". The problem is, when I set pin PB0 (CAPTEUR) to "1" and after to "0", there is nothing on PB4. I think that the sub program of the interrupt isn't called.

On PB0 I have a push button with a pull-up resistor to Vcc. Also, as the length of each states is long enough, I don't have to do debouncing, but I will try some ideas of the pdf.

The program is now :

#define F_CPU 1000000UL 

#include  
#include  
#include  

#define CAPTEUR PB0 
#define SORTIE PB4 

void init(void) 
{ 
// config E/S 

DDRB &= ~_BV(CAPTEUR); 
DDRB |= _BV(SORTIE); 

// config Int0 

MCUCR = 0x02; // falling edge (00000010b)
GIMSK = 0x40; // enable interrupt INT0 (01000000b)
} 

int main(void) 
{ 
init(); 

sei(); 

while(1) 
{ 

} 

return 0; 
} 

ISR(INT0_vect) 
{ 
PORTB |= _BV(SORTIE); 
}

I've just read that I must have a I/O clock to recognize an edge, maybe that's the origin of my problem ? how can I set it on ?

Thanks for your assistance :)

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

Nobody have an idea ?

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

The way the code is written, PB4 is always HIGH. You probably want

ISR(INT0_vect)
{
PINB |= _BV(SORTIE);
}

which will toggle the value on PB4 each time the ISR is called. Even if the ISR is called multiple times due to bounce, you should see changes on PB4 with your scope.

Preston

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

Actually the problem is with the interrupt configuration. PCINT0 and INT0 are not the same. INT0 is on PB1, while PCINT0 is on PB0. If you want to catch a change on PB0 with an interrupt you have to set the PCIF bit in GIFR.

EDIT:

You must also use the PCINT0_vect if you want to catch a change on PB0 with an interrupt. It does not help that the pin name PCINT0 is named the same as PCINT0 the interrupt vector, as the interrupt vector PCINT0_vect is used to catch a change on any of the PCINTx pins.

Last Edited: Tue. Apr 22, 2008 - 04:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The way the code is written, PB4 is always HIGH.

No, it is high after the first interrupt. It should start out low. Toggling in the interrupt would not be a good idea right now since the OP is doing nothing about bounce.

#define CAPTEUR PB0 

By this I assume that you are using PB0 as the interrupt pin? If you are, it is incorrect. That is PCINT0, not INT0. INT0 is PB1 (pin 6).

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:
No, it is high after the first interrupt.

Yes, that is correct. My bad.

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

:|

Pin PCINT0 isn't the same of INT0 ! INT0 is on PB1 :twisted:

Thanks a lot !! :D