Здравствуйте, _Mandor_, Вы писали:
_M_>Как сделать? _M_>Дайте пример. _M_>И запись тоже
Ууу. Это сложно будет. Читай про регистры устройства (3F8-3FF). DOS-ом (точнее BIOS-ом) поддерживаются скорости только до 9600 бод, что на сегодняшний день явно мало. А все остальное в DOS-е только ручками прямой записью значений в порты этой микросхемы (Motorola 16550 если я не ошибаюсь). Да еще и на прерывания неплохо было бы повеситься, чтобы вовремя ловить момент прихода байта. Пример не дам — слишком длинно и без теоретической базы (понимания принципов работы аппаратуры последовательного адаптера) не разберешься. Так как в виндах (CreateFile()->SetCommState()->ReadFile()/WriteFile()->CloseHandle()) не получится — в DOS-е это _намного_ сложнее. Зато интереснее и свободы больше. В этом есть свои плюсы .
"programmater" <34509@users.rsdn.ru> wrote in message news:1876857@news.rsdn.ru... > Здравствуйте, _Mandor_, Вы писали: > > _M_>Как сделать? > _M_>Дайте пример. > _M_>И запись тоже > Ууу. Это сложно будет. Читай про регистры устройства (3F8-3FF). DOS-ом (точнее BIOS-ом) поддерживаются скорости только до 9600 бод, что на сегодняшний день явно мало. А все остальное в DOS-е только ручками прямой записью значений в порты этой микросхемы (Motorola 16550 если я не ошибаюсь). Да еще и на прерывания неплохо было бы повеситься, чтобы вовремя ловить момент прихода байта. Пример не дам — слишком длинно и без теоретической базы (понимания принципов работы аппаратуры последовательного адаптера) не разберешься. Так как в виндах (CreateFile()->SetCommState()->ReadFile()/WriteFile()->CloseHandle()) не получится — в DOS-е это _намного_ сложнее. Зато интереснее и свободы больше. В этом есть свои плюсы .
Здравствуйте, programmater, Вы писали:
P>Ууу. Это сложно будет. Читай про регистры устройства (3F8-3FF). DOS-ом (точнее BIOS-ом) поддерживаются скорости только до 9600 бод, что на сегодняшний день явно мало. А все остальное в DOS-е только ручками прямой записью значений в порты этой микросхемы (Motorola 16550 если я не ошибаюсь). Да еще и на прерывания неплохо было бы повеситься, чтобы вовремя ловить момент прихода байта. Пример не дам — слишком длинно и без теоретической базы (понимания принципов работы аппаратуры последовательного адаптера) не разберешься.
Вообщето именно 9600 и нужно т.к. больше сама железяка не умеет.
Может все же разродитесь примером? ИМХО разберемся...
Здравствуйте, _Mandor_, Вы писали:
_M_>Здравствуйте, programmater, Вы писали:
P>>Ууу. Это сложно будет. Читай про регистры устройства (3F8-3FF). DOS-ом (точнее BIOS-ом) поддерживаются скорости только до 9600 бод, что на сегодняшний день явно мало. А все остальное в DOS-е только ручками прямой записью значений в порты этой микросхемы (Motorola 16550 если я не ошибаюсь). Да еще и на прерывания неплохо было бы повеситься, чтобы вовремя ловить момент прихода байта. Пример не дам — слишком длинно и без теоретической базы (понимания принципов работы аппаратуры последовательного адаптера) не разберешься.
_M_>Вообщето именно 9600 и нужно т.к. больше сама железяка не умеет. _M_>Может все же разродитесь примером? ИМХО разберемся...
Здравствуйте, _Mandor_, Вы писали:
_M_>А почему перенесли? Мне же пример на C++ надо...
Потому что работа с прерываниями на C++ делается сложнее, чем на ассемблере, а в DOS-е подобные вещи прерываниями делаются (это в случае 9600 и меньше) или вообще не делаются, только ручками прямой записью в порты (если выше 9600). Так что к сям придется ассемблерный переходник писать (типа функции WriteToPort(const char* Buf, unsigned short int BufLng)) и на сях использовать уже эту функцию. А тело самой этой функции лучше писать на асме. Так что переместили правильно.
Сейчас к сожалению доки по прерываниям BIOS нет, так что с ходу пример дать не могу. Как докопаюсь — дам.
Здравствуйте, DOOM, Вы писали:
DOO>Здравствуйте, _Mandor_, Вы писали:
_M_>>Как сделать? _M_>>Дайте пример. _M_>>И запись тоже
DOO>Сам в свое время по Журдену осваивал. DOO>P.S. Кодировка cp866 если что...
Кстати да, очень рекомендую для начала изучить то, что он пишет. Он правда пропустил прием и передачу данных через "средний уровень" (видимо оставил в качестве упражнения читателю ), а он явно проще "низкого уровня", который проводит Джордейн. Но средний уровень обладает очень серьезным недостатком: при приеме программа можент навечно зависнуть в ожидании байта, который (возможно) ей никогда не придет. И нет способа вывести программу из этого состояния, кроме как перезагрузить машину . В серьезных программах такое недопустимо, но для начала (для изучения работы DOS и последовательного адаптера) вполне сойдет. Я правда изучал все это по другим книгам и писал свои собственные функции, но то что за то, пишет Джордейн, ручаться не могу, но очень похоже на правду. Сейчас сочиню процедуры "среднего уровня" для работы с портом. Предупреждаю, tasm-а и turbo Debuger-а под рукой нет, так что возможно не будет компилироваться и не совсем правильно работать (ну давно я использовал все эти локальные переменные и передачу параметров из сей в ассемблер, так что могу со стеком намудрить). Я хочу показать идею, принцип. С конкретикой надеюсь _Mandor_ разберется. Поехали :
// Объявления в h файле.
функции записи буфера и приема серии байт писать на асме в лом. Хотя если переходить на схему с прерываниями от COM порта (а не прерыванем BIOS!), то писать надо будет именно такие функции. Но это уже следующий уровень. В одном посте не ответишь. Да и отлаживать долго. Так что сейчас всю "пакетность" пиши на сях.
Перед тем, как давать реализацию вышезадекларированных функций на асме приведу отрывок документации на прерывание BIOS 14h, которое используется при работе с последовательным портом.
15. INT 14H — функции асинхроннной связи
Следующие функции INT 14H поддерживают протокол RS-232-C:
(AH) = 0 — инициализация порта асинхронной связи;
1 — передача байта;
2 — прием байта;
3 — получить состояние;
4 — расширенная инициализация;
5 — расширенное управление портом связи.
Последние две функции применяются только в System/2.
Сохраняются значения всех регистров, кроме AX. Базовые адреса портов
адаптеров связи и значения таймаутов устанавливаются при инициализации БСВВ.
15.1. Инициализация порта асинхронной связи.
Параметры: (AH) = 0;
(DX) — номер канала (0 — 3) в соответствии с базовым
адресом портов в таблице БСВВ по адресу 40:0;
(AL) — параметры инициализации:
биты 1,0 = 00 — 5-ти битный код,
= 01 — 6-ти битный код,
= 10 — 7-ми битный код,
= 11 — 8-ми битный код;
бит 2 = 0 — 1 стоп-бит,
1 — 2 стоп-бита для 6-8-ми битного кода,
1,5 стоп-бита для 5-ти битного кода;
бит 3 = 0 — нет контроля по паритету,
= 1 — есть контроль по паритету;
бит 4 = 0 — контроль по нечетности,
= 1 — контроль по четности;
биты 7-5 — скорость обмена (бод):
= 000 — 110
= 100 — 150
= 010 — 300
= 110 — 600
= 001 — 1200
= 101 — 2400
= 011 — 4800
= 111 — 9600
Результаты: (AH) — состояние линии управления,
(AL) — состояние модема (см. 15.4).
15.2. Передача байта
Параметры: (AH) = 1;
(DX) — номер канала (0 — 3) в соответствии с базовым
адресом портов в таблице БСВВ по адресу 40:0;
(AL) — байт данных для передачи.
Результаты: (AH) — состояние линии управления (см. 15.4),
(AL) — сохраняется.
Если бит 7 состояния линии устанавливается в 1, то остальные биты
состояния непредсказуемы. Байт в этом случае не передан.
15.3. Прием байта
Параметры: (AH) = 2;
(DX) — номер канала (0 — 3) в соответствии с базовым
адресом портов в таблице БСВВ по адресу 40:0;
(AL) — байт данных для передачи.
Результаты: (AH) — состояние линии управления (см. 15.4),
(AL) — принятый байт данных.
Модуль БСВВ ожидает приема байта.
15.4. Получить состояние канала.
Параметры: (AH) = 3;
(DX) — номер канала (0 — 3) в соответствии с базовым
адресом портов в таблице БСВВ по адресу 40:0;
Результаты: (AH) — состояние линии управления:
бит 7 — таймаут
6 — конец передачи (КПД)
5 — готов к передаче (ГПД)
4 — обрыв канала (авария)
3 — ошибка по стоп-биту
2 — ошибка по паритету
1 — переполнение
0 — готов к приему (ГПР)
(AL) — состояние модема:
бит 7 — детектор принимаемого линейного
сигнала канала данных (цепь 109),
6 — индикатор вызова (цепь 125),
5 — аппаратура готова (цепь 107),
4 — готов к передаче (цепь 106).
Документация какая-то древняя, но другой все равно под рукой нет, так что пишу отталкиваясь от того, что имею. Итак, используя сведения из этой доки, пишем реализацию функций на ассемблере:
InitPort PROC NEAR
ARG PortNum:WORD , BaudRateCode:WORD , StopBitsCode:WORD , ParityCode:WORD
push bp ; стандартная конвенция входа в процедуру с использованием
mov bp,sp ; параметров и локальных переменных (в следующих функциях называется "пролог")
; возможно этот кусок кода будет сгенерирован ассемблером,
; но надо смотреть (из документации не ясно, а я сам уже забыл)
push dx ax
mov ax , BaudRateCode ; опять не помню как правильно: так
;mov ax , [BaudRateCode] или так.
or ax , StopBitsCode ; и далее обращения к локальным переменным. Если что, проставишь скобочки :)
or ax , ParityCode
or al , 3 ;8-ми битное слово. Сейчас других уже не бывает.
mov dx , PortNum ; вот здеть не проверяем на корректность. Передавай правильные значения (0 - COM1 и т.д.)
int 14h ;вызов прерывания BIOS для инициализации порта.
pop ax dx
pop bp ; тож может быть сгенерировано ассемблером вместе с кодом входа в процедуру (см.выше)
; далее "эпилог"
ret
InitPort Endp
ReadByteFromCOM proc NEAR
ARG PortNum:WORD
;--------------пролог---------------------------
push bp
mov bp,sp
;------------------------------------------------
push dx
mov dx,PortNum
mov ah,2
int 14h ; Вот тут можем повиснуть надолго (если ожидаемый нами байт не придет)
; это главный недостаток приема данных используя прерывания BIOS
; чтобы этого не было, нужно организовывать опрос (т.н. полинг)
; или работать по аппаратному прерыванию от COM порта.
; Но это уже ближе к Джордейну и его "низкому уровню"
mov ah,0
pop dx
pop bp ;------Эпилог-----------------
ret
ReadByteFromCOM endp
WriteByteToCOM proc NEAR
ARG PortNum:WORD , ByteToSend:WORD
;--------------пролог---------------------------
push bp
mov bp,sp
;------------------------------------------------
push ax dx
;в передаче данных есть одна тонкость: нужно убедиться, что передатчик готов
;т.е. передача предыдущего байта уже завершена. Теоретически здесь тоже можно
;зависнуть, так что если не в лом, потом сможешь сам организовать выход по таймауту.
;-------проверим готовность передатчика
;-------для этого прочитаем состояние линии (функция 3 прерывания 14h)
@@WAIT_COMM_TRANSMITTER_READY_LOP:
mov ah,3
mov dx,PortNum
int 14h
; теперь имеем в ah байт состояния линии. Проверим бит готовности передатчика
test ah , 32
jnz @@WAIT_COMM_TRANSMITTER_READY_LOP ; Если передатчик не готов, то переходим
; на опрос состояния линии.
; здесь вместо сразу перехода на опрос линии можно
; вставить еще и проверку таймаута (оставлю для упражнения)
; передатчик готов, можно передавать байт
mov ax , ByteToSend
mov ah , 1
mov dx PortNum ; по идее должен был сохраниться с предыдущего обращения к прерыванию.
; Но на всякий случай пишу (вот так и разрастаются программы :) )
; если хочешь, эту команду можно выбросить.
int 14h
pop dx ax
pop bp ;------Эпилог-----------------
ret
WriteByteToCOM endp
Теоретически функцию проверки состояния линии можно было оформить как отдельную сишную функцию и организовать работу по опросу (при этом теоретически можно было проверять и бит готовности приемника), т.е. никогда не зависнуть, всегда быть способным среагировать на действия юзера и т.д. Но я этого никогда не делал (в смысле через прерывания BIOS, я делал так, но только через чтение/запись портов контроллера, а прерывания от контроллера запрещал, но это к делу не относится), поэтому приводить код не стал — слишком большая вероятность, что что-то напутаю. Поэтому рекомендую поэкспериментировать с этой функцией, посмотреть, что она возвращает в разных ситуациях. Возможно это как-то использовать. Ну, вроде все. Направление я дал, а дальше копай. Удачи.
Одна поправка... Jourdain надо читать не по-английски, а по-французски. Т.е. все-таки Жу(ю)рден. А то получается как у Акунина в Алтын-Толобасе "...усиленно называл меня мистер Фандорайн...."
Здравствуйте, _Mandor_, Вы писали:
_M_>Как сделать? _M_>Дайте пример. _M_>И запись тоже
Вот то, чем я пользуюсь (будет работать под DOS16 и под DOS32).
Извините за размер.
Есть еще один вариант работы с COM-портом, если нужен, могу выслать на почту (только для DOS16).
Пример работы c функциями:
InstallCom(1,115200,8,0,1); //настраиваем параметры порта
ClearCom(1); //очищаем входной буфер
//постоянно читаем данные из порта и выводим на экранwhile(1)
{
while(DataSizeInCom(1))
printf("%c",ReadCom(1));
}
Заголовочный файл :
/* serial.h */
/* работа с последовательным портом для PC x86 */#if !defined _SERIAL_H_
#define _SERIAL_H_
/* input buffer size*/#define IN_BUF_SIZE 1024
#define __interrupt interrupt
#define __far far
#define __PARAM ...
#define NoError 0
#define ChkSumErr -1
#define TimeOut -2
void InstallCom1(long baud,int nbit,int parity,int stopbit); //установка параметров портаvoid RestoreCom1(); //закрытие портаint IsCom1(); //проверка наличия данных в буфере портаvoid ToCom1(int data); //отправка байта в портint ReadCom1(); //чтение байта из входного буфераvoid ClearCom1(); //очистка входного буфераint DataSizeInCom1(); //размер данных во входном буфереvoid __interrupt __far SerialISR1(__PARAM); //ф-ия обработки прерыванияvoid InstallCom2(long baud,int nbit,int parity,int stopbit); //установка параметров портаvoid RestoreCom2(); //закрытие портаint IsCom2(); //проверка наличия данных в буфере портаvoid ToCom2(int data); //отправка байта в портint ReadCom2(); //чтение байта из входного буфераvoid ClearCom2(); //очистка входного буфераint DataSizeInCom2(); //размер данных во входном буфереvoid __interrupt __far SerialISR2(__PARAM); //ф-ия обработки прерывания
// функции для работы с модулями 7000int SndRcvCom1(char *cmd, char * resp,char chksum,int timeout);//отправка команды/прием ответаint SndRcvCom2(char *cmd, char * resp,char chksum,int timeout);//отправка команды/прием ответа
// функции для ICOP-6070void Set485DirToTransmit2();//включить порт RS485 на передачуvoid Set485DirToReceive2(); //включить порт RS485 на прием
//общие функцииvoid InstallCom(int port, long baud, int nbit, int parity, int stopbit);
void RestoreCom(int port);
int IsCom(int port);
void ToCom(int port, int data);
int ReadCom(int port);
void ClearCom(int port);
int DataSizeInCom(int port);
void ToComStr(int port, char * str);
void ToComBufn(int port, char * buf, int size);
#endif//_SERIAL
CPP-шник:
/* serial.cpp */#include"serial.h"#include <dos.h>
//#include <i86.h>#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
/* baud */#define BR_110 0x410
#define BR_150 0x300
#define BR_300 0x180
#define BR_600 0xC0
#define BR_1200 0x60
#define BR_2400 0x30
#define BR_4800 0x18
#define BR_9600 0xC
#define BR_19200 0x6
#define BR_38400 0x3
#define BR_57600 0x2
#define BR_115200 0x1
/* nbit */#define bit_5 0x00
#define bit_6 0x01
#define bit_7 0x02
#define bit_8 0x03
/* parity */#define NoParity 0x00
#define Odd 0x08
#define Even 0x18
/* stopbit */#define OneStopBit 0x00
#define TwoStopBit 0x04
static char InBuf1[IN_BUF_SIZE];
static int wrcount1, rdcount1;
static char InBuf2[IN_BUF_SIZE];
static int wrcount2, rdcount2;
static void __interrupt __far (* oldvectCom1)(__PARAM);
static void __interrupt __far (* oldvectCom2)(__PARAM);
#define PORT1 0x3F8
#define INTVECT1 0xC
#define PORT2 0x2F8
#define INTVECT2 0xB
void __interrupt __far SerialISR1(__PARAM)
{// получено прерывание от портаwhile( inp(PORT1+5) & 0x01 )
{
if( wrcount1 >= IN_BUF_SIZE )
{
wrcount1 = 0;
rdcount1 = 0;
}
InBuf1[wrcount1++] = (char)inp(PORT1);
}
outp(0x20,0x20);
};
void InstallCom1(long baud,int nbit,int parity,int stopbit)
{
outp(PORT1+1,0); //запрещаем прерывания от UART
oldvectCom1 = _dos_getvect(INTVECT1); //получаем старый вектор прерывания
_dos_setvect(INTVECT1,SerialISR1); //устанавливаем новый вектор прерывания
outp(PORT1+3,0x80); //устанавливаем режим загрузки делителя
//скорость передачиswitch( baud )
{
case 110L: baud = BR_110; break;
case 150L: baud = BR_150; break;
case 300L: baud = BR_300; break;
case 600L: baud = BR_600; break;
case 1200L: baud = BR_1200; break;
case 2400L: baud = BR_2400; break;
case 4800L: baud = BR_4800; break;
case 9600L: baud = BR_9600; break;
case 19200L: baud = BR_19200; break;
case 38400L: baud = BR_38400; break;
case 57600L: baud = BR_57600; break;
case 115200L: baud = BR_115200; break;
default: baud = BR_9600;
}
outp(PORT1+0, baud & 0xFF ); //загружаем младший байт делителя
outp(PORT1+1,baud>>8); //загружаем старший байт делителя
//кол-во битswitch( nbit )
{
case 5: nbit = bit_5; break;
case 6: nbit = bit_6; break;
case 7: nbit = bit_7; break;
case 8: nbit = bit_8; break;
default: nbit = bit_8;
};
//четностьswitch( parity )
{
case 0: parity = NoParity; break;
case 1: parity = Odd; break;
case 2: parity = Even; break;
default: parity = NoParity;
};
//стоп-битыswitch( stopbit )
{
case 1: stopbit = OneStopBit; break;
case 2: stopbit = TwoStopBit; break;
default: stopbit = OneStopBit;
};
outp(PORT1+3,nbit|parity|stopbit); //настраиваем формат передачи: кол-во бит/паритет/стоп-бит
outp(PORT1+2,0x07); //буфер FIFO - 1 байт, включаем буфер
outp(PORT1+4,0x0B); //устанавливаем линии RTS, DTR, OUT1
outp(0x21,inp(0x21)&0xEF); //настраиваем регистр маски прерываний контроллера прер-й
outp(PORT1+1,0x01); //разрешаем контроллеру UART прерывание по приему байта
};
void RestoreCom1()
{
outp(PORT1+1,0); //запрещаем прерывания от UART*/
outp(0x21,(inp(0x21)|0x10)); //маскируем линию запроса прерыванияif( oldvectCom1 )
_dos_setvect(INTVECT1, oldvectCom1); //возвращаем старый вектор прерывания
};
int IsCom1()
{
return ( wrcount1 > rdcount1 );
};
int ReadCom1()
{
if( wrcount1 > rdcount1 )
return InBuf1[rdcount1++];
return -1;
};
void ToCom1(int data)
{
while( !(inp(PORT1+5) & 0x20) );//ждем отправки байта
outp(PORT1+0,data);//отправляем байт
};
void ClearCom1()
{
wrcount1 = rdcount1 = 0;
};
int DataSizeInCom1()
{
return (wrcount1 - rdcount1);
};
void __interrupt __far SerialISR2(__PARAM)
{//получено прерывание от портаwhile( inp(PORT2+5) & 0x01 )
{
if( wrcount2 >= IN_BUF_SIZE )
{
wrcount2 = 0;
rdcount2 = 0;
}
InBuf2[wrcount2++] = (char)inp(PORT2);
}
outp(0x20,0x20);
};
void InstallCom2(long baud,int nbit,int parity,int stopbit)
{
outp(PORT2+1,0); //запрещаем прерывания от UART
oldvectCom2 = _dos_getvect(INTVECT2);//получаем старый вектор прерывания
_dos_setvect(INTVECT2,SerialISR2); //устанавливаем новый вектор прерывания
outp(PORT2+3,0x80); //устанавливаем режим загрузки делителя
//скорость передачиswitch( baud )
{
case 110L: baud = BR_110; break;
case 150L: baud = BR_150; break;
case 300L: baud = BR_300; break;
case 600L: baud = BR_600; break;
case 1200L: baud = BR_1200; break;
case 2400L: baud = BR_2400; break;
case 4800L: baud = BR_4800; break;
case 9600L: baud = BR_9600; break;
case 19200L: baud = BR_19200; break;
case 38400L: baud = BR_38400; break;
case 57600L: baud = BR_57600; break;
case 115200L: baud = BR_115200; break;
default: baud = BR_9600;
}
outp(PORT2+0, baud & 0xFF ); //загружаем младший байт делителя
outp(PORT2+1,baud>>8); //загружаем старший байт делителя
//кол-во битswitch( nbit )
{
case 5: nbit = bit_5; break;
case 6: nbit = bit_6; break;
case 7: nbit = bit_7; break;
case 8: nbit = bit_8; break;
default: nbit = bit_8;
};
//четностьswitch( parity )
{
case 0: parity = NoParity; break;
case 1: parity = Odd; break;
case 2: parity = Even; break;
default: parity = NoParity;
};
//стоп-битыswitch( stopbit )
{
case 1: stopbit = OneStopBit; break;
case 2: stopbit = TwoStopBit; break;
default: stopbit = OneStopBit;
};
outp(PORT2+3,nbit|parity|stopbit); //настраиваем формат передачи: бит/паритет/стоп-бит
outp(PORT2+2,0x7); //буфер FIFO - 1 байт, включаем буфер
outp(PORT2+4,0x0B); //устанавливаем линии RTS, DTR, OUT1
outp(0x21,inp(0x21)&0xF7); //настраиваем регистр маски прерываний контроллера прер-й
outp(PORT2+1,0x01); //разрешаем контроллеру UART прерывание по приему байта
};
void RestoreCom2()
{
outp(PORT2+1,0);//запрещаем прерывания от UART*/
outp(0x21,(inp(0x21)|0x10));//маскируем линию запроса прерыванияif( oldvectCom2 )
_dos_setvect(INTVECT2, oldvectCom2);//возвращаем старый вектор прерывания
};
int IsCom2()
{
return ( wrcount2 > rdcount2 );
};
int ReadCom2()
{
if( wrcount2 > rdcount2 )
return InBuf2[rdcount2++];
return -1;
};
void ToCom2(int data)
{
while( !(inp(PORT2+5) & 0x20) );
outp(PORT2+0,data);
};
void ClearCom2()
{
wrcount2 = rdcount2 = 0;
};
int DataSizeInCom2()
{
return (wrcount2 - rdcount2);
};
void Set485DirToTransmit2()
{
outp( PORT2+4, inp(PORT2+4) | 0x02 );//устанавливаем линию RTS
}
void Set485DirToReceive2()
{
outp( PORT2+4, inp(PORT2+4) & 0xFD );//сбрасываем линию RTS
}
//функции для работы с модулями 7000
//отправка команды/прием ответаint SndRcvCom1(char *cmd, char * resp,char chksum,int timeout)
{
unsigned char sum = 0;
char sumstr[2];
if( chksum )
{
for( int i = 0; i < strlen(cmd); i++ )
sum += cmd[i];
sprintf(sumstr,"%02X",sum);
}
//отправка командыfor( int byte = 0; byte < strlen(cmd); byte++ )
ToCom1(cmd[byte]);
if( chksum )
{
ToCom1(sumstr[0]);
ToCom1(sumstr[1]);
}
ToCom1('\r');
//
clock_t start_time = clock(), end_time;
//ждем появления данныхint counter = 0;
char ch;
do
{
while( !IsCom1() )
{
end_time = clock();
if( (end_time - start_time) >= timeout ) return TimeOut;
}
ch = (char)ReadCom1();
resp[counter++] = ch;
}
while( ch != '\r' );
if( counter )
{
counter--;
resp[counter] = 0;
}
if( chksum )
{
if( strlen(resp) < 2 ) return ChkSumErr;
sum = 0;
for( int i = 0; i < strlen(resp)-2; i++ )
sum += resp[i];
if( sum == (unsigned char)strtoul(resp+strlen(resp)-2,0,16) )
{
resp[strlen(resp)-2] = 0;
return NoError;
}
else
{
return ChkSumErr;
}
}
return NoError;
}
/* отправка команды/прием ответа */int SndRcvCom2(char *cmd, char * resp,char chksum,int timeout)
{
unsigned char sum = 0;
char sumstr[3];
if( chksum )
{
for( int i = 0; i < strlen(cmd); i++ )
sum += cmd[i];
sprintf(sumstr,"%02X",sum);
}
//отправка командыfor( int byte = 0; byte < strlen(cmd); byte++ )
ToCom2(cmd[byte]);
if( chksum )
{
ToCom2(sumstr[0]);
ToCom2(sumstr[1]);
}
ToCom2('\r');
//
clock_t start_time = clock(), end_time;
//ждем появления данныхint counter = 0;
char ch;
do
{
while( !IsCom2() )
{
end_time = clock();
if( (end_time - start_time) >= timeout ) return TimeOut;
}
ch = (char)ReadCom2();
if( resp )
resp[counter++] = ch;
}
while( ch != '\r' );
if( counter )
{
counter--;
resp[counter] = 0;
}
if( chksum )
{
if( strlen(resp) < 2 ) return ChkSumErr;
sum = 0;
for( int i = 0; i < strlen(resp)-2; i++ )
sum += resp[i];
if( sum == (unsigned char)strtoul(resp+strlen(resp)-2,0,16) )
{
resp[strlen(resp)-2] = 0;
return NoError;
}
else
{
return ChkSumErr;
}
}
return NoError;
}
void InstallCom(int port, long baud, int nbit, int parity, int stopbit)
{
switch( port )
{
case 1: InstallCom1(baud, nbit, parity, stopbit);break;
case 2: InstallCom2(baud, nbit, parity, stopbit);break;
default: InstallCom1(baud, nbit, parity, stopbit);break;
}
};
void RestoreCom(int port)
{
switch( port )
{
case 1: RestoreCom1();break;
case 2: RestoreCom2();break;
default: RestoreCom1();break;
}
};
int IsCom(int port)
{
switch( port )
{
case 1: return IsCom1();
case 2: return IsCom2();
default: return IsCom1();
}
};
void ToCom(int port, int data )
{
switch( port )
{
case 1: ToCom1(data); break;
case 2: ToCom2(data); break;
default: ToCom1(data); break;
}
};
int ReadCom(int port)
{
switch( port )
{
case 1: return ReadCom1();
case 2: return ReadCom2();
default: return ReadCom1();
}
};
void ClearCom(int port)
{
switch( port )
{
case 1: ClearCom1(); break;
case 2: ClearCom2(); break;
default: ClearCom1(); break;
}
};
int DataSizeInCom(int port)
{
switch( port )
{
case 1: return DataSizeInCom1();
case 2: return DataSizeInCom2();
default: return DataSizeInCom1();
}
};
void ToComStr(int port, char * str)
{
for( int i = 0; i < strlen(str); i++)
ToCom(port,str[i]);
};
void ToComBufn(int port, char * buf, int size)
{
for( int i = 0; i < size; i++)
ToCom(port,buf[i]);
};