Hay un buen truco que puede hacer si la comunicación es en una dirección solo a la vez (es decir, comunicación semidúplex). No funcionará si ambas partes se comunican entre sí al mismo tiempo (dúplex completo), pero si es su típico "haga esto", "esta es la respuesta", "ahora haga esto", "esta es la nueva respuesta". Funciona bastante bien.
Como el enlace UART usa una condición inactiva del transmisor en un nivel lógico alto (1), usaría una puerta AND de 2 entradas y conectaría el TX de cada lado a una entrada AND. La salida de la compuerta AND es su entrada al UART de su sniffer (es el pin RX). Ahora tome la línea TX del dispositivo B y también llévela a un puerto de E / S en el sniffer. Configurará el sniffer para generar una interrupción cuando este pin pase de mayor a menor.
Para recapitular: dispositivo A UART TX -> Y entrada de puerta. Dispositivo B UART TX -> otra entrada de compuerta AND Y pin GPIO sniffer. Salida de la compuerta AND -> sniffer línea UART RX.
Las comunicaciones UART consisten en un bit de inicio, cierto número de bits de datos, un bit de paridad opcional y uno o más bits de parada. Como el estado inactivo es un nivel lógico alto (1), el inicio de CADA byte será un nivel lógico bajo (0) y se disparará la interrupción en el sniffer. Mientras su sniffer está ejecutando la interrupción de E / S, el hardware de UART recogerá bits de la puerta AND. Para cuando el UART haya recibido el bit de parada, la interrupción de E / S habrá finalizado por mucho tiempo y se disparará la interrupción UART RX.
La rutina de interrupción por cambio de E / S establecerá una variable de "dirección" para indicar que las comunicaciones están en la dirección "B-> A". La interrupción de recepción UART del sniffer miraría esta variable de "dirección" y escribiría el byte recién recibido en el búfer apropiado. La interrupción de UART RX volvería a establecer la variable "dirección" en el estado predeterminado "A-> B":
volatile int direction = 0; /* 0 = A -> B */
void io_interrupt(void)
{
direction = 1; /* switch direction, now B -> A */
}
void uart_interrupt(void)
{
unsigned char b;
b = UART_RX_REG;
if(direction) {
store_byte_to_device_b_sniff_buffer(b);
} else {
store_byte_to_device_a_sniff_buffer(b);
}
direction = 0; /* reset direction to default A -> B */
}
Este código está escrito para mayor claridad y no necesariamente lo que escribiría en una situación del mundo real. Personalmente, haría de "dirección" un puntero a la estructura FIFO apropiada, pero ese es otro ejercicio completamente diferente. :-)
Cuando el dispositivo A está hablando, la línea de E / S no se mueve (permanece en un '1' lógico ya que el transmisor UART del dispositivo B está inactivo), y la interrupción UART RX recibirá un byte, verifique que la dirección sea A-> B y almacenar los datos en ese búfer. Cuando el dispositivo B está hablando, la línea de E / S se reducirá tan pronto como el dispositivo B comience a cambiar los datos, y la rutina de interrupción de E / S establecerá la dirección para indicar que el dispositivo B está hablando. La interrupción UART RX eventualmente se disparará después de que se hayan recopilado todos los bits y dado que la interrupción de E / S se ha encargado de establecer el registro de dirección de manera adecuada, el byte recibido se almacenará en el búfer correcto.
Presto: comunicaciones semidúplex entre dos dispositivos capturados con una sola línea UART y línea de E / S en el sniffer, sin comunicaciones UART con bit bitged.