This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
Duda con interrupciones externas en AVR
#1
Hola a todos, estoy comenzando a aprender el manejo de las interrupciones en AVR y tengo algunas dudas.

Estoy trabajando con un ATtiny13, cuya tabla de vectores de interrupción es esta:

[Imagen: 8aSox.png]

Como veis, sólo tiene un único vector para interrupciones externas (INT0).

Este es su pinout:

[Imagen: ATtiny13.png]

Pero según he leído en su datasheet, se pueden poner interrupciones en cualquiera de sus pines, desde PCINT5 hasta PCINT0.

Esto significa que si se utiliza una interrupción externa (PCINT0 a PCINT5), la rutina de interrupción se realizará dentro de la siguiente función:

ISR(PCINT0_vect){
//tareas a realizar dentro de la rutina de interrupción de PCINT0 a PCINT5
}

Entonces para probar esto, he hecho una simulación muy simple. He montado este circuito:

[Imagen: Kyhpz.png]

La idea es que cuando presione el botón, el led se encienda 100 ms. Quiero que se encienda únicamente cuando se presiona, es decir, cuando PB3 pase de nivel bajo a alto.

Este es el código que he escrito:

Código:
#define F_CPU 9600000UL

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

ISR(PCINT0_vect)
{
PORTB |= (1<<PB1);
_delay_ms(100);
PORTB &= ~(1<<PB1);
_delay_ms(100);
}

void SystemInit(void)
{
PCMSK |= (1<<PCINT3); // pin change mask: nos ponemos a escuchar en PB3
GIMSK |= (1<<PCIE); // habilita  las interrupciones PCINT 
sei(); // habilitamos las interrupciones globales
}

int main(void)
{
DDRB |= (1<<PB1);
DDRB |= (1<<PB3);

SystemInit();

    while (1) 
    {
    }
}

El problema es que funciona siempre que el pin cambia de estado, y yo sólo quiero que cambie cuando haya un cambio de nivel bajo a nivel alto.

He estado viendo el registro MCUCR en el datasheet:

[Imagen: interrupci%C3%B3n-externa-avr-int0.jpg]

Y he a gente que hace esto:

Código:
MCUCR &= ~(_BV(ISC01) | _BV(ISC00));

Pero no termino de entender como hacerlo.

¿Alguien me podría arrojar algo de luz por favor?

Gracias!!!
  Responder
#2
El caso que quieres es el último de la tabla, con los dos a 1:
Código:
MCUCR |= (_BV(ISC01) | _BV(ISC00));

P.D. Pon una resistencia de pulldown, para evitar estados indeterminados (desconozco como se comporta Proteus en esos casos).
  Responder


Posibles temas similares…
Tema Autor Respuestas Vistas Último mensaje
  ¿Qué programador usáis para AVR? cybero 1 1,261 12-05-2017, 03:43 PM
Último mensaje: BricoGeek
  [AVR] ¿Alguien usa USBasp? cybero 2 2,068 07-05-2017, 11:31 PM
Último mensaje: cybero
  [Proyecto] AVR Fuse Doctor cybero 14 4,390 23-04-2017, 03:50 PM
Último mensaje: cybero
  Programación para AVR. ¿Por dónde empezar? cybero 2 1,891 17-02-2017, 05:01 PM
Último mensaje: cybero
  Alguien en el foro que domine C para AVR Jaimelito 3 1,593 01-11-2015, 03:55 PM
Último mensaje: Jaimelito