#1 2009-10-08 20:46:09

milt
Ветеран
Зарегистрирован: 2008-04-22
Сообщений: 78
Профиль

Работа с COM-портом с заточкой под RS-485 под ДОС

В связи с тем, что компьютерные платы становятся всё дешевле и дешевле (AMD Geode в типоразмере 2.5" стоит нынче 160$), такие платы довольно удобно использовать во многих приложениях реального времени, например, для управления чем-либо, обработки данных и т.п.. Вот тут и всплывает проблема "дальней" связи с такой платой. Наиболее простое решение - реализация интерфейса RS-485.

Вот тут и всплывает давно забытый досовский "дзен", например, работа с COM-портом. Компьютер, как правило, не имеет встроенного интерфейса RS-485, а имеет интерфейс RS-232. Дальность связи по интерфейсу RS-232 редко превышает 10м, а для перехода от интерфейса RS-232 к RS-485 используют переходные адаптеры.

Интерфейс RS-232 предназначен для работы в дуплексном режиме, т.е. может одновременно принимать и передавать данные. Но полный дуплекс редко где используется, имеет смысл "затачивать" программу под полудуплекс, т.е. сразу делать работу по порту совместимой с протоколом RS-485: в этом протоколе передача и приём не могут идти одновременно, т.к. в протоколе RS-485 приём и передача идут по одним и тем же проводам. Ну и как дополнительный аргумент, говорящий в пользу такого подхода - по дуплексному интерфейсу RS-232 полудуплексный софт для RS-485 всегда будет работать smile

Вобщем, функции ввода-вывода программы должны быть настроены на работу через интерфейс RS-232, но с учётом RS-485: когда ведём передачу - приёма быть не должно.


Канал RS-485 настроен на приём, и переключается на передачу только в момент появления данных на выходе TxD на COM-порте. Есть автоматические переключатели, которые реализуют ф-цию переключения приём-передача по наличию данных на выводе TxD COM-порта (например, IP-CON), но большинство простых адаптеров используют дополнительный вывод COM-порта для переключения направления приём-передача. Обычно, это вывод RTS - этот вывод участвует в синхронной передаче данных, однако, некоторые поделки успешно используют вывод DTR. Чтобы не было промашки с выводом адаптера, лучше "дёргать" при передаче оба вывода: и RTS, и DTR. При передаче состояние RTS=DTR=0.

Работу c COM-портом под ДОС целесообразно вести без прерываний: производительность обычно избыточная, от пропускания приёма байта спасает кэш в контроллере COM-порта. При такой организации легко реализуются тайминги обмена и обработка ошибок, не требуется сложная привязка к контроллеру прерываний, которые сейчас, мягко говоря, могут несколько отличаться от того, что было 10 лет назад (ага, можно подумать, что каскадное включение 8259 вырублено навечно smile )

Пусть есть глобальные переменные: uart_base - базовый адрес порта, uart_rate - скорость в бодах. Ниже приводится ф-ция для инициализации COM-порта. Весь код написан для WATCOM C под экстендер DOS4G.

Код:

BOOL link_init(void)
{
    BOOL        bRet=FALSE;
    WORD        divider;

    divider=(uart_rate)?115200/uart_rate:0xFFFF;
    outp(uart_base+3,0x80);                         // переводим в режим установки скорости
    if ((inp(uart_base+3)&0x80)==0) goto lini_exit; // выход, если нет порта
    outp(uart_base+0,(BYTE)(divider&0xFF));         // мл.байт делителя
    if (inp(uart_base+0)!=((BYTE)(divider&0xFF))) goto lini_exit;   // выход, если нет порта
    outp(uart_base+1,(BYTE)(divider>>8));           // ст.байт делителя
    if (inp(uart_base+1)!=((BYTE)(divider>>8))) goto lini_exit;     // выход, если нет порта
    outp(uart_base+3,0x03);                         // управление линией, протокол 8N1
    if ((inp(uart_base+3)&0x80)) goto lini_exit;    // выход, если нет порта
    outp(uart_base+1,0x00);                         // прерывания выключены
    outp(uart_base+4,0x03);                         //485: DTR==1, RTS=1
    outp(uart_base+2,0x07);                         // сброс FIFO
    bRet=TRUE;
lini_exit:
    return bRet;
}

Ф-ция link_init возвращает TRUE в случае успешной инициализации порта. В принципе, эту ф-цию можно использовать для поиска порта в адресном пространстве PC: в uart_base записываем номер базового порта (3F8h, 2F8h, 3E8h, 2E8h) и вызываем ф-цию link_init. Если ф-ция вернула TRUE - порт есть, FALSE - порта нет.

Для реализации таймаутов удобно использовать таймер системы: достаточно просто читать его текущее значение. В отличие от Windows и Linux, шаг таймера под ДОС грубее - всего 55млС, но для большинства применений этого шага вполне достаточно. Вот ф-ция чтения кол-ва тиков таймера от начала старта системы GetTickCount.

Код:

DWORD GetTickCount(void)
{
    return *((PDWORD)0x46C);
}

Ниже приводится ф-ция приёма байта с учётом таймаута.

Код:

BOOL link_rxbyte(PBYTE val)
{
    DWORD       stoptick;

    outp(uart_base+4,0x03);                         //485: DTR==1, RTS==1
    stoptick=GetTickCount()+TIMEOUT_RX;
    while ((inp(uart_base+5)&0x01)==0)
        if (GetTickCount()>=stoptick) return FALSE;
    *val=inp(uart_base+0);
    return TRUE;
}

Если байт принят, ф-ция возвращает TRUE.

Ф-ция передачи байта, если байт успешно передан, то возвращает TRUE.

Код:

BOOL link_txbyte(BYTE val)
{
    DWORD       stoptick;

    stoptick=GetTickCount()+TIMEOUT_TX;
    while ((inp(uart_base+5)&0x20)==0)              // ожидание освобождения буфера передачи
        if (GetTickCount()>=stoptick) return FALSE;
    outp(uart_base+4,0x00);                         //485: DTR==0, RTS==0
    outp(uart_base+0,val);                          // вывод байта
    // ожидание конца передачи (для RS485)
    stoptick=GetTickCount()+TIMEOUT_TX;             //485: установка таймаута ожидания конца передачи
    while ((inp(uart_base+5)&0x60)!=0x60)           //485: ожидание конца передачи
        if (GetTickCount()>=stoptick) return FALSE; //485: выход по таймауту
    outp(uart_base+4,0x03);                         //485: DTR==1, RTS==1
    outp(uart_base+2,0x07);                         //485: убиваем эхо, сбросом FIFO
    return TRUE;
}

Вот собственно и всё. Всё просто smile

Неактивен

 

#2 2010-05-17 19:48:23

krik8
Новичок
Зарегистрирован: 2010-05-17
Сообщений: 1
Профиль

Re: Работа с COM-портом с заточкой под RS-485 под ДОС

Вопрос: здесь используется режим FIFO?

Неактивен

 

#3 2010-05-18 20:49:29

kam
Бывалый
Зарегистрирован: 2008-04-24
Сообщений: 34
Профиль

Re: Работа с COM-портом с заточкой под RS-485 под ДОС

Только для приёма, педарача без фифы.

Неактивен

 

Board footer

Powered by PunBB

[ Generated in 0.016 seconds, 9 queries executed ]