Введение
Думаю многие из тех, кто как-то связан с разработкой электронных устройств, хотя бы раз слышали о программном комплексе Proteus от Labcenter Electronics. Какая бы не была обширная библиотека компонентов, доступных для моделирования, «жизнь» схемы ограничена пределами окна эмулятора, за редким исключением. Уже существует несколько моделей, которые могу, например, записывать какие-то данные в файл или даже представляться системе как USB устройства, но пока они могут решить небольшой класс задач.
Задача
При работе над курсовым проектом, в рамках которого необходимо разработать систему радиоуправления самолётом, возникла необходимость связи модели с ПК. Так как одним из самых простых интерфейсов для связи с ПК является RS-232, он и был выбран(использовался переходник usb-uart).
Так как же отлаживать эту систему на самом начальном этапе, когда ещё не найдены довольно грубые ошибки, которые могут привести к выходу из строя электронных компонентов, и не возиться с частой прошивкой микроконтроллер(ов)?
Довольно удобным решением является Proteus. Но тут появляется новая проблема — связь с пк.

Сразу в голову приходит мысль о виртуальных ком портах. Например com0com, который создаёт 2 виртуальных COM порта, ввод и вывод которых перенаправлен друг в друга. А тем, кто по каким-либо причинам работает на виртуальных машинах, может пригодится возможность перенапрявлять com порты средствами ВМ.
Но
Шаги создания модели
Создание графического изображения модели
Добавляем прямоугольник, ещё прямоугольник, текст, выводы (с помощью Device Pins) получаем:

совсем подробно описано в той статье или тут
Разработка программы
Для взаимодействия с моделью, я решил использовать именованные каналы ОС Windows. Возможно решение покажется странным, но задумка состоит в том, чтобы обеспечить интерфейс максимально похожий, на интерфейс реального устройства. Выбор пал на именованные каналы, так как работа с ними и COM портами практически идентична работе с обычными файлами.
Но даже если у нас есть канал связи с «внешним миром», то как реализовать обмен по интерфейсу uart?
Надо вспомнить его формат кадра:

Логика генерации/разбора сигнала такого вида выделена в отдельный класс.
Основными для модели протеуса будут два метода:
производящий начальную настройку:
VOID PIPEUARTMODEL::setup (IINSTANCE *instance, IDSIMCKT *dsimckt)
{
uart = new Uart();
logger = new Logger(instance);
pipe = new Pipe("\\\\.\\pipe\\uart", logger);
//сохраняем ссылку на dsimckt
ckt = dsimckt;
//связываем пины по имени
txd = instance->getdsimpin("TXD", true);
rxd = instance->getdsimpin("RXD", true);
//устанавливаем начальное состояние txd
txd->setstate(SHI);
//добавляем 2 события
ckt->setcallback(1, this, rxd_event);
ckt->setcallback(2, this, txd_event);
}
и то, который дёргается callback'ом
VOID PIPEUARTMODEL::callback(ABSTIME time, EVENTID eventid) {
switch (eventid) {
case rxd_event:
uart->rxBit(ishigh(rxd_pin_state)); //обрабатываем сигналы со схемы
if (uart->rxC) {
pipe->rxd_queue.push(uart->rxD); //отправляем в pipe
uart->rxC = 0;
}
//устанавливаем время следующего вызова в пикосекундах
ckt->setcallback(time + 1000000000000 / uart_baudrate, this, rxd_event);
break;
case txd_event:
if ((uart->txC) && (!pipe->txd_queue.empty())) {
uart->txD = pipe->txd_queue.front(); //отправляем в uart
pipe->txd_queue.pop();
}
txd->setstate(time, 1, uart->txBit() ? SHI : SLO); //устанавливает значение выхода
ckt->setcallback(time + 1000000000000 / uart_baudrate, this, txd_event);
break;
}
}
Тестирование
Пример работы моей модели с Virtual Terminal:

Предстоит ещё проверить на сколько удобным окажется данное решение, но на первый взгляд, оно меня полностью устраивает.
Надеюсь представленные рецепты помогут решить множество Ваших проблем.