Uso de múltiples interrupciones externas en PIC

He usado PIC16F877( hoja de datos ) para varios proyectos. Para interrupciones de cambio de un solo pin externo, puede usar PORTB0interrupt. Pero ahora necesito admitir 8 interrupciones de cambio de pin externas independientes, en un solo circuito.

En la hoja de datos dice que hay 15 interrupciones PIC16F877, pero supongo que se cuentan, incluidas las interrupciones de desbordamiento del temporizador, etc., que son inútiles en este caso.

Esto es lo que dice la hoja de datos sobre el INTCONregistro.

ingrese la descripción de la imagen aquí

¿Puedo tener 4 interrupciones independientes usando bit0, RBIF? Representa el cambio en PB7:PB4. ¿Cómo puedo identificar qué pin cambió, es leyendo el valor del puerto en la rutina de interrupción?

Incluso si obtengo respuestas positivas a lo anterior, ¿necesito 8 interrupciones? por supuesto que todavía puedo usar INTE, para PORTB0cambiar. Entonces 4 + 1 = 5, pero ¿qué pasa con los otros 3? (Sin embargo, como los 8 eventos de interrupción son del mismo tipo, la 4 + 1 + 3 = 8cosa parece fea, ¿no?)

No se esperan otras tareas pesadas del microcontrolador aparte de monitorear 8 pines. (Hablando de las otras tareas, tendrá que mantener un conjunto de variables de contador separadas y con frecuencia transmitir alrededor de 4 bytes a la PC en serie)

Cualquier sugerencia es bienvenida. Aunque se trate de cambiar el microcontrolador por uno más adecuado (pero eh.. no me digas que me aleje de PICs).

Sin usar interrupciones, es posible que pueda monitorear los pines en el programa principal. Pero eso no es perfecto. Como alternativa, puedes optar por Arduino. Aunque no es PIC, es bastante simple, lo entenderá fácilmente ya que ya está familiarizado con los PIC.
Si usa la interrupción RBIE, puede simplemente almacenar en búfer el valor anterior cada vez y un XOR para encontrar qué ha cambiado. Debería ser bastante rápido de ejecutar.
@PeterJ no entendí muy bien eso. Amortiguador qué valor?
@PeterJ genial! esperando...
Una forma es usar una puerta externa de 8 entradas (como la 74LS30 en los viejos tiempos) para combinar las señales externas en un pin de interrupción. Como el 74(HC)30 es una puerta NAND, necesitaría todas las entradas altas en el estado de reposo; también tendrían que estar conectadas a los pines del puerto para poder identificar qué interrupciones estaban activas leyendo el puerto.
@CodenamedSC, ¿no es más fácil cambiar a otro PIC que admita la interrupción al cambiar para obtener más pines? Creo que hay algunos que admiten todo el puerto B.
¿Qué tan rápido debe el sistema detectar y reaccionar a un cambio? ¿Cuál es el tiempo mínimo que debe persistir un cambio para ser válido? Realmente, debería haber sido obvio que esos son parámetros importantes para proporcionar.
@BrianDrummond sí, esa es una solución práctica (y parece que es la mejor). Pero el único problema es que no me gusta perder el tiempo con el hardware ahora que tengo un circuito completo. Pero definitivamente consideraré eso si tuviera que reconstruir uno en cualquier caso. ¡Gracias!
Yo también estoy buscando algo similar. Necesito tener 8 interrupciones. Estoy haciendo un sistema de zumbador de detección de primera pulsación para QUIZ. Por lo tanto, las encuestas serán injustas para los participantes.

Respuestas (3)

Este es un pseudocódigo C para explicar una idea. Utiliza un OR exclusivo para determinar qué pines han cambiado y llamará a sus diferentes controladores dentro de una interrupción RBIE. Dependiendo de cuán crítica sea la aplicación, es posible que desee verificar cómo el PIC maneja situaciones como un cambio de puerto mientras se ejecuta la interrupción para asegurarse de que no se perderá ningún evento.

int old_port_b;

void isr_handler()
{
    int new_port_b, changed_pins;
    new_port_b = read_port_b();
    changed_pins = new_port_b ^ old_port_b;
    if (changed_pins | 1)
        rb0_hander();
    if (changed_pins | 2)
        rb1_hander();
        // ... etc
    old_port_b = new_port_b;
}

int main()
{
    old_port_b = read_port_b();
    enable_interrupt();
}
Lo entiendo, gracias! pero esa no es la respuesta exacta que estoy buscando. De esa manera, solo puede monitorear RB7:RB44 pines. Pero estoy pidiendo una forma de monitorear 8 pines. ¿cualquier sugerencia?
Supongo que hay una razón por la que no puede usar RB0 - RB7 ¿para lo que debería funcionar lo anterior? De lo contrario, no puedo pensar en una forma, si activar el código rápidamente no es vital, podría usar el estilo de código anterior en una interrupción del temporizador (o solo el bucle principal).
Para ese PIC, si necesita usar interrupciones para hacer esto, el truco XOR en RB4: RB7 y cuatro interrupciones para RB0: RB3 es el camino a seguir. Si no necesita la interrupción, simplemente sondee todo el puerto en su código, o use una interrupción de temporizador para manejar el sondeo si necesita una frecuencia de muestreo estricta.
and four interrupts for the RB0:RB3? PIC16F877 no admite interrupciones para RB1:RB3, ¿eh?
Me lo había perdido en la hoja de datos, asumí que cubría todo el puerto. Pero vi su otro comentario sobre una vez por segundo, así que creo que sería mejor simplemente ejecutar esto en su bucle principal. Con las interrupciones, deberá encargarse de la actualización de las variables en cualquier momento durante la ejecución y cómo manejar los cambios de pin mientras se ejecuta la interrupción. Realmente parece que solo lo complicará sin una ganancia real. La única excepción en la que podría pensar es si quisiera usar despertar desde el modo de suspensión en la interrupción, en cuyo caso necesitaría hardware MUX.

Esa parte solo tiene 4 interrupciones de cambio de pin y algunas otras que puede configurar en los bordes seleccionados. Una estrategia sería detectar un cambio en el valor de 8 bits externamente y luego interrumpir si no coincide. Eso se complica en el hardware, pero será exactamente lo que quieres.

Los parámetros importantes que no ha indicado son qué tan rápido necesita responder a un cambio de pin y cuánto tiempo mínimo persistirá un cambio de pin para que sea válido. Según las respuestas, puede sondear en función de una interrupción regular en el firmware. El 16F877 puede funcionar a una velocidad de instrucción de 5 MHz, y verificar si hay un cambio solo requeriría unas pocas instrucciones. Digamos que configura la interrupción cada 50 instrucciones. Eso dejaría una buena parte del tiempo del procesador al código de primer plano. La tasa de interrupción sería de 100 kHz y el período de 10 µs. Por supuesto, el código de primer plano aún necesita ver el indicador de cambio y hacer algo al respecto, por lo que el tiempo de respuesta será de más de 10 µs, pero no ha dicho nada sobre lo que debe hacer cuando se detecta un cambio. Si esto solo necesita responder en tiempo humano,

Perdón por los detalles que faltan. Como la tasa de respuesta esperada once per secondserá suficiente. Cuando se detecta un cambio de pin (solo un borde, digamos ascendente), se debe incrementar un contador (variable). En el bucle principal, tiene que monitorear los valores del contador y cuando uno supera cierto valor, se deben transmitir cuatro bytes a través USARTde la PC. Luego reinicie el valor del contador relevante a cero. Simple como eso. Supongo que la opción de sondeo irá bien, ¿verdad?
¡ Una vez por segundo ! Entonces, ¿para qué sirven todas las interrupciones angustiosas? Esto se hace fácilmente con encuestas periódicas. ¿Cuál es el problema entonces?
um... pensé que sería mejor ya que hay 8 de ellos y además, la respuesta no se puede predecir (pero se puede suponer que ese valor es el mínimo). ¡Oye! la gente puede cometer errores, verdad.. :(

Puede usar la puerta NAND de 8 entradas como lo menciona @Brian Drummond para elevar una interrupción sobre el pin INT y también conectar sus fuentes de interrupción al registro de desplazamiento de entrada en paralelo/salida en serie de 8 bits como "74HC165N", entonces necesitará simplemente leer los datos de ese registro de desplazamiento después de que aumentó la interrupción y eso le dará la información sobre su fuente de interrupción real ... puede que no sea la forma más rápida, pero es fácil de expandir y no usará más de 5 pines, y si agrega un sistema de control de direcciones (MUX, LATCH,...), solo necesitará un pin para la notificación de interrupción y otros pines se pueden reutilizar en diferentes momentos para diferentes recursos;)