Взаимодействие схемы в Proteus'е с внешним миром

Введение


Думаю многие из тех, кто как-то связан с разработкой электронных устройств, хотя бы раз слышали о программном комплексе Proteus от Labcenter Electronics. Какая бы не была обширная библиотека компонентов, доступных для моделирования, «жизнь» схемы ограничена пределами окна эмулятора, за редким исключением. Уже существует несколько моделей, которые могу, например, записывать какие-то данные в файл или даже представляться системе как USB устройства, но пока они могут решить небольшой класс задач.

Задача


При работе над курсовым проектом, в рамках которого необходимо разработать систему радиоуправления самолётом, возникла необходимость связи модели с ПК. Так как одним из самых простых интерфейсов для связи с ПК является RS-232, он и был выбран(использовался переходник usb-uart).

Так как же отлаживать эту систему на самом начальном этапе, когда ещё не найдены довольно грубые ошибки, которые могут привести к выходу из строя электронных компонентов, и не возиться с частой прошивкой микроконтроллер(ов)?

Довольно удобным решением является Proteus. Но тут появляется новая проблема — связь с пк.
В библиотеке компонентов присутствует модель COMPIM, которая позволяет связывать схему с COM портом ПК, что позволяет обрабатывать запросы поступающие от устройств, подключённых к данному COM порту, как будто они подключены к эмулируемому устройству. Можно конечно через другой COM порт подключится к тому, который соединён со схемой, но это требует 2х COM портов и внешнего нуль-модемного кабеля.

Сразу в голову приходит мысль о виртуальных ком портах. Например com0com, который создаёт 2 виртуальных COM порта, ввод и вывод которых перенаправлен друг в друга. А тем, кто по каким-либо причинам работает на виртуальных машинах, может пригодится возможность перенапрявлять com порты средствами ВМ.

Но мы не ищем легких путей. случайно я набрёл на статью про создание собственных цифровых моделей для Proteus. В ней рассказывается, как вынести всю логику работы модели в динамическую библиотеку. Тут я подумал, что это как минимум позволит решить мою проблему, а как максимум очень сильно расширить возможности эмулятора, добавив собственные устройства. Которые могут иметь интерфейсы uart, i2c, spi и т.д.(со стороны схемы) и практически любые для связи с внешним миром(хоть 3D GUI)

Шаги создания модели


Создание графического изображения модели

Добавляем прямоугольник, ещё прямоугольник, текст, выводы (с помощью Device Pins) получаем:
image
совсем подробно описано в той статье или тут

Разработка программы

Для взаимодействия с моделью, я решил использовать именованные каналы ОС 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:

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

Надеюсь представленные рецепты помогут решить множество Ваших проблем.

Список источников

  1. Довольно хорошее описание системы Proteus и руководство по создания моделей
  2. easyelectronics.ru/tag/rs232
  3. Страничка на гуглокоде, где можно получить все исходники
  4. Собранный dll и библиотека для Proteus'а
Поделиться публикацией
Комментарии 0

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое