Сообщение от
Илья Кареткин
...Что значит быстрота..при какой длине RS-485 проявляется разница..?
Длина кабеля минимальная – 10 см. Это ведь копейки.
Программу писал как на чистом Си с использованием WinAPI, так и на C# с использованием компонента SerialPort. Когда работаю по 232-му - ответ получаю сразу. Причём ошибки встречаются крайне редко - 1/1000, да даже и того реже.
Когда работаю по 485-му сразу же чувствуется нестабильность работы.
В программе на Си эта нестабильность проявляется в следующем:
1) В ответ приходит абракадабра или ответ "ERROR"
2) Вообще ничего не приходит. Может таймауты маленькие? Но длинные таймауты не помогают. Пробовал работать через дублирование команд (посылать запрос пока не получу "OK"). Работает, но на каждую команду с несколькими перезапросами уходит время, что неприемлемо. Если находишься в режиме передачи данных AT+CIPSEND - то не понимаешь - перешёл ли модем в режим посылки данных или нет.
3) Приходит "OK" или другой ответ в зависимости от контекста. Причём у модема бывают периоды обострения, т.е. когда он отвечает успешно на несколько команд подряд, а потом опять себя ведёт не так как надо.
В программе на C# по событию DataReceived ответы приходят, но такое чувство, что модем получает команду, отвечает на неё, но реагирует на содержание команды не сразу.
Например, посылая команду "AT+CMGF=0", а потом запрашивая "AT+CMGF?" (переключился ли он в этот режим или нет) обычно заканчивается 3 ситуациями:
1) Режим сразу же был изменён.
2) Режим не был изменён и, как показывает практика, не будет изменён, пока не послать "AT+CMGF=0" ещё несколько раз.
3) Модем вообще ничего не ответил, либо ответил следующую абракадабру:
Запрос: AT+CMGF=0
Оmвеm: bcb~0
Запрос: AT+CMGF?
Оmвеm: b?gp?3?_?
Запрос: AT+CMGF=0
Оmвеm: OK
Запрос: AT+CMGF?
Оmвеm: ??A- j; 8?C8??? ?
Поражает то, что по 232-му всё работает как в сказке!
И ещё...
Программы (а точнее их части, отвечающие за приём/передачу через порт) отлично работают с ОВЕН МСД-100 по 485-му интерфейсу!
Код настройки порта:
Код:
HANDLE hSerialPort; // Дескприптор для последовательного порта
BOOL SetDCB() // Настраиваем порт
{
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerialPort, &dcbSerialParams)) printf("\nError getting serial port state\n");
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerialPort, &dcbSerialParams)) return FALSE;
else return TRUE;
}
BOOL SetTimeOuts() // Устанавливаем таймауты для порта
{
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 100;
timeouts.ReadTotalTimeoutMultiplier = 2;
timeouts.ReadTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hSerialPort, &timeouts)) return FALSE;
else return TRUE;
}
void OpenPort(unsigned const char* PortName) // Функция открытия порта
{
hSerialPort = CreateFile(PortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerialPort == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND) printf("\nSerial port (%s) doesn't exist\n",PortName);
else printf("\nError opening serial port (%s)\n",PortName);
}
if (SetDCB() == FALSE) printf("\nError setting serial port state (%s)\n",PortName);;
if (SetTimeOuts() == FALSE) printf("\nError setting serial port timeouts (%s)\n",PortName);;
}
void ClosePort() // Функция закрытия порта
{
CloseHandle(hSerialPort);
}