L'Arduino peut-il être utilisé pour «espionner» une connexion UART entre deux appareils?


11

J'ai besoin d'installer un Arduino (en fait juste l'IC) dans le matériel existant pour améliorer les fonctionnalités.

Ce que je voudrais faire, c'est connecter l'Arduino pour qu'il "espionne" sur les lignes d'E / S entre deux puces sur une carte. Si l'Arduino prend un mot-clé spécifique sur cette connexion UART, il effectuera une action spécifique sur un ensemble distinct de broches de sortie.

Ce que je ne sais pas, c'est comment connecter l'Arduino de telle manière qu'il puisse décoder une connexion UART existante sans y participer? Si ce n'est pas possible, je m'intéresse aux théories, idées, etc.

Réponses:


17

Si je comprends bien, vous avez 2 appareils connectés via UART. Je suppose que seules les lignes TX, RX et GND sont connectées entre les appareils? (c.-à-d., aucune ligne de contrôle DTS / CTS / DTR / RTS utilisée - ceci est typique).

Dans ce scénario, le TX (émission) du périphérique 1 est connecté au RX (réception) du périphérique 2, et vice-versa. Leurs motifs sont reliés les uns aux autres. Ainsi, chaque appareil peut transmettre et recevoir en même temps (chacun transmet sur un fil séparé, la communication est en duplex intégral).

La raison pour laquelle je mentionne tout cela est parce qu'il devient clair que pour "renifler" ou "écouter", vous aurez en fait besoin de 2 UART pour écouter les deux côtés de la conversation.

Fondamentalement, tout ce que vous feriez est de vous assurer que les GND UART des 3 appareils sont court-circuités et de connecter (vraiment, "tee", comme dans un raccord en T, comme la plomberie) les lignes TX de l'appareil 1 et de l'appareil 2 aux 2 lignes RX sur 2 UART. Assurez-vous que les débits en bauds sont tous configurés de manière identique.

Il existe de nombreuses cartes / conceptions Arduino. Le plus courant de nos jours, le Duemilanove, utilise l'ATMega328P, qui, je pense, n'a qu'un seul UART (enfin, USART). Il vous faudrait donc soit câbler un 2e CI UART, soit recourir à un "coup de bit" sur le deuxième récepteur.

Les communications UART Async sont bien définies, avec des bits de démarrage et d'arrêt (et parfois des bits de parité), donc si votre processeur est assez rapide, vous pouvez simplement connecter l'une des lignes UART TX de l'appareil à un GPIO configuré en entrée et interroger la ligne assez rapide avec suréchantillonnage pour détecter START & STOP et échantillonner les bits. L'article "Bit Banging" de Jack Ganssle vous donnera beaucoup à mâcher.

Une description décente de la forme d'onde RS232 peut être trouvée sur BeyondLogic .

Notez qu'il y a d'autres problèmes tels que les niveaux de tension (0 / + 5, -10V / + 10V, etc.) que vous devrez prendre en considération (voir la section Beyond Logic sur "Convertisseurs de niveau RS232"). Je n'ai pas assez d'informations sur votre système pour discuter de l'interface matérielle en plus de l'approche «connecter les lignes» discutée ci-dessus. En supposant que les niveaux de tension correspondent, généralement ce n'est pas un problème de "raccorder" la ligne TX à un deuxième récepteur (le renifleur), mais si le TX n'a ​​pas assez de lecteur, vous devrez peut-être insérer un tampon / pilote pour empêcher la signal de dégradation.


Belle! Je n'aurai besoin que des données voyageant dans une seule direction, donc le seul UART sur la puce ATMega est juste suffisant! Les deux puces communiquent avec +/- 5V UART, ce qui, je pense, est le même que l'ATMega. Wow, ça devrait être ça! Merci!
Brad Hein

@BradHein, ce que vous appelez "+/- 5V" est généralement appelé "niveau TTL" - voir en.wikipedia.org/wiki/Logic_level .
Mels

3
@Mels +/- 5V n'est PAS TTL, TTL ne descend PAS sous la terre. Ceci est RS-232.
nmz787

9

Il y a une astuce intéressante que vous pouvez faire si la communication est dans une seule direction à la fois (c'est-à-dire une communication semi-duplex). Cela ne fonctionnera pas si les deux parties se parlent en même temps (duplex intégral) mais si c'est votre "faire ceci" "ok voici la réponse" "maintenant faire ceci" "ok voici la nouvelle réponse" type de communications ça marche assez bien.

Étant donné que la liaison UART utilise une condition inactive de l'émetteur à un niveau logique élevé (1), vous utiliseriez une porte ET à 2 entrées et connectez le TX de chaque côté à une entrée ET. La sortie de la porte ET est votre entrée pour l'UART de votre renifleur (c'est la broche RX). Prenez maintenant la ligne TX du périphérique B et amenez-la également à un port d'E / S sur le renifleur. Vous allez configurer le renifleur pour générer une interruption lorsque cette broche passe de haut à bas.

Pour récapituler: périphérique A UART TX -> ET entrée de porte. Périphérique B UART TX -> autre entrée ET porte ET broche GPIO de renifleur. Sortie de la porte ET -> ligne renifleur UART RX.

Les communications UART se composent d'un bit de démarrage, d'un certain nombre de bits de données, d'un bit de parité facultatif et d'un ou plusieurs bits d'arrêt. Étant donné que l'état inactif est un niveau logique haut (1), le début de CHAQUE octet sera un niveau logique bas (0) et l'interruption sur le renifleur se déclenchera. Pendant que votre renifleur exécute l'interruption d'E / S, le matériel UART collecte les bits de la porte ET. Au moment où l'UART a reçu le bit d'arrêt, l'interruption d'E / S sera longue et l'interruption UART RX se déclenchera.

La routine d'interruption sur changement d'E / S définira une variable de "direction" pour indiquer que les communications sont dans le sens "B-> A". L'interruption de réception UART du renifleur examine cette variable de "direction" et écrit l'octet qui vient d'être reçu dans le tampon approprié. L'interruption UART RX remettrait alors la variable "direction" à l'état par défaut "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 */
}

Ce code est écrit pour plus de clarté et pas nécessairement ce que vous écririez dans une situation réelle. Personnellement, je ferais de "direction" un pointeur vers la structure FIFO appropriée, mais c'est un tout autre exercice. :-)

Lorsque le périphérique A parle, la ligne d'E / S ne bouge pas (elle reste à un «1» logique car le transmetteur UART du périphérique B est inactif) et l'interruption UART RX recevra un octet, voir que la direction est A-> B et stockez les données dans ce tampon. Lorsque le périphérique B parle, la ligne d'E / S devient faible dès que le périphérique B commence à transférer des données, et la routine d'interruption d'E / S définit la direction pour indiquer que le périphérique B parle. L'interruption UART RX se déclenchera finalement une fois que tous les bits auront été collectés et puisque l'interruption d'E / S a pris soin de régler le registre de direction de manière appropriée, l'octet reçu sera stocké dans le tampon correct.

Presto: communications semi-duplex entre deux appareils capturés avec une seule ligne UART et E / S sur le renifleur, sans communications UART binaires.


Intrigant. Cela repousse les limites de ma compréhension, mais c'est super! Une partie que je ne comprends pas est de savoir comment l'UART du renifleur est connecté à la cible afin qu'il puisse intercepter les deux directions de communication? J'ai plusieurs broches d'E / S disponibles, alors pourrais-je simplement utiliser deux broches d'E / S en utilisant cette méthode et collecter efficacement les deux directions du trafic?
Brad Hein

La ligne de renifleur UART RX est connectée à la sortie de la porte ET. L'UART TX de l'appareil A est connecté à une entrée de la porte ET et l'UART TX de l'appareil B est connecté à l'autre entrée de la porte ET. Étant donné que l'état inactif (pas de trafic) d'un UART est un «1» logique, la porte ET combine efficacement les deux signaux de transmission en un seul. La ligne d'E / S sur le renifleur est utilisée pour détecter le bit de démarrage du périphérique B afin qu'il puisse prendre l'octet qu'il reçoit sur son UART et le mettre dans le tampon approprié (trafic du périphérique A ou trafic du périphérique B).
akohlsmith

Le fragment de code et le câblage de la porte ET permettent au renifleur d'enregistrer les deux directions du flux de trafic avec un seul UART. Cela ne fonctionne que si le trafic est semi-duplex. Cela signifie que lorsqu'un appareil parle, l'autre écoute. Si les deux parlent en même temps (duplex intégral), cela ne fonctionnerait pas du tout.
akohlsmith

5

Vous n'avez pas à brancher la broche de transmission des données de l'AVR dans votre circuit. Connectez simplement la ligne de réception à la moitié du lien existant que vous souhaitez écouter. Si votre AVR possède deux ports série, vous devriez pouvoir espionner simultanément les deux moitiés de la liaison existante. Il vous suffit de faire correspondre les paramètres du port au débit en bauds existant, aux bits d'arrêt, etc.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.