Istnieje fajna sztuczka, którą możesz zrobić, jeśli komunikacja odbywa się tylko w jednym kierunku (tj. Komunikacja półdupleksowa). Nie zadziała, jeśli obie strony będą ze sobą rozmawiać w tym samym czasie (pełny dupleks), ale jeśli jest to typowe „zrób to” „ok, oto odpowiedź” „teraz zrób to” „ok, oto nowy rodzaj odpowiedzi” działa całkiem dobrze.
Ponieważ łącze UART wykorzystuje stan bezczynności nadajnika na wysokim poziomie logicznym (1), użyłbyś bramki AND z 2 wejściami i łączy TX z każdej strony z wejściem AND. Wyjście bramki AND jest Twoim wejściem do UART twojego sniffera (jest to pin RX). Teraz weź linię TX urządzenia B, a także przenieś ją do portu we / wy w snifferze. Sniffer skonfigurujesz tak, aby generował przerwanie, gdy ten pin zmieni się z wysokiego na niski.
Podsumowując: urządzenie A UART TX -> AND bramka wejściowa. Urządzenie B UART TX -> inne ORAZ wejście bramki ORAZ sniffer pin GPIO. Wyjście bramki AND -> sniffer linii UART RX.
Komunikacja UART składa się z bitu początkowego, pewnej liczby bitów danych, opcjonalnego bitu parzystości i jednego lub więcej bitów stopu. Ponieważ stan bezczynności jest wysokim poziomem logicznym (1), początek KAŻDEGO bajtu będzie miał niski poziom logiczny (0), a przerwanie na snifferze zostanie uruchomione. Podczas gdy Twój sniffer wykonuje przerwanie we / wy, sprzęt UART będzie zbierał bity z bramki AND. Zanim UART otrzyma bit stopu, przerwanie we / wy będzie długo trwało, a przerwanie UART RX zadziała.
Procedura zmiany przerwania przy IO ustawi zmienną „kierunek”, aby wskazać, że komunikacja odbywa się w kierunku „B-> A”. Przerwanie odbierania UART sniffera spojrzy na tę zmienną „kierunek” i zapisze właśnie odebrany bajt do odpowiedniego bufora. Przerwanie UART RX przywróciłoby wówczas zmienną „direction” powrót do domyślnego stanu „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 */
}
Ten kod został napisany dla zachowania przejrzystości i niekoniecznie tego, co napisałbyś w rzeczywistej sytuacji. Osobiście uczyniłbym „kierunek” wskaźnikiem odpowiedniej struktury FIFO, ale to zupełnie inne ćwiczenie. :-)
Gdy urządzenie A mówi, linia we / wy nie porusza się (pozostaje na logicznym „1”, ponieważ nadajnik UART urządzenia B jest bezczynny), a przerwanie UART RX otrzyma bajt, sprawdź, czy kierunek to A-> B i przechowuj dane w tym buforze. Gdy urządzenie B mówi, linia we / wy obniży się, gdy tylko urządzenie B zacznie wysyłać dane, a procedura przerwania we / wy ustawi kierunek wskazujący, że urządzenie B mówi. Przerwanie UART RX ostatecznie uruchomi się po zebraniu wszystkich bitów, a ponieważ przerwanie We / Wy zajęło się odpowiednim ustawieniem rejestru kierunku, odebrany bajt zostanie zapisany w odpowiednim buforze.
Presto: komunikacja w trybie półdupleksu między dwoma urządzeniami przechwyconymi za pomocą pojedynczej linii UART i linii we / wy w węźle podsłuchowym, bez komunikacji UART w postaci bitów.