Ви можете зробити акуратний трюк, якщо спілкування ведеться лише в одному напрямку (тобто напівдуплексне спілкування). Це не спрацює, якщо обидві сторони розмовляють між собою одночасно (повний дуплекс), але якщо це типовий "зробіть це" "нормально, ось відповідь" "зараз зробіть це" "добре ось новий тип відповіді" це працює досить добре.
Оскільки посилання UART використовує неробочий стан передавача на логічно високому рівні (1), ви б використовували 2-вхідний і затворний І підключали TX з кожної сторони до входу AND. Вихід воріт AND - це ваш вхід до UART вашого сніфера (це RX-контакт). Тепер візьміть лінію TX пристрою B, а також піднесіть його до порту вводу / виводу на снайфері. Ви налаштуєте sniffer для створення переривання, коли цей штифт перейде від високого до низького.
Для резюме: пристрій AART TX -> AND вхід на ворота. Пристрій B UART TX -> інший І вхід І ворота та нюхальний GPIO контакт. Вихід лінії І - - sniffer лінія UART RX.
Комунікації UART складаються з початкового біта, деякої кількості бітів даних, необов'язкового біта парності та одного або декількох стоп-бітів. Оскільки стан холостого ходу є логічно високим (1), то початок кожного байта буде логічно низьким (0), і переривання на sniffer запуститься. Поки ваш sniffer виконує переривання вводу / виводу, апаратне забезпечення UART буде збирати біти з воріт AND. До того моменту, коли UART отримає стоп-біт, переривання вводу / виводу буде зроблено довго, і перерва UART RX запуститься.
Підпрограма перерви на введення-виведення встановлює змінну "напрям", яка вказує на те, що комунікації йдуть у напрямку "B-> A". Переривання прийому UART sniffer буде дивитись на цю змінну "напряму" і записувати щойно отриманий байт у відповідний буфер. Потім перерив UART RX поверне змінну "напрям" назад до стану "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 */
}
Цей код написано для наочності, а не обов'язково для написання в реальній ситуації. Особисто я б зробив "напрямок" вказівника на відповідну структуру FIFO, але це вже інша вправа. :-)
Коли пристрій A розмовляє, лінія вводу / виводу не рухається (вона залишається в логіці "1", оскільки передавач UART пристрою B не працює), а переривник UART RX отримає байт, дивіться, що напрямок A-> B , і зберігати дані до цього буфера. Коли пристрій B розмовляє, лінія вводу / виводу знизиться, як тільки пристрій B почне перемикати дані, і програма переривання вводу / виводу встановить напрямок, який вказує на те, що пристрій B говорить. Переривання UART RX в кінцевому підсумку спрацює після того, як всі біти будуть зібрані, і оскільки переривання вводу / виводу переймається правильним встановленням регістру напрямків, отриманий байт буде зберігатися у правильному буфері.
Presto: напівдуплексний зв’язок між двома пристроями, захопленими однією лінією UART та вводу / виводу на нюхалеві, без зв’язку біт-ударів UART.