Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.07.2017, 07:33   #1
zvb
Пользователь
 
Регистрация: 17.07.2017
Сообщений: 11
Хорошо 9 бит данных по COM-порту

Есть некое устройство (купюроприёмник), работающее по последдовательному порту по протоколу MDB (protocol, which is based on a Motorola 9-bit UART implemented as an 8-bit data value with an additional mode bit. The mode bit differentiates between ADDRESS and DATA bytes). Для реализации на PC рекомендуют использовать бит чётности.
Есть программа, работающая с этим устройством из-под Windows. Вот её обмен с устройством, записанный с помощью портмонитора (кусок, где непосредственно посылаются данные, при необходимости выложу всё):
Код:
28	0.00000978	Mdb.exe	IOCTL_SERIAL_SET_BAUD_RATE	Serial0	SUCCESS	Rate: 9600	
29	0.00000587	Mdb.exe	IOCTL_SERIAL_CLR_RTS	Serial0	SUCCESS		
30	0.00000615	Mdb.exe	IOCTL_SERIAL_CLR_DTR	Serial0	SUCCESS		
31	0.00000419	Mdb.exe	IOCTL_SERIAL_SET_LINE_CONTROL	Serial0	SUCCESS	StopBits: 1 Parity: SPACE WordLength: 8	
32	0.00000307	Mdb.exe	IOCTL_SERIAL_SET_CHAR	Serial0	SUCCESS	EOF:0 ERR:0 BRK:0 EVT:0 XON:11 XOFF:13	
33	0.00000447	Mdb.exe	IOCTL_SERIAL_SET_HANDFLOW	Serial0	SUCCESS	Shake:0 Replace:0 XonLimit:2048 XoffLimit:512	
34	0.00000503	Mdb.exe	IRP_MJ_DEVICE_CONTROL	Serial0	SUCCESS	IOCTL: 0x1B009C	
35	0.00000251	Mdb.exe	IOCTL_SERIAL_GET_LINE_CONTROL	Serial0	SUCCESS		
36	0.00000475	Mdb.exe	IOCTL_SERIAL_SET_LINE_CONTROL	Serial0	SUCCESS	StopBits: 1 Parity: MARK WordLength: 8	
37	0.00000643	Mdb.exe	IOCTL_SERIAL_PURGE	Serial0	SUCCESS	Purge: TXABORT RXABORT TXCLEAR RXCLEAR	
38	0.00000615	Mdb.exe	IOCTL_SERIAL_SET_LINE_CONTROL	Serial0	SUCCESS	StopBits: 1 Parity: MARK WordLength: 8	
39	0.00002654	Mdb.exe	IRP_MJ_WRITE	Serial0	SUCCESS	Length 1: 33 	
40	0.00000559	Mdb.exe	IOCTL_SERIAL_SET_LINE_CONTROL	Serial0	SUCCESS	StopBits: 1 Parity: SPACE WordLength: 8	
41	0.00002375	Mdb.exe	IRP_MJ_WRITE	Serial0	SUCCESS	Length 1: 33 	
42	0.00000447	Mdb.exe	IOCTL_SERIAL_GET_COMMSTATUS	Serial0	SUCCESS		
43	0.00000223	Mdb.exe	IOCTL_SERIAL_GET_COMMSTATUS	Serial0	SUCCESS		
...
246	0.00000196	Mdb.exe	IOCTL_SERIAL_GET_COMMSTATUS	Serial0	SUCCESS		
247	0.00000279	Mdb.exe	IOCTL_SERIAL_GET_COMMSTATUS	Serial0	SUCCESS		
248	0.00000698	Mdb.exe	IRP_MJ_READ	Serial0	SUCCESS	Length 2: 06 06
Пытаюсь реализовать подобный обмен из своего кода, устройство не отвечает:
Код:
	hPort = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

        DCB dcb;
	GetCommState(hPort, &dcb);
	//dcb.fParity = dcb.fErrorChar = 1;
	dcb.BaudRate = CBR_9600;
	dcb.ByteSize = 8;
	dcb.StopBits = ONESTOPBIT;
	dcb.Parity = EVENPARITY;
	SetCommState(hPort, &dcb);

	COMMTIMEOUTS timeouts;
	GetCommTimeouts(hPort, &timeouts);
	timeouts.ReadIntervalTimeout = 10;
	timeouts.ReadTotalTimeoutMultiplier = 11;
	timeouts.ReadTotalTimeoutConstant = 500;
	timeouts.WriteTotalTimeoutMultiplier = 11;
	timeouts.WriteTotalTimeoutConstant = 100;
	SetCommTimeouts(hPort, &timeouts);

	dcb.Parity = SPACEPARITY;
	SetCommState(hPort, &dcb);

	dcb.Parity = MARKPARITY;
	SetCommState(hPort, &dcb);

	PurgeComm(hPort, PURGE_RXABORT | PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

	//SetCommMask(hPort, EV_ERR | EV_RXCHAR | EV_RXFLAG);

	dcb.Parity = MARKPARITY;
	SetCommState(hPort, &dcb);

	char buf[1024];
	buf[0] = 0x33;
	unsigned long nBytes;
	WriteFile(hPort, buf, 1, &nBytes, NULL);

	dcb.Parity = SPACEPARITY;
	SetCommState(hPort, &dcb);

	WriteFile(hPort, buf, 1, &nBytes, NULL);

	ReadFile(hPort, buf, 1, &nBytes, NULL);
Вопрос, как его победить?
zvb вне форума Ответить с цитированием
Старый 17.07.2017, 10:51   #2
agmag
Пользователь
 
Регистрация: 15.07.2017
Сообщений: 31
По умолчанию

Каковы возвращаемые значения функций API?
Код:
CreateFile
GetCommState
SetCommState
WriteFile
ReadFile
agmag вне форума Ответить с цитированием
Старый 17.07.2017, 10:59   #3
zvb
Пользователь
 
Регистрация: 17.07.2017
Сообщений: 11
По умолчанию

Цитата:
Сообщение от agmag Посмотреть сообщение
Каковы возвращаемые значения функций API?
Код:
CreateFile
GetCommState
SetCommState
WriteFile
ReadFile
Все TRUE. И по портмонитору видно, что всё нормально, только ответ от устройства не приходит (или оно не понимает моего запроса).
zvb вне форума Ответить с цитированием
Старый 17.07.2017, 11:25   #4
zvb
Пользователь
 
Регистрация: 17.07.2017
Сообщений: 11
По умолчанию

Можно и несколько более общих вопросов сформулировать:

1. Я правильно понимаю, что все манипуляции, например с SetCommState до того, как я вызову WriteFile порту на самом деле по барабану? Посмотрим на лог от работающей программы - в строке 31 установилось Parity: SPACE, потом в 36 - Parity: MARK, потом в 38 опять Parity: MARK. Это зачем?

2. Что происходило в программе когда в лог вывелась строка 34, там где IRP_MJ_DEVICE_CONTROL IOCTL: 0x1B009C ?

3. Как им удаётся сделать чистый IOCTL_SERIAL_SET_LINE_CONTROL ? Я меняю бит чётности путём вызова SetCommState, но в мониторе видно что при этом происходят и другие события - как в логе от строки 28 до строки 33.
zvb вне форума Ответить с цитированием
Старый 17.07.2017, 13:51   #5
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 1,772
По умолчанию

Цитата:
Сообщение от zvb Посмотреть сообщение
IRP_MJ_DEVICE_CONTROL IOCTL: 0x1B009C
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
Цитата:
Сообщение от zvb Посмотреть сообщение
Как им удаётся сделать
Покажите программу, посмотрю
Black Fregat вне форума Ответить с цитированием
Старый 17.07.2017, 14:32   #6
zvb
Пользователь
 
Регистрация: 17.07.2017
Сообщений: 11
По умолчанию

Цитата:
Сообщение от Black Fregat Посмотреть сообщение
Покажите программу, посмотрю
Exe-шник брал отсюда: http://www.cashcode.com.ua/content/blogcategory/9/25/ файл MDB.exe, исходников ясное дело нету.
Работает жёстко по COM1, для того чтобы начался обмен приведенный в логе надо нажать кнопку Connect.
zvb вне форума Ответить с цитированием
Старый 17.07.2017, 14:32   #7
kutani
Форумчанин
 
Регистрация: 23.01.2016
Сообщений: 608
По умолчанию

Цитата:
1. Я правильно понимаю
неправильно.

Цитата:
Я меняю бит чётности путём вызова SetCommState, но в мониторе видно что при этом происходят и другие события
там много и других состояний-линий контролируется:
Код:
     typedef struct _DCB {   
       DWORD DCBlength;               // sizeof(DCB)
       DWORD BaudRate;                 // current baud rate
       DWORD fBinary: 1;               // binary mode, no EOF check
       DWORD fParity: 1;                // enable parity checking
       DWORD fOutxCtsFlow:1;    // CTS output flow control
       DWORD fOutxDsrFlow:1;    // DSR output flow control
       DWORD fDtrControl:2;        // DTR flow control type
       DWORD fDsrSensitivity:1;   // DSR sensitivity 
       DWORD fTXContinueOnXoff:1;  // XOFF continues Tx
       DWORD fOutX: 1;                           // XON/XOFF out flow control
       DWORD fInX: 1;                             // XON/XOFF in flow control
       DWORD fErrorChar: 1;                 // enable error replacement
       DWORD fNull: 1;                            // enable null stripping
       DWORD fRtsControl:2;                // RTS flow control
       DWORD fAbortOnError:1;         // abort reads/writes on error
       DWORD fDummy2:17;                // reserved    WORD wReserved; // not currently used

       WORD XonLim;              // transmit XON threshold
       WORD XoffLim;              // transmit XOFF threshold
       BYTE ByteSize;              // number of bits/byte, 4-8
       BYTE Parity;                  // 0-4=no,odd,even,mark,space
       BYTE StopBits;              // 0,1,2 = 1, 1.5, 2
       char XonChar;              // Tx and Rx XON character
       char XoffChar;              // Tx and Rx XOFF character
       char ErrorChar;            // error replacement character

       char EofChar;               // end of input character
       char EvtChar;               // received event character
       WORD wReserved1;     // reserved; do not use
    } DCB;
Цитата:
9 бит
анализ бита Parity или управление им под виндами геморрой еще тот (переключение с parityMark на paritySpace происходит раньше, чем выйдет байт в TX-линию (будет байт с состоянием paritySpace). Начиная с NT есть минимальная системная пауза в 10 мс между адресным и последующим байтом... а сие может привести к восприятию удаленным устройством как срыв передачи. Так что, если вы не в 9х, воспользуйтесь прямым доступом к порту, через giveio и ему подобным драйверам.

Цитата:
MDB (protocol
что помешало не трахать мозг, а воспользоваться готовой либой - WinMDB32.dll ?
kutani вне форума Ответить с цитированием
Старый 17.07.2017, 14:44   #8
zvb
Пользователь
 
Регистрация: 17.07.2017
Сообщений: 11
По умолчанию

Цитата:
Сообщение от kutani Посмотреть сообщение
неправильно
А как правильно? Что произойдёт непосредственно в порту при других вызовах (не считая установки RTS/CTS), без посылки байтов?

Цитата:
Сообщение от kutani Посмотреть сообщение
там много и других состояний-линий контролируется
Угу. А как можно делать только SetLineControl ? (В работающей программе это им как-то удаётся).

Цитата:
Сообщение от kutani Посмотреть сообщение
что помешало не трахать мозг, а воспользоваться готовой либой - WinMDB32.dll ?
Спасибо, посмотрю, но только в качестве дополнительного источника информации. Окончательный обмен должен происходить из-под Линукса, под виндой решил отработать обмен потому-что был готовый эмулятор.
zvb вне форума Ответить с цитированием
Старый 17.07.2017, 14:49   #9
agmag
Пользователь
 
Регистрация: 15.07.2017
Сообщений: 31
По умолчанию

Можно попробовать вручную пообщаться с устройством через терминал:
https://sites.google.com/site/terminalbpp/
http://www.compt.ru/ru/index.php

Кстати, у меня был такой баг, когда символ на COM-порт не принимался.
Дело в том, что UART использует асинхронный протокол.
Т.е. после отправки символа нет гарантий, что он успел прийдти и уже находится во входном буффере контроллера. Поэтому читать сразу нельзя.

Поэтому, при программировании UART используются следующие походы:
1) ожидание поступления байта в буффер чтения и ожидание опустошения буффера отправки на основе прерываний
(использование событий
http://support.tenasys.com/INtimeHel...commevent.html
http://support.tenasys.com/INtimeHel...tcommmask.html)
2) ручная проверка регистра состояния в цикле(этот вариант для DOS'а)
https://www.lookrs232.com/rs232/lsr.htm
3) хак: вставка конкретной задержки после отправки символа(напр. 50 мсек), да и вообще после всех операций ввода-вывода. Возможно надо поэкспериментировать с длительностью задержки.
agmag вне форума Ответить с цитированием
Старый 17.07.2017, 15:23   #10
agmag
Пользователь
 
Регистрация: 15.07.2017
Сообщений: 31
По умолчанию

Цитата:
Угу. А как можно делать только SetLineControl ? (В работающей программе это им как-то удаётся).
Скорее всего используется DeviceIOControl.
https://msdn.microsoft.com/ru-ru/lib...(v=vs.85).aspx
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

Последний раз редактировалось agmag; 17.07.2017 в 15:38.
agmag вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Исправить код программы: Ввести с клавиатуры 8-разрядное двоичное число Х, установить младший бит этого числа так, чтобы количество единичных бит в двоичном числе Х стало четным Zhan1234 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 25.05.2017 12:41
Прием и передача данных по COM порту PTyTb32 Компоненты Delphi 2 26.06.2015 22:12
Побитовый контроль передаваемых по COM порту данных Lexa_kltn C/C++ Сетевое программирование 0 19.05.2011 14:39
Ковертирование из png 24 бит в png 8 бит isat Общие вопросы .NET 0 22.03.2010 13:38
Подключиться к COM порту doober Общие вопросы .NET 3 23.07.2009 13:34