Display 7 segmentos 4 dígitos con PIC16f84A fallo de luminiscencia...

Buenas,

gracias por tus contestaciones.

Aquí van mis respuestas:

Ok.

Empezá a descartar cosas:

1. Si tenés protoboard, probá todos los segmentos de un dígito conectandolo a 5v con una resistencia limitadora de 150 Ohms y verificá que todos encienden bien.

Si conecto uno a uno con Proto, la resistencia de 147ohm y a 5V, se ven bien los segmentos A y B.

Modificá el código para que solo encienda 1 digito y verificá que todos los segmentos encienden bien.
Si modifico el códgio para que muestre 4 dígitos sin que sean distintos del mismo en todos, es decir: 4 4 : 4 4 ó 2 2 : 2 2, se ven todos bien iluminados y correctamente.
¿A todos los segmentos le pusiste resistencias de 220Ohms?
Sí, todas las salidas de los 7 segmentos tienen una R de 220 ohm.

saludos, gracias por contestar.. :)

p.d.
Me doy cuenta de que cuando muestro 1 dígito distinto en cada dígito del 7-seg-4-digit es cuando falla la luminiscencia. va a ser fallo de que el refresco es demasiado alto, ¿no?

En fin.. no sé que puede ser...
 
Última edición:
Los errores más comunes de código en el refresco pueden ser:

  1. Darle poco tiempo a un cierto dígito. Pero en este caso sería raro, ya que el resto de los segmentos si te funcionan bien.
  2. Cuando cambias de dígitos, antes de deshabilitar el dígito anterior ya estás colocando el valor del próximo dígito, esto genera un efecto "fantasma".
  3. Habilitar dos o más dígitos a la vez.

Secuencia correcta para el cambio de dígito:

  1. Todos los dígitos deshabilitados.
  2. Coloco en el puerto el valor del próximo dígito.
  3. Habilito el dígito.
  4. Dejo el dígito encendido el tiempo necesario.
  5. Repito desde 1.

Hacé una prueba bien simple, asigná 4 valores distintos a c/dígito y hacé un refresco lento, es decir que tarde entre 1 o 2 seg para ver si la secuencia programada es la correcta.
 
Última edición:
Amigo mio, eres un ¡¡¡genio!!! El error fue mio desde que cambiamos la polaridad en los pines VCC jojojo
Al estar a 0 continuamente se encendían los 2 puntos del centro, lo que hacía que perdiese intensidad en los demás segmentos!
¡¡Bien, pues eso, solucionado!!

Jojojo

muchas gracias amigos, es un placer encontrar gente como uds.
gracias, gracias, gracias... ¡un abrazo! jjajajaja

Adjunto fotos del resultado ;)
 

Adjuntos

  • 20131020_225907_mini.jpg
    20131020_225907_mini.jpg
    108.3 KB · Visitas: 25
¡Buenas de nuevo!

Me conecto para plantearos unas dudas que tengo, en forma de preguntas!

claro, como si no iba a ser.. jojojo

veréis:

1. cuando le pongo 4 pilas recargables de 1.2V, el display de ve bien, pero lo deje conectado y al día siguiente se veía un tanto flojo. Al volver de clase, se veía solo el segundo digito y los dos puntos ':'. (Los demás muy flojos...) ¿Es esto que la bateria está descargándose? ¿O que requiere de algún componente más?

2. ¿Cómo puedo medir lo que consume el circuit? Probé a conectarle el miliamperímetro en serie y me marcaba .02A. pero lo que me paró fue que solo se encendía el primer dígito.. :LOL:

3. Quiero colocarle 2 botones pulsadores. Y quiero hacer la lectura en el mismo pin, poniendo 2 resistencias diferentes en cada botón, para diferenciar el valor analógico y poder operar... ¿Se puede hacer esto con el pin RA4? Siendo así, podría buscar en google códgio ejemplar...

Gracias cosme, amigo, por tu "me gusta"! Y gracias, muchas gracias, de nuevo, por tu gran ayuda, ¡Estoy muy conteto!

Un saludo.
 
...1. cuando le pongo 4 pilas recargables de 1.2V, el display de ve bien, pero lo deje conectado y al día siguiente se veía un tanto flojo. Al volver de clase, se veía solo el segundo digito y los dos puntos ':'. (Los demás muy flojos...) ¿Es esto que la bateria está descargándose? ¿O que requiere de algún componente más?

4 pilas en serie dan 6v (con pilas a full), ¿cómo limitas a 5v?

...2. ¿Cómo puedo medir lo que consume el circuit? Probé a conectarle el miliamperímetro en serie y me marcaba .02A. pero lo que me paró fue que solo se encendía el primer dígito.. :LOL:

Amperimetro en serie entre la fuente de alimentacion y el Vcc del circuito. Yo creo que rondará entre 70 a 120mA, poco más poco menos.

3. Quiero colocarle 2 botones pulsadores. Y quiero hacer la lectura en el mismo pin, poniendo 2 resistencias diferentes en cada botón, para diferenciar el valor analógico y poder operar... ¿Se puede hacer esto con el pin RA4? Siendo así, podría buscar en google códgio ejemplar...

No entiendo, ¿valor analógico en puertos digitales?¿Qué aplicación necesitás hacer con los botones?

Mira que solo tenés una interrupción externa.
 
Uhm... buenos días cosme; amigo ;)

te cuento:

4 pilas de 1.2 en serie, teoría dan 4.8V; lo medí con el voltímetro y rondaba los 5V...

Ok, debe ser problema del amperímetro porque no tengo fusible y estaba midiendo con el de 20A max... y seguramente lo conecté en GND jojo...

Pues, la idea es poner en hora el reloj, o cualquier otra aplicación con tiempos: pulsar durante 2 segundos, pulsar en menos de 1.3 segundos varias veces, etc... todo esto para controlar el un poco el aparato...
Yo es que no sé si el 16f84A tiene alguna entrada analógica, no lo he mirado a fondo, pero por ejemplo en arduino, los pines A0 hasta el A5 creo, son configurables como analógicos o digitales.
La idea era colocar una resistencia en cada boton de diferente valor, para leer un valor analógico diferente; pero claro, hace falta un pin ADC, ¿no? ¡Pues es que no sé si tiene! jojo

Respecto a la interrupción externa, si no me equivoco, solo podría lanzarla con 1 botón, ¿no? conectándolo a VCC o a GND y configurándola como Rising o lo otro que no recuerdo... :LOL:

Bueno, amigo, gracias por tu contestación y que pases un buen día. Me dispongo a ir a clase.

Un saludo!
 
Uhm... buenos días cosme; amigo ;)

te cuento:

4 pilas de 1.2 en serie, teoría dan 4.8V; lo medí con el voltímetro y rondaba los 5V...c

Ok, solo digo, tené cuidado cuando las baterías están totalmente cargadas, en esa situación pueden llegar a tener 1,5v c/u por un cierto tiempo hasta que se descargan, ej. la baterías de 3,6v (3 celdas de 1,2v c/u) a máxima carga pueden llegar a 4,5v.

Yo es que no sé si el 16f84A tiene alguna entrada analógica, no lo he mirado a fondo, pero por ejemplo en arduino, los pines A0 hasta el A5 creo, son configurables como analógicos o digitales.

Mirá la hoja de datos del 16f84, olvidate del arduino.

La idea era colocar una resistencia en cada boton de diferente valor, para leer un valor analógico diferente; pero claro, hace falta un pin ADC, ¿no? ¡Pues es que no sé si tiene! jojo

Nuevamente, ver hoja de datos.

Respecto a la interrupción externa, si no me equivoco, solo podría lanzarla con 1 botón, ¿no? conectándolo a VCC o a GND y configurándola como Rising o lo otro que no recuerdo... :LOL:

Si, pero como alternativa se me ocurre que podrías hacer un barrido, es decir usar 3 pines:

  1. Pin que tiene la interrupción externa.
  2. Pin 1 que hace de gnd o vcc.
  3. Pin 2 que hace de gnd o vcc.

La idea es por ej. configurar la externa para que detecte flancos descendentes (pin configurado como pull-up), y de ese pin conectar dos pulsadores, uno que vaya a Pin 1 y otro que vaya a Pin 2. Entonces con el soft deberías todo el tiempo cambiar de estado Pin 1 y Pin 2 (cuando uno está en Vcc, el otro en Gnd), solo se detectará aquel pulsador que fue presionado y que en ese momento su Pin estaba a Gnd. Obviamente el barrido deberías hacerlo con suficiente velocidad, yo le calculo que 75mS como máximo para el cambio de estado de c/ Pin.
 
Buenas,

en primer lugar, mis disculpas por la ausencia de respuesta.
en segundo lugar, decir que muchas gracias por la respuesta.

y por último punto de esta entrada, decir que cambie la configuración de pines, para tener RB0/INT disponible para el botón.

Se me ocurre generar interrupciones con el <<push button>> (si es que fuera posible) y así, según los tiempos de pulsado, y la frecuencia con la que se pulsan, poder actualizar la hora del pic.

Me pregunto qué es lo que falla... conecté el botón como muestran todos los ejemplos de internet, google.com. Es decir, una resistencia de 4k7 entre GND y VCC el botón. Más o menos creo que es así de memoria.

Ahora tengo RA4, que es open-drain, como el que ilumina los ':' del 7 seg, gracias a tu gran idea de poner transistores... ha sido posible poner esta maravilla en marcha y dejar un pin con interrupción o que pueda leer/escribir.

Lo que hice fue activar las interrupciones, (GIE), (que ya estaban activadas antes...=) y/o después configuré RB0 como INT en vez de como RB0, valga la redundancia. Me pregunto, por qué al pulsar el botón, se vuelve loco el "circuito"... es decir, puse que si apretaba el boton, el pic se pone en modo MANUAL_PROG, y si lo vuelvo a apretar, se pone en DEF_MODE. Pero no funciona bien, porque si apreto el botón, debería aparecer 6666 y si lo vuelvo a apretar, debería salir la hora. Pero salen los 2 números entrecruzados... a veces pulso rapido o varias veces el boton y se queda en un modo, y si lo repito, se mueve al otro... me da que no entiendo bien lo que es una interrupción, ni cómo funciona tampoco... jojojo.

Una ayudita mi gran amigo argentino?

Gracias por todo, a todo el foro, sois unos grandes maestros.


Saludos,

abelillo.

A continuación os dejo el código, por si os hiciera falta ;)

Código:
/* ----------------------------------------------------------------------- */
/* Template source file generated by piklab */
#include <pic16f84a.h>

/* ----------------------------------------------------------------------- */
/* Configuration bits: adapt to your setup and needs */
typedef unsigned int word;
word __at 0x2007 CONFIG = _XT_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF;

#define BIN(x) \
( ((0x##x##L & 0x00000001L) ? 0x01 : 0) | ((0x##x##L & 0x00000010L) ? 0x02 : 0) | ((0x##x##L & 0x00000100L) ? 0x04 : 0) | ((0x##x##L & 0x00001000L) ? 0x08 : 0) | ((0x##x##L & 0x00010000L) ? 0x10 : 0) | ((0x##x##L & 0x00100000L) ? 0x20 : 0) | ((0x##x##L & 0x01000000L) ? 0x40 : 0) | ((0x##x##L & 0x10000000L) ? 0x80 : 0))

unsigned char tmr0_times  = 0;
unsigned char tmr0_times2 = 0;
unsigned char secs        = 0;
unsigned char hours       = 7;
unsigned char mins        = 30;
unsigned char hours_d1	  = 0;
unsigned char hours_d2	  = 0;
unsigned char mins_d3	  = 0;
unsigned char mins_d4	  = 0;
unsigned char mode        = DEF_MODE;

#define POSITION_1 23    /**/// 0111  ===> 10111
#define POSITION_2 27    /**/// 1011  ===> 11011
#define POSITION_3 29    /**/// 1101  ===> 11101
#define POSITION_4 30    /**/// 1110  ===> 11110
#define POSITION_5 15    /**/// ----  ===> 01111  //** nuevo codigo de encendido del ':' **
#define POSITION_OFF 31  /**/// 1111  ===> 11111


enum {
  MANUAL_PROG,
  AUTO_PROG,
  DEF_MODE
};

/**
 * BIT NUMBER:VALUE/SIGNIFICANT
 * 0:
 * 1:
 * 2:enciende/apaga segmento central. (-)
 * 3:
 * 4:uno de los puntos de ':' y una barra del 7segmentos.
 * 5:
 * 6:uno de los puntos de ':' y una barra del 7segmentos.
 * 7:0V->enciende ':'; 5V->apaga ':'.
 *             
 * 
 *//// LOL
 
unsigned char map[] = {
  5,    /**/// 00000101 => 0   ===> 00000101
  231,  /**/// 11100111 => 1   ===> 11100111
  49,   /**/// 00110001 => 2   ===> 00110011
  161,  /**/// 10100001 => 3   ===> 10100001
  195,  /**/// 11000011 => 4   ===> 11000011
  137,  /**/// 10001001 => 5   ===> 10001001
  9,    /**/// 00001001 => 6   ===> 00001001
  229,  /**/// 11100101 => 7   ===> 11100101
  1,    /**/// 00000001 => 8   ===> 00000001
  129,  /**/// 10000001 => 9   ===> 10000001
  244   /**/// 11110100 => :   ===> 11110100
};


void delay_4ms(void) {
  int i;
  for (i=0;i<230;i++) ;
}

void isr() __interrupt 0 {                                            /* interrupt service routine */
  if (T0IF == 1) {
    TMR0 = 0x083;
    T0IF = 0;
    tmr0_times2 ++;
      
    if (tmr0_times2 == 10) {
      tmr0_times2 = 0;
      tmr0_times ++;
      if (tmr0_times == 100) {
	tmr0_times = 0;
	secs ++;
	if (secs == 60) {
	  secs = 0;
	  mins ++;
	  if (mins == 60) {
	    mins = 0;
	    hours ++;
	    if (hours == 24) {
	      hours = 0;
	    }
	    hours_d1 = hours / 10;
	    hours_d2 = hours % 10;
	  }
	  mins_d3  = mins / 10;
	  mins_d4  = mins % 10;
	}
      }
    }
  }
  
  if (INTF == 1) { /*** Service External Routine (button) ***/
    INTF = 0;
    switch (mode) {
      case DEF_MODE:
	mode = MANUAL_PROG;
	break;
      case MANUAL_PROG:
      case AUTO_PROG:
	mode = DEF_MODE;
	break;
    }
  }
}
/*
void delay_1s() {
  int times = 1000/4, i;
  for (i=0; i < times; i++) delay_4ms();
}
*/

void sayHELO() {
    PORTA = POSITION_1;
    PORTB = map[6];
    
    delay_4ms();
    
    PORTA = POSITION_2;
    PORTB = map[6];
    
    delay_4ms();
    
    PORTA = POSITION_3;
    PORTB = map[6];
    
    delay_4ms();
    
    PORTA = POSITION_4;
    PORTB = map[6];
    
    delay_4ms();
}

void main() {
  TMR0       = 0x083;
  OPTION_REG = BIN(11000010);
  INTCON     = BIN(10110000);
  TRISB      = 0;
  TRISA      = 0;
  
  hours_d1 = hours / 10;
  hours_d2 = hours % 10;
  mins_d3  = mins / 10;
  mins_d4  = mins % 10;
  
  /*** ¿¡¿QUÉ COÑO ES ESTO?!?
  PORTB = map[hours_d1];
  PORTA = POSITION_1 & POSITION_2 & POSITION_3 & POSITION_4;
  *////XD
  
  while (1) {
    
    if (mode == MANUAL_PROG) {
      sayHELO();
    } else if (mode == AUTO_PROG) {
      
    } else {
    
      /** Modo pintado de hora en display 7segmentos **/
      PORTB = 255;
      PORTA = POSITION_OFF;
      
      PORTB = map[hours_d1];
      PORTA = POSITION_1;
    
      delay_4ms();
    
      PORTB = 255;
      PORTA = POSITION_OFF;
      
      PORTB = map[hours_d2];
      PORTA = POSITION_2;
    
      delay_4ms();
      
      PORTB = 255;
      PORTA = POSITION_OFF;
      
      PORTB = map[mins_d3];
      PORTA = POSITION_3;
      
      delay_4ms();
      
      PORTB = 255;
      PORTA = POSITION_OFF;
      
      PORTB = map[mins_d4];
      PORTA = POSITION_4;
      
      delay_4ms();
      
      PORTB = 255;
      PORTA = POSITION_OFF;
      
      PORTB = map[sizeof(map) - 1];
      PORTA = POSITION_5;
      
      delay_4ms();
      /**///Fin del pintado de la hora actual.
    }
  }
}
 
Última edición:
¿Como configuraste la interrupción?

Del modo que pusiste el pulsador, necesitas un flanco positivo.

Otra cosa muuuy importante, te falta un antirrebote, ya que el uC detecta esto cuando usas el pulsador:



Tenés dos opciones de resolverlo:

- Por soft, mediante una rutina. Acá te dejo una explicación de como debería funcionar esa rutina (ver abajo, cuando aparece el gráfico del rebote), pero esa rutina está pensada para un flanco descendente, a diferencia de tu configuración flanco ascendente.

- Por hard mediante un filtro R-C.
 
Buenas cosme,

gracias por tu respuesta.

Te diré como tengo configurado el botón: el VCC de la alimentación va a un pin del botón, y el GND está conectado por una resistencia de 21k creo (marron negro naranja oro) al otro pin del botón y al pin del PIC.

El tema del antirebote, no lo acabo de pillar con el código fuente que me has pasado, creo que tendré que buscar en google, o estudiar el tema de hacerlo por hardware con un filtro R-C, lo cual no sé lo que es... jejeje.

Lo del flanco positivo tampoco lo entendí al 100%, supongo que te refieres que debe de dar el VCC al pin, en vez del GND, es así?

Bueno, ya me dices algo al respecto, yo voy a ver si concilio el sueño... si no, te leo en breves, supongo jejeje.

Un saludo amigo!

Gracias por todo!

Hola amigo cosme,
ya entendí un poco mejor qué es el rebote. Leí tu POST y me gustó mucho.

Básicamente, el rebote es el continúo triggering de la interrupción en ese tiempo en el que el botón sigue pulsado y nosotros no somos capaces de soltar en lo que sería una sola interrupción, y por ello debemos regular con software o hardware para evitar interrupciones innecesarias, que es lo que me está pasando a mí creo.

Creo que leyendo tu explicación, me atrevería a lanzarme a la piscina y programar yo algo según mi configuración.

Lo que no acabo de entender bien, es según la configuración que tengo del botón, la cual no sabría decirte si es de flanco positivo o negativo, cuál sería la configuración adecuada de mi interrupción.
Es decir, si debiera de ser on "rising-edege" ó "falling-edge"... (Yo creo que esta última, es así ?:)

Bueno, un saludo, y gracias de nuevo.

Sos un maestro... jaja.

Abel.
 
Última edición:
Básicamente, el rebote es el continúo triggering de la interrupción en ese tiempo en el que el botón sigue pulsado y nosotros no somos capaces de soltar en lo que sería una sola interrupción, y por ello debemos regular con software o hardware para evitar interrupciones innecesarias, que es lo que me está pasando a mí creo.

El rebote es producto del pulsador, cuando lo largas, justamente rebota y pasa lo que te puse en la figura de arriba, conduce... deja de conducir... todo en forma aleatoria.

Creo que leyendo tu explicación, me atrevería a lanzarme a la piscina y programar yo algo según mi configuración.

La idea es que hagas eso, te bases en los 5 pasos que puse. Es altamente recomendable que esos pasos no los hagas dentro de la rutina de interrupción.

Lo que no acabo de entender bien, es según la configuración que tengo del botón, la cual no sabría decirte si es de flanco positivo o negativo, cuál sería la configuración adecuada de mi interrupción.
Es decir, si debiera de ser on "rising-edege" ó "falling-edge"... (Yo creo que esta última, es así ?:)

Es cuestión de analizarlo amigo, cuando apretás el pulsador ¿de qué estado inicial a qué estado final pasas?
 
Buenos días por aquí amigo cosme,

gracias por tu respuesta, como siempre tan amigo mío... :).


Bueno, citaría tus respuestas pero no sé cómo, así que como siempre te voy a responder como sé, jeje.

El rebote ya lo entendí mejor que antes, y eso me hace feliz. Así que gracias por tu explicación ;).

El tema del antirebote, lo voy a tener que estudiar cuando tenga tiempo, para entenderlo a mayor profundidad y así poder implementarlo.

Finalmente, te diré muy a mi pesar, que como decimos por aquí: "me has pillado!" jaja, es decir, no sé a qué te refieres con el estado inicial del que estoy al que paso finalmente. Sin embargo, puedo decirte, que por como está conectado el botón, yo siempre creí que esto tenía que ver con si quería la interrupción cuando pasase de GND a VCC, o viceversa... por lo que, según tengo conectado, diría que es "rising edge" porque quiero que la interrupción se genere en cuanto se pulse el botón. O sería mejor, cuando se pulsase y se dejase de pulsar? Sinceramente, creo que una interrupción sigue un ciclo, es decir, pasa por 2 estados, estando primero en 1: +...-...+ -> se genera interrupción. ó, -....+....- -> se genera interrupción. ¿Es así?

Como siempre, disculpa mi ignorancia, ya me gustaría a mí saber lo que tú! jajaja

un saludo muy grato, y espero sigamos en contacto mucho tiempo más.

Un abrazo.

Abel.
 
Exacto, así como colocaste el pulsador la interrupción debe ser configurada para detectar flanco ascendente porque la entrada de dicha interrupción pasa de GND (sin pulsar) a Vcc (pulsado).

Sobre el antirrebote, podés encontrar mucha información en el foro, algunos simplemente la implementan con un delay de 100 o 300 mSeg, no es la mejor solución, pero sirve.
 
Buenas amigo cosme,

esta mañana he estado estudiando el tema, ya he entendido cómo puedo hacer para controlar el rebote. O sea, implementar un anti-rebote. El problema que tengo ahora mismo, es que la interrupción salta sola, pasados 3 segundos desde que lo enchufo. Seguramente debe ser un error de programación.
Algo que veo no me gusta, es que uso la misma función para las 2 interrupciones (TMR0 e INT), porque con el SDCC compiler versión 3.3.0 no consigo definir 2 distintas, para cada. Por lo que en el código anterior que postee anteayer, está programado que la misma rutina compruebe la INTF y la T0IF, para saber qué interrupción ha saltado... pero creo que no es correcta esta programación, y puede ser causa de fallos en el futuro.

Por lo dicho antes, pregunto a tu persona, más experimentada y con más conocimiento, para adquirir consejo al respecto. ¿Debería cambiar de compilador, o simplemente es la versión?

He observado en la red, buscando por google.com, páginas que muestran como definir una interrupción para según qué acción, por ejemplo, una interrupción para la externa, debería usar una función tal que así:

Código:
void isr_intexterna (void) __interrupt 0 {
 // body
}

Y para la interrupción del timer 0, sería lo mismo, cambiando el nombre y el número correspondiente a la interrupción: __interrupt 1

Bien, pues esto hice, y al compilar el código C, el código ensamblador aparece repitiendo un label, y por tanto el ensamblamiento resulta en error.

¿Algún consejo, respecto a otro compilador, forma de programarlo o resolución de la duda sobre el por qué salta sola la interrupción? Con respecto a este último enumerado concepto, debo decir que si la interrupción salta sola, al cabo de 1 segundo, debería aparecer de nuevo la hora, en vez de 6666 todo el rato, tras 3 segundos.

Gracias,

un abrazo.

Saludos a todos los que nos leáis.

Abel.
 
Nunca ví que una rutina de interrupción manejara dos periféricos distintos.

¿Qué dice el datasheet respecto a las interrupciones de c/periférico?

Nota: yo nunca usé PIC y menos el 16f84, por lo tanto te recomiendo que preguntes en la zona de uC.
 
Última edición:
Buenas,

amigo cosme, yo hace tiempo estuve leyendo un manual/libro del MCS51 para ayudar a un amigo a aprobar un exámen. Entonces aprendí que los uC utilizan un vector a partir de X dirección, en donde te caben justos unos jumps a las rutinas que manejan las interrupciones. Es por eso que estuve todo el día ofuscado, pensando que sdcc tenía un fallo; pero parece ser que cuando se programa en C y opcionalmente en ASM, se utiliza una sola rutina. En función de los flags establecidos por el uC, se detecta el tipo de interrupción ocurrida.

Voy a seguir ahora que ya sé, (porque descargué el MPLAB IDE y el XC8 para Linux y lo aprendí), verificando que mi código esté bien.

Muchas gracias por tu ayuda, pronto te informaré con más detalles.

Gracias.

Abel.
 
No señor, por lo menos no con las familias de uC que usé, eso incluye familia 8051, AVR y ARM. Cada periférico tiene su propia rutina de interrupción.

La pregunta es, ¿el 16f84 tiene un vector de interrupciones? o ¿es tan precario que tenés una sola dirección de interrupción donde es necesario manejar a todos los periféricos dependiendo del estado de un bit?
 
Según el datasheet, el vector de interrupción está en la dirección 0004h, y no muestra ninguna otra dirección ni espacio del mismo. Así que debe ser lo que tú dices: precario.

Así que rectifico, tienes tú la razón cuando dices que cada servicio tiene su rutina, yo lo aprendí así.
Y debe ser que sdcc detecta que es 16f84a y solo puede tener una rutina.

En todos los topics que he visto al respecto de la família 16f8XX (si mal no recuerdo), es que utilizan una sola rutina.

Y de hecho, el XC8 de microchip, utiliza una keyword para definir una rutina de interrupción.

Y en ningún caso, excepto en el MCS51 y código ASM, he visto que se puedan asociar rutinas a servicios de interrupción.

Todos comentan, que utilizan una sola rutina en caso de estos uC.

Saludos,

gracias por la contestación.

Un abrazo.



Rectifico: En ningún caso he visto que se pueda asociar una rutina a un servicio concreto, excepto con SDCC cuando se usa la keyword __interrupt y entre '(' y ')' (paréntesis) el identificador según el uC, correspondiente a un servicio distinto: Ext, TMR0, Ext2, TMR1, etc.

En el caso de los uC 18F, existen interrupciones de alta y baja prioridad, y el vector y la definición de las mismas, se parece más a lo que me has dicho: una rutina por servicio.

Pero debe ser que la família 16F8XXy es más precaria.

Trabajando con arduino, recuerdo haber podido asociarlas a diferentes servicios. Pero esto no recuerdo bien cómo hacerlo y tampoco lo aprendí en profundidad.

EDIT: que no se me malinterprete, cuando digo "en ningún caso" me refiero a lo que conozco, supongo que las interrupciones y la forma de manejarlas varían según el uC, chip o lo que sea...



Por cierto, ya conseguí que funcionase el pulsador. Y ahora tengo el problema del rebote, antes lo que me ocurría puede ser por 2 razones:

1. no limpiaba el valor de RB0
2. no tenía el pin RB0 como entrada
3. 1 y 2.

Ahora tengo que hacer que cuando pulso el botón no rebote jeje...
 
Última edición:
El antirrebote por soft más sencillo es usar un delay, con el inconveniente que desaprovechas la capacidad del uC (es decir, cero optimización).

La idea sería:

Declarás una nueva variable global que vas a usar como flag (puede que necesite ser volátil)

PHP:
unsigned char flag_interrupcion_externa=0;

o

PHP:
volatile unsigned char flag_interrupcion_externa=0;


Incluís esa variable en tu rutina de interrupción

PHP:
void isr() __interrupt 0 {                                            /* interrupt service routine */
  
  if (T0IF == 1) {  
      ....// Tú código para el timer
  }
  
  if (INTF == 1) { /*** Service External Routine (button) ***/
    INTF = 0;    
    flag_interrupcion_externa=1;
  }
}

Luego en main

PHP:
void main() {
   ... // Inicialización
   
   while (1) {
   ... // Tú código
   
   if(flag_interrupcion_externa)
     {
        ....//Deshabilitá la interrupción externa!
        flag_interrupcion_externa=0; //Reseteo el flag        
        delay(); //De 50 a 300mS, es cuestión de probar
        
        switch (mode) {
                  ...// Tú código que estaba en la rutina de interrupción      
        }
        
         ....//Habilitá la interrupción externa!
     }
   }
}
 
Última edición:
Aaaah!! cojones... jeje ya entendí.

Le podría poner algo más para aprovechar que tengo el timer0, o sea no haría falta el delay, pero ya lo entendí!!

muchas gracias, feliz año a tod@s!!
ya te cuento más cosas ;)
 
Atrás
Arriba