Программирование COM порта. С чего начать? Или получение первых результатов от COM. (Часть 1) Ну чтож, Вот мы и добрались до COM порта. Но с ним все не так просто как с LPT, и его полноценное использование потребует значительно больших усилий. Главной загвоздкой является и его главное преимущество - передача данных в последовательном виде. Если в LPT байт данных передается по 8-ми линиям по биту на каждую, и состояние каждой линии можно было легко посмотреть, то в COM порту байт данных передается бит за битом по одной линии (относительно земли, конечно) и посмотреть что там передается с помощью одних светодиодов не удасться. Для этого нужно специальное устройство - преобразователь потока последовательных данных в параллельный, т.н. USART (Universal Synchronous/Asynchronous Receiver Transmitter). Например, он есть в составе материнской платы компьютера, снабженного COM портом, в любом более менее серьезном микроконтроллере.
Надеюсь, Вы еще пали духом в освоении COM порта. Все не так уж и мрачно. Некоторые результаты можно получить и без USART. Сформулируем задачу, которую реализуем на начальном этапе работы с COM портом:
"Хочу чтоб к компьютеру через COM порт подключался светодиод. Запускаю программу. Далаю какое-то действие в этой программе, светодиод загорается, делаю другое - светодиод тухнет."
Задача довольно специфичная (с учетом того, что USART не используется) и является чистой "самопальщиной", но вполне реализуема и работоспособна. Давайте приступим к ее реализации.
1. COM порт
Опять берем системный блок Вашего ПК и смотрим в тыловую часть. Примечаем там 9-ти штырьковй разъем - это и есть COM порт. Реально их может быть неколько (до 4-х). На моем ПК установлено два COM порта (см. фото).
2. Удлинитель COM порта
Нам потребуется удлинитель COM порта, но не просто удлинитель, а т.н. нуль-модемный кабель. Как он выглядит? Так как на фото, причем на обох его концах установлен разъем типа "мама". Далее втыкайте его в любой COM порт Вашего ПК и выводите его на рабочее место.
3. Аппаратная часть
С аппаратной частью нам тоже придется "повозиться", в том смысле что она будет сложнее чем с первым устройством для LPT порта. Дело в том что протокол RS-232 по которому идет обмен данными в COM порту, имеет несколько отличное соотношение логическое состояние - напряжение. Если обычно это логический 0 <-> 0 В, логическая 1 <-> +5 В, то в RS-232 это соотношение следующее: логический 0 <-> +12 В, логическая 1 <-> -12 В.
И например, получив -12 В не сразу понятно что с этим напряжением делать. Обычно проводят преобразование уровней RS-232 в ТТЛ (0, 5 В). Самый простой вариант - стабилитроны. Но я предлагаю сделать этот преобразователь на специальной микросхеме. Называется она MAX232.
Микросхема эта дешевая и широко распространенная. Особенных проблем в ее добывании возникнуть не должно. Что она умеет? Она одновременно может преобразовывать два сигнала из RS-232 в ТТЛ и еще два из ТТЛ в RS-232.
Теперь давайте посмотрим, а какие сигналы из COM порта мы можем посмотреть на светодиодах? В действительности, в COM порту есть аж 6 независимых линий, представляющих интерес для разработчика устройств сопряжения. Две из них пока для нас недоступны - линии по передаче последовательных данных. А вот оставшиеся 4 предназначены для управления и индикации процесса передачи данных и мы сможем "переделать" их под свои нужды. Две из них предназначены для управления со стороны внешнего устройства и мы их пока трогать не будем, а вот последние две оставшиеся линии мы сейчас и будем использовать. Они называются:
* RTS - Запрос на передачу. Линия взаимодействия, которая показывает, что компьютер готов к приему данных.
* DTR - Компьютер готов. Линия взаимодействия, которая показывает, что компьютер включен и готов к связи.
Сейчас мы немного переделаем их назначение, и светодиоды, подключенные к ним будут либо тухнуть либо загораться, в зависимости от действий в нашей собственной программе.
Итак, давайте соберем схему, которая позволит нам проводить задуманные действия.
А вот ее практическая реализация. Я думаю Вы меня простите, что я сделал ее в таком стрёмном макетном варианте, ибо делать плату для такой "высоко продуктивной" схемы не хочется.
4. Программная часть
Тут все попроще. Давайте создадим Windows приложение в Microsoft Visual C++ 6.0 на основе MFC для управления двумя линиями взаимодействия COM порта. Для этого создаем новый проект MFC и указываем ему имя, например, TestCOM. Далее выбираем вариант построения на основе диалога.
Придайте внешний вид окну диалога нашей программы, как на рис. ниже, а именно добавьте четыре кнопки, по две на каждую из линий. Одна из них соответственно необходима для того чтобы "погасить" линию, другая чтобы ее "установить" в еденицу.
Далее, в файле TestCOMDlg.h в описание класса диалога добавьте строчку: HANDLE hFile;.
class CTestCOMDlg : public CDialog
{
// Construction
public:
CTestCOMDlg(CWnd* pParent = NULL); // standard constructor
HANDLE hFile;
Чтобы наша программа могла упрявлять линиями COM порта, его надо сначала открыть. Напишем код, ответственный за открытие порта при загрузке программы.
hFile = CreateFile("COM2", GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
MessageBox("Не удалось открыть порт!", "Оштбка", MB_ICONERROR);
}
else
{
MessageBox("Порт успешно открыт", "Ok", MB_OK);
}
С помощью стандарной функции Win API CreateFile() открываем COM-порт COM2. Далее проверяем успешность открытия с выводом информационного сообщения. Вот тут надо сделать важное замечание: COM2 - это в моем компьютере, а на Вашем компьютере Вы могли подключить его к другому COM порту. Соответственно, его имя нужно изменить на то, кокай порт Вы используете. Посмотреть, какие номера портов присутствуют на Вашем компьютере, можно так: Пуск -> Настройка -> Панель управления -> Система -> Оборудование -> Диспетчер устройств -> Порты (COM и LPT).
В итоге, функция CTestCOMDlg::OnInitDialog(), расположенная в файле TestCOMDlg.cpp, класса нашего диалога должна принять вид:
BOOL CTestCOMDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
hFile = CreateFile("COM2", GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
MessageBox("Не удалось открыть порт!", "Оштбка", MB_ICONERROR);
}
else
{
MessageBox("Порт успешно открыт", "Ok", MB_OK);
}
return TRUE; // return TRUE unless you set the focus to a control
}
Теперь добавим обработчики кнопок управления линиями. Я дал им соответствующие имена: функция, которая устанавливает еденицу на линии DTR - OnDTR1(), 0 - OnDTR0(). Для линии RTS соответственно аналогичным образом. Напомню, что обработчик создается при двойном щелчке на кнопке. В итоге, эти четыре функции должны принять вид:
void CTestCOMDlg::OnDTR1()
{
// TODO: Add your control notification handler code here
EscapeCommFunction(hFile, 6);
}
void CTestCOMDlg::OnDTR0()
{
// TODO: Add your control notification handler code here
EscapeCommFunction(hFile, 5);
}
void CTestCOMDlg::OnRTS1()
{
// TODO: Add your control notification handler code here
EscapeCommFunction(hFile, 4);
}
void CTestCOMDlg::OnRTS0()
{
// TODO: Add your control notification handler code here
EscapeCommFunction(hFile, 3);
}
Поясню немного как они работают. Как видно, внитри себя они содержат вызов одной и той же Win API функции EscapeCommFunction() с двумя параметрами. Первый из них - это хэндл (HANDLE) на открытый порт, второй - специальный код действия, соответствующий необходимому состоянию линии.
Все, комилируем, запускаем. Если все хорошо, должны увидеть сообщение об успешном открытии порта. Далее, нажатием соответствующих кнопок мигаем светодиодами, подключенными к COM порту. Если порт открылся, но нажатия кнопок не дают результата, убедитесь, что Ваше устройство подключено к тому же порту, который Вы открываете в функции CreateFile().
Иванов Д. В.
9 декабря 2006 года
www.pcports.ru