Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Программирование интерфейса RS232 
:(
    Опции темы
Gremlin
Дата 28.8.2006, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Если ктото имеет информацию по данному вопросу или писал программы большая просьба выложить здесь листинги функций или ссылки на них  где люди смогут найти ответы на свои вопросы! А меня собственно интересует список апи функций для работы с этим интерфейсом! Заранее благодарен! 
PM MAIL   Вверх
_hunter
Дата 28.8.2006, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 13
Всего: 98



Цитата(Gremlin @  28.8.2006,  11:03 Найти цитируемый пост)
А меня собственно интересует список апи функций для работы с этим интерфейсом

если интересует -- почему поиском не воспользовался?
http://www.izone.kiev.ua/articles/delphi/16/282.htm


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
chozen
Дата 28.8.2006, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 64
Регистрация: 14.8.2006

Репутация: нет
Всего: нет



bugtraq.ru/library/programming/rs232.html
www.opennet.ru/openforum/vsluhforumID9/5319.html 

- первые же строчки гугла smile  smile 

PM MAIL   Вверх
bel_nikita
Дата 28.8.2006, 23:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 4
Всего: 47



Цитата(Gremlin @ 28.8.2006,  10:03)
А меня собственно интересует список апи функций для работы с этим интерфейсом!

Собственно одним списком не отделаешься smile 
Тема не раз уже обсуждалась. Взгляни сюда, правда сделано через MFC, но можешь "заточить" под себя


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Gremlin
Дата 29.8.2006, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



ой а нет ли случайно у кого Агуров П. - Последовательные интерфейсы ПК. в электронном варианте выложите сцылочку

Добавлено @ 21:08 
да и ешо вот посмотрел я все выложенные сцылки! у меня в ммануале на прибор сказано типа команда LVn - выбор канала (n=1..10)
или экзамплы (Pc->Instrument) TS4.85E+0 типа выставить погрешность
дак вот я не понял как мне послать данные команды smile 
PM MAIL   Вверх
GremlinProg
Дата 30.8.2006, 07:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



В этом мануале и поищи формат команд для твоего девайса, для RS232 нет специализированного языка, каждый может использовать свой интерфейс ввода-вывода


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 30.8.2006, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



а вот  я столкнулся с двумя случаями какой выбрать
есть класс CSerial и HANDLE ? оба открывают порты устанавливают скорость и тд и тп
PM MAIL   Вверх
chozen
Дата 30.8.2006, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 64
Регистрация: 14.8.2006

Репутация: нет
Всего: нет



Что-то мне сомнительным кажется наличие класса HANDLE... Мож это не класс, а что-нибудь другое smile  smile  smile ???

Если одинаковые, используй тот, название которого передает смысл области применения - CSerial.
PM MAIL   Вверх
Gremlin
Дата 30.8.2006, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Код

HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);

lpFileName — указатель на строку с нулевым завершающим символом. Обычно это имя открываемого файла, но в нашем случае это должно быть название порта (COM1, COM2, …). 
dwDesiredAccess — тип доступа. В нашем случае должен быть равен GENERIC_READ|GENERIC_WRITE. 
dwShareMode — параметр совместного доступа. Для коммуникационных портов всегда равен 0. 
lpSecurityAttributes — атрибут защиты. Для коммуникационных портов всегда равен NULL. 
dwCreationDistribution — режим автосоздания. Для коммуникационных портов всегда равен OPEN_EXESTING. 
dwFlagsAndAttributes — атрибут режима обработки. Для коммуникационных портов должен быть равен 0 или FILE_FLAG_OVERLAPPED. 
hTemplateFile — описатель файла-шаблона. Для коммуникационных портов должен быть равен NULL. 
При успешном открытии порта функция возвращает его описатель, а в случае ошибки возвращает INVALID_HANDLE_VALUE.

Добавлено @ 11:49 
Цитата(GremlinProg @  30.8.2006,  07:43 Найти цитируемый пост)
В этом мануале и поищи формат команд для твоего девайса, для RS232 нет специализированного языка, каждый может использовать свой интерфейс ввода-вывода 

Написано так
The protocol structure is defined in the syntax below. Data transfer takes place as simple ASCII protocol with
Command code - 2 characters
Parameters: 1..8 characters
Separator: ,;:/
Terminators: <cr><lf>, <cr> or <lf>
Blanks are ignored
Upper and lower case letters are allowed
и пример дан
Command(PC -> Instrument): TS<cr>
Replay(Instrument -> PC): TS4.26E+0<cr>

Это сообщение отредактировал(а) Gremlin - 30.8.2006, 11:50
PM MAIL   Вверх
GremlinProg
Дата 30.8.2006, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



ну, эта команда, по крайней мере понятна:

Код

struct command_TS{
  char name[2];
  byte args_size;
  char separator;// = '.'
  float param
  char terminator;// = '\r' or '\n'
};

вот, к примеру её инициализация и посылка
Код

command_TS cmd = {{'T','S'},sizeof(float),'.',26E+0,'\n'};
RS232Write(&cmd,sizeof(cmd));

RS232Write - условная функция для посылки в RS232 с двумя параметрами: 1 - адрес данных, 2 - размер данных
PS: структуру надо упаковыть прагмой.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Fixin
Дата 30.8.2006, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



Пример посылки команды
Цитата(Gremlin @  30.8.2006,  11:39 Найти цитируемый пост)
TS<cr>
а это ответ:
Цитата(Gremlin @  30.8.2006,  11:39 Найти цитируемый пост)
TS4.26E+0<cr>


PM MAIL ICQ   Вверх
Fixin
Дата 30.8.2006, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



GremlinProg, ты думаешь? Вообщето, послав такую структуру мы не получим команду вида
Цитата(Gremlin @  30.8.2006,  11:39 Найти цитируемый пост)
 TS<cr>
а что-то вроде
Цитата
TS<0x04>.<00><00><D0><41><cr><lf>
вместо
Цитата
TS<cr><lf>


PM MAIL ICQ   Вверх
GremlinProg
Дата 30.8.2006, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Fixin, может быть...

наверное 4.26E+0 - это и есть параметр, тогда нужно сделать иначе:
Код

char szBuffer[1024];
sprintf(szBuffer,"TS%.2e\n",epsilon);
RS232Write(szBuffer,strlen(szBuffer));

а в общем случае, если параметров несколько, разделять их чем нибудь из ",;:/"

Это сообщение отредактировал(а) GremlinProg - 30.8.2006, 16:12


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 31.8.2006, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



В хидере класса объявил DCB DcbPort;
В конструкторе класса пишу DcbPort.ByteSize = 8;
Поставил точку остановки после этого и смотрю значение DcbPort.ByteSize = 8 +'пустой квадратик'
т.е. эта переменная имеет тип unsigned char, но как такое может быть если оно должно быть типа BYTE _DcbPort.ByteSize! Подскажите пожалуйста как решить данный трабл!
PM MAIL   Вверх
_hunter
Дата 31.8.2006, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 13
Всего: 98



а BYTE это и есть unsigned char (правой кнопкой по BYTE тыкни и там выбери Goto declaration)


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
Fixin
Дата 2.9.2006, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 8
Всего: 18



Цитата(Gremlin @  31.8.2006,  17:53 Найти цитируемый пост)
как решить данный трабл!
ну это уже офтоповый трабл - это раз, и в чем проблема-то - это два.
имхо, квадратик после циферки в дебаггере - это отображения символа из таблицы ASCII по номеру, в данном случае, 8 - неотображаемый символ, вот и видишь ты квадратик пустой.

PM MAIL ICQ   Вверх
Gremlin
Дата 3.9.2006, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Как мне послать устройству команды описанные выше например TS
Код

if (!SetCommMask(hPort, EV_RXCHAR)) 
         MessageBox("Error setting port mask");

    DWORD dwWrite;
    OVERLAPPED OverWrite;
    BYTE WriteBytes[2] = "TS"; 
    OverWrite.hEvent = CreateEvent(NULL, true, false, NULL);
    if (OverWrite.hEvent == NULL)
        MessageBox("Error creating write event");
    if (!WriteFile(hPort, WriteBytes, sizeof(WriteBytes), &dwWrite, &OverWrite) && (GetLastError() != ERROR_IO_PENDING))
                              MessageBox("Error writing port"); 

 BYTE WriteBytes[2] = "TS"; --- вот здесь как записать команду



Это сообщение отредактировал(а) Gremlin - 3.9.2006, 12:45
PM MAIL   Вверх
GremlinProg
Дата 3.9.2006, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



показал ведь уже:
Код

double epsilon = 4.26E+0;
CHAR WriteBytes[1024]; 
sprintf(WriteBytes,"TS%.2e\n",epsilon);

после выполнения sprintf, в массиве WriteBytes будет содержаться команда TS4.26E+0<CR>
Здесь epsilon выставили в 4.26E+0, но если её поменяешь, соответственно поменяется и команда в массиве WriteBytes

отправляешь WriteBytes так:
Код

WriteFile(hPort, WriteBytes, strlen(WriteBytes), &dwWrite, &OverWrite)



--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 3.9.2006, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



ок тока чото я не понимаю запись TS%.2e\n и разве не нужно <cr>? 
PM MAIL   Вверх
GremlinProg
Дата 3.9.2006, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



\n - это и есть <cr>, в принципе, исходя из информации, которую ты тут выложил, можно использовать любой из четырех вариантов завершения команды: \n , \r, \r\n, \n\r, я выбрал первый.
%.2e - строка, форматирующая вещественное число в такой вот, экспоненциальный вид: x.xxE+x


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 3.9.2006, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Аааа понятно!! Вот ешо! Я открываю ком порт у него есть такие свойства как parity, bitssize, stopbits какие значения мне необходимо выставить ибо в мануале только сказано что baudrate = 9600, а остальное не сказано smile
PM MAIL   Вверх
GremlinProg
Дата 3.9.2006, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



обычно на железе сильно не заморачиваются, так что обычно програмят с параметрами Dcb,  выставленными следующим образом
Цитата

  Dcb.Parity    = NOPARITY;
  Dcb.ByteSize  = 8;
  Dcb.StopBits  = ONESTOPBIT;

но для большей надежности, я заполняю Dcb исходя из текущего состояния порта, т.е. пееред тем как выставлять Parity, ByteSize..., вызови GetCommState(port,Dcb). Это установит флаги Dcb так, как они были установлены при последнем обращении к порту.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 4.9.2006, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Сделал так
Код

// --- Перевод в режим прием данных ---
    if (!SetCommMask(hPort, EV_RXCHAR)) 
         MessageBox("Error setting port mask");
    //--- посылка----
    double epsilon = 4.26E+0;
    CHAR WriteBytes[1024]; 
    sprintf(WriteBytes,"TS%.2e\n",epsilon);
    DWORD dwWrite;
    OVERLAPPED OverWrite;
    
    OverWrite.hEvent = CreateEvent(NULL, true, false, NULL);
    if (OverWrite.hEvent == NULL)
        MessageBox("Error creating write event");
    if (!WriteFile(hPort, WriteBytes, sizeof(WriteBytes), &dwWrite, &OverWrite) && (GetLastError() == ERROR_IO_PENDING))
                              MessageBox("Error writing port"); 
    //--- ответ ---
    COMSTAT ComStat;
    DWORD dwMask, dwError;
    OVERLAPPED OverRead;
    CHAR Buf[1024];                         
    DWORD dwRead; 
    OverRead.hEvent = CreateEvent(NULL, true, false, NULL);
    if (OverRead.hEvent == NULL) 
        MessageBox("Error creating read event");

        
    if  (!WaitCommEvent(hPort, &dwMask, &OverRead)) 
    {
        if (GetLastError() == ERROR_IO_PENDING)
            WaitForSingleObject(OverRead.hEvent, INFINITE); 
        else 
            MessageBox("Error waiting port event");
        
    }
    if (!ClearCommError(hPort, &dwError, &ComStat))
           MessageBox("Error clearing port"); 
    
    dwRead = ComStat.cbInQue; 
    if (dwRead > 0) 
    {
        if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead)) 
             MessageBox("Error reading port");
    }

На месте WaitForSingleObject(OverRead.hEvent, INFINITE); он уходит в раздумья типа ничего с прибора не получает ответа даже опшибки smile


Это сообщение отредактировал(а) Gremlin - 4.9.2006, 12:42
PM MAIL   Вверх
GremlinProg
Дата 4.9.2006, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(Gremlin @  4.9.2006,  14:40 Найти цитируемый пост)
На месте WaitForSingleObject(OverRead.hEvent, INFINITE); он уходит в раздумья типа ничего с прибора не получает ответа даже опшибки 

перед тем, как отправлять в порт свои команды, пошли в него просто 1-2 байта для синхронизации, например таких: "\0\n". Это, скорее всего, решит проблему.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 5.9.2006, 07:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



ой а мне сказали нужно разделить потоки Thread для чтения тока не сказали как! И кстати у меня не получается послать команду т.е. прибор не реагирует на команду smile
PM MAIL   Вверх
GremlinProg
Дата 5.9.2006, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



всю прверку WaitCommEvent нужно положить в "бесконечный" цикл, а цикл - в отдельный поток. Любое чтение байт из порта нужно каждый раз сбрасывать в отдельный буфер (организовать очередь), а после добавления новых байт в эту очередь - выполнять, нужную тебе, процедуру обработки буфера. Перед работой потока желательно синхронизировать I/O порта с I/O машины (см. предыдущий пост), иначе будешь практически всегда терять, по крайней мере, первый байт как на прием, так и на передачу(возможно из за рассинхронизации команда и не принимается устройством).

Все это нужно делать в идеальном случае.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 8.9.2006, 06:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Ошибка первая была в том что нужно инициализировать  OVERLAPPED OverRead ={0}; и теперь я нормально посылаю команды Read еще не пробовал но если можно то мне бы сэмпл по поводу создания отдельного потока
PM MAIL   Вверх
GremlinProg
Дата 8.9.2006, 07:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



по идее, OverRead и OverWrite должны быть инициализированы в ноль перед использованием
Цитата(MSDN)

This structure should always be initialized to zero before it is used in a function call. If it is not, the function may fail and return ERROR_INVALID_PARAMETER.


Добавлено @ 07:14 
http://msdn.microsoft.com/library/default....reatethread.asp
http://msdn.microsoft.com/library/default....ginthreadex.asp


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 13.9.2006, 07:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Сходил по ссылке данной в начале топика http://www.izone.kiev.ua/articles/delphi/16/282.htm там пример но в делфи тама написано так:

"Рассмотрение работы с потоками в Windows, в частности того, как это реализовано в Delphi, выходит за рамки данной статьи. Предполагаю, что читатель встречался или по крайней мере знаком с этим. Скажу лишь, что у любого потока есть главная функция, которая начинает выполняться после его создания. В Delphi для потоков существует класс TThread, а его главная процедура называется TThread.Execute(). 

Вот так выглядит главная процедура отдельного потока, которая ожидает появление одного или нескольких символов и считывает их:

Код

procedure TReadThread.Execute;
var ComStat: TComStat; 
dwMask, dwError: DWORD; 
OverRead: TOverlapped; 
Buf: array[0..$FF] of Byte; 
dwRead: DWORD;
begin OverRead.hEvent := CreateEvent(nil, True, False, nil); 
if OverRead.hEvent = Null then  raise Exception.Create('Error creating read event'); 
FreeOnTerminate := True;  
while not Terminated do begin   
if not WaitCommEvent(hPort, dwMask, @OverRead) 
then   begin    
if GetLastError = ERROR_IO_PENDING 
then      WaitForSingleObject(OverRead.hEvent, INFINITE)    
else      raise Exception.Create('Error waiting port event');   
end;   
if not ClearCommError(hPort, dwError, @ComStat) 
then     raise Exception.Create('Error clearing port');   
dwRead := ComStat.cbInQue;  
 if dwRead > 0 then   begin     
if not ReadFile(hPort, Buf, dwRead, dwRead, @OverRead)
 then       raise Exception.Create('Error reading port');     
// В Buf находятся прочитанные байты     
// Далее идет обработка принятых байтов   
end;
end; 
{while}end; 


В приведенном примере в потоке крутится цикл, тем самым инициируется ожидание события порта вызовом функции WaitCommEvent(), ожидание же самого этого события задается функцией WaitForSingleObject(). Для определения количества принятых символов используется функция ClearCommError(). Когда количество принятых символов (dwRead) известно, непосредственное чтение символов выполняется функцией ReadFile(). "

Как это реализовать в Си? не могу найти какой функцией в Си пользоваться вместо TReadThread.Execute помогите плз!

PM MAIL   Вверх
GremlinProg
Дата 13.9.2006, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Сходи по ссылкам предыдущего поста. 2 ссылки - 2 решения, выбирай любое, какое нравится. Примеры там же, но для первой ищи For an example, see... в конце страницы.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 15.9.2006, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Код

uintptr_t _beginthread( 
   void( __cdecl *start_address )( void * ),
   unsigned stack_size,
   void *arglist 
);
делаю как в примере только своя функция в потоке а объявление тоже как и в примере
  _beginthread( ReadBuff, 0, NULL );
где
Код

void ReadBuff( void *dummy )
{
    
    repeat = 0;    /* _endthread implied */

}
компилю получаю еггог не может преобразовать void(void *) в void(_cdecl *)(void *) None of the functions whith this name in scope match the target type и что делать?

PM MAIL   Вверх
dumb
Дата 15.9.2006, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 27
Всего: 158



дык
Код

void _cdecl ReadBuff( void *dummy )
{
  repeat = 0;
}

PM MAIL   Вверх
Gremlin
Дата 17.9.2006, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Не там просил void(cdecl *)(void *) я сделал так объявил в хидере void (__cdecl *ReadABuffer)(void *dummy); без описания _beginthread( ReadABuffer, 0, NULL ); компилит без проблем но кагда я её пытаюсь описать эту функцию
void (__cdecl *ReadABuffer)(void *dummy)
{} то на на скобке вылезает еггог d:\C++_Project\Visual C++.NET\Kistler Measuring Hardware\MultiAmp.cpp(833): error C2470: 'ReadABuffer' : looks like a function definition, but there is no formal parameter list; skipping apparent body
тоесть функция выглядит как функция но не функция гыгы и не знаю что и сделать теперь smile

PM MAIL   Вверх
Gremlin
Дата 18.9.2006, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Возможно в компиляторе нужно чтото включить? хотя там мультитридинг стоит
PM MAIL   Вверх
GremlinProg
Дата 18.9.2006, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



это называется "гадание на кофейной гуще"
покажи код


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 18.9.2006, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



для _beginthread callback должен выглядеть так:
Код

void __cdecl ReadBuff( void * ptr ){
  ...
}
а для _beginthreadex callback должен выглядеть так:
Код

unsigned __stdcall ReadBuff( void * ptr ){
  ...
}
обе функции порождают поток, только _beginthreadex дает больше параметров для настройки этого потока

void(__cdecl*FType)(void *) - это описание ТИПА функции(здесь имя типа FType)
void __cdecl func(void *) - это описание функции(здесь имя функции func)

разницу видишь?

Это сообщение отредактировал(а) GremlinProg - 18.9.2006, 17:55


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 19.9.2006, 05:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Ааааааа два дня сижу думаю твою дивизию тоесть я сделал так в хидере void (__cdecl *ReadABuffer)(void *dummy); а в цпп описываю не указатель а саму функцию void __cdecl ReadABuffer(void *dummy); блин как сразу не допенькалsmile огромное вам спасибо за хелп!!!
PM MAIL   Вверх
Gremlin
Дата 19.9.2006, 08:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Такс серавно чото не получается вопщем у меня есть класс его хидер:
Код

#pragma once
#include "afxwin.h"


// CMultiAmp dialog

class CMultiAmp : public CPropertyPage
{
    DECLARE_DYNAMIC(CMultiAmp)

public:
    CMultiAmp();
    virtual ~CMultiAmp();

// Dialog Data
    enum { IDD = IDD_DIALOG2 };

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    RECT m_RectSpaceWhite;
    DECLARE_MESSAGE_MAP()
public:
    HANDLE hPort;
    virtual BOOL OnInitDialog();
    bool WriteABuffer(char* lpBuf, DWORD dwToWrite);
    CMultiAmp *MultiAmp; // временная переменная для хранений полей во вкладке MultiAmp
    //--- Переменные и обработчики Каналов
    ...
    //--- Переменные и обработчики Меток;
    ...
    //--- Переменные и обработчики Чувствительности
    ...
    //--- Переменные и обработчики единиц Чувствительности
    ...
    //--- Переменные и обработчики Диапазона
    ...
    //--- Переменные и обработчики Единиц измерения
    ...
    //--- Переменные и обработчики Фильтров
    ...
    //--- Переменные и обработчики Постоянной по времени
    ...
    
public:
    CMultiAmp& operator = (const CMultiAmp&); //операция присваивания
    void (__cdecl *ReadABuffer)(void *dummy);
    ...
};

СPP:

Код

// MultiAmp.cpp : implementation file
//

#include "stdafx.h"
#include "Kistler Measuring Hardware.h"
#include "MultiAmp.h"
#include ".\multiamp.h"
#include "RSSetup.h"
#include <process.h>    /* _beginthread, _endthread */




#define MAX_THREADS 2
#define BUF_SIZE 255

// CMultiAmp dialog

IMPLEMENT_DYNAMIC(CMultiAmp, CPropertyPage)
CMultiAmp::CMultiAmp()
    : CPropertyPage(CMultiAmp::IDD)
    
{
}

CMultiAmp::~CMultiAmp()
{
}
CMultiAmp& CMultiAmp::operator = (const CMultiAmp& cmultiamp)
{
...
    return *this;
}
void CMultiAmp::DoDataExchange(CDataExchange* pDX)
{
    CPropertyPage::DoDataExchange(pDX);
    ...
}


BEGIN_MESSAGE_MAP(CMultiAmp, CPropertyPage)
    ...
END_MESSAGE_MAP()


// CMultiAmp message handlers


//}    

BOOL CMultiAmp::OnInitDialog()
{
    CPropertyPage::OnInitDialog();
    // TODO:  Add extra initialization here
    

    //--- Начальная инициализация полей------
    // канал 1
    ...
    // канал 2
    ...
    // канал 3
    ...
    // ----------------------------------------    
    
    //--- Ограничения по вводу в поля
    ...
    

    return TRUE;  // return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
}

bool CMultiAmp::WriteABuffer(char* lpBuf, DWORD dwToWrite)
{    
    OVERLAPPED osWrite = {0};
    DWORD dwWritten;
    DWORD dwRes;
    BOOL fRes;

   // Create this write operation's OVERLAPPED structure's hEvent.
    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osWrite.hEvent == NULL)
    {
       // error creating overlapped event handle
        MessageBox("Error creating write event");
        return false; 
    }
    // Issue write.
    if (!WriteFile(hPort, lpBuf, dwToWrite, &dwWritten, &osWrite))
    {    
        if (GetLastError() != ERROR_IO_PENDING) 
        { 
            MessageBox("Error writing port"); 
            fRes = false;
        }
        else
        {
            // Write is pending.
            dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
            switch(dwRes)
            {
                // OVERLAPPED structure's event has been signaled. 
                case WAIT_OBJECT_0:
                    if (!GetOverlappedResult(hPort, &osWrite, &dwWritten, FALSE))
                        fRes = FALSE;
                    else
                    // Write operation completed successfully.
                    fRes = TRUE;
                    break;
                
                default:
                    // An error has occurred in WaitForSingleObject.
                    // This usually indicates a problem with the
                    // OVERLAPPED structure's event handle.
                    fRes = FALSE;
                    break;
            }
        }
    }
    else
    {    
       // WriteFile completed immediately.
        fRes = TRUE;
    }

    CloseHandle(osWrite.hEvent);
    return fRes;
}
BOOL CMultiAmp::OnApply()
{
    // TODO: Add your specialized code here and/or call the base class
    // --- набор команд ---

    //------------------------ 1 Канал -------------------------
    
    ...
    //------------------------ 2 Канал -------------------------
    
    ...
    //------------------------ 3 Канал -------------------------
    ...
    
    WriteABuffer(&Command[0], strlen(Command));
    
    // ----- Чтение параметров ----------

    _beginthread( ReadABuffer, 0, NULL );

    _endthread();
    return CPropertyPage::OnApply();
}
void __cdecl ReadABuffer(void *dummy)
{
    //--- ответ ---
    CMultiAmp MultiAmp;
    HANDLE hPort = MultiAmp.GethPort();
    COMSTAT ComStat;
    DWORD dwMask, dwError;
    OVERLAPPED OverRead;
    CHAR Buf[1024];                         
    DWORD dwRead; 
    OverRead.hEvent = CreateEvent(NULL, true, false, NULL);
    if (OverRead.hEvent == NULL) 
        AfxMessageBox("Error creating write event");
//

//    
    if  (!WaitCommEvent(hPort, &dwMask, &OverRead)) 
    {
        if (GetLastError() == ERROR_IO_PENDING)
            WaitForSingleObject(OverRead.hEvent, INFINITE);
        else 
            AfxMessageBox("Error waiting port event");
        
    }
//    if (!ClearCommError(hPort, &dwError, &ComStat))
//           MessageBox("Error clearing port"); 
//    
//    dwRead = ComStat.cbInQue; 
//    if (dwRead > 0) 
//    {
//        if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead)) 
//             MessageBox("Error reading port");
//    }
//    // В  Buf находятся прочитанные байты
//    // Далее идет  обработка принятых байтов
}

/// далее идут обработчики событий


И блин если я так объявляю то члены класса не видны в функции ReadABuffer 
а мне нужно чтоб это все в классе делалось smile или подскажи другую реализацию
PM MAIL   Вверх
GremlinProg
Дата 19.9.2006, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Код

class CMultiAmp : public CPropertyPage{
    ...
public:
    //    StaticReadABuffer - статический callback
    static void __cdecl StaticReadABuffer(void *dummy){
        ((CMultiAmp*)dummy)->ReadABuffer();
    }
    ...
    BOOL OnApply()
    {
        ...
        HANDLE hstream    = (HANDLE)_beginthread(StaticReadABuffer,0,(void*)this);
        WaitForSingleObject(hstream,INFINITE);
        //    WaitForSingleObject не вернет результат, пока поток не завершится,
        //    в данном случае, пока не выполнится процедура ReadABuffer
        //    _endthread() вызывать не нужно, иначе поток завершится преждевременно
        //    WaitForSingleObject можешь поставить в любое нужное тебе место,
        //    но тогда и hstream должен быть виден в классе
        ...
    }
    ...
    void ReadABuffer(void){
        // здесь работаешь уже с классом в потоке
        GethPort();
        ...
    }
    ...
};



--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 19.9.2006, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



ага сибо мудреное объявление но вроде робитsmile


Это сообщение отредактировал(а) Gremlin - 19.9.2006, 18:25
PM MAIL   Вверх
GremlinProg
Дата 19.9.2006, 18:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



у меня не ругается, компилер другой, вынеси реализацию этих методов в cpp или хотя бы StaticReadABuffer


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 19.9.2006, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Код

void CMultiAmp::ReadABuffer(void)
{
    OVERLAPPED OverRead = {0};
    COMSTAT ComStat;
    DWORD dwMask, dwError;
    char Buf[1024];                         
    DWORD dwRead; 
    if (!SetCommMask(hPort, EV_RXCHAR)) 
        MessageBox("Error setting port mask");
    OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (OverRead.hEvent == NULL) 
        MessageBox("Error creating write event");
    if  (!WaitCommEvent(hPort, &dwMask, &OverRead)) 
    {
        if (GetLastError() == ERROR_IO_PENDING)
            WaitForSingleObject(OverRead.hEvent, INFINITE);
        else 
            AfxMessageBox("Error waiting port event");
        
    }
    if (!ClearCommError(hPort, &dwError, &ComStat))
           MessageBox("Error clearing port"); 
    
    dwRead = ComStat.cbInQue; 
    if (dwRead > 0) 
    {
        if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead)) 
             MessageBox("Error reading port");
    }
    // В  Buf находятся прочитанные байты
    // Далее идет  обработка принятых байтов
}

Но я думал что создав другой поток я смогу работать с остальным приложением нормально а оно виснет и ждет ответа с ком порта


Это сообщение отредактировал(а) Gremlin - 19.9.2006, 18:54
PM MAIL   Вверх
GremlinProg
Дата 19.9.2006, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(GremlinProg @  19.9.2006,  12:09 Найти цитируемый пост)
WaitForSingleObject не вернет результат, пока поток не завершится

Ну убери WaitForSingleObject вообще, либо поставь перед завершением программы.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 19.9.2006, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Цитата(GremlinProg @  19.9.2006,  19:01 Найти цитируемый пост)
Ну убери WaitForSingleObject вообще, либо поставь перед завершением программы. 
 А как лучше её внутри ReadABuffer или после закрытия потока?


Это сообщение отредактировал(а) Gremlin - 19.9.2006, 19:38
PM MAIL   Вверх
GremlinProg
Дата 19.9.2006, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Я говорю вот про вэйт после создания потока :
Код

        HANDLE hstream    = (HANDLE)_beginthread(StaticReadABuffer,0,(void*)this);
        WaitForSingleObject(hstream,INFINITE);

Убери его пока, чтобы ничего не висло. Правильнее будет поставить его перед завершением программы, например в WM_DESTROY (это только в случае, если нужно освободить какие-нибудь ресурсы, используемые в потоке, например буфер, в который ты складываешь инфу с кома или сбросить буфера в файл и т.п.)


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 20.9.2006, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



При выполнении
Код

void CMultiAmp::ReadABuffer(void)
{
    char Command[1024] = "LV1;OE1;";
    strcat(Command, "TS");
    strcat(Command, "\n");
    WriteABuffer(&Command[0], strlen(Command));
    if (!PurgeComm(hPort, PURGE_TXCLEAR && PURGE_RXCLEAR)) 
        MessageBox("Error purging port");
    OVERLAPPED OverRead = {0};
    COMSTAT ComStat;
    DWORD dwMask, dwError;
    char Buf[1024];                         
    DWORD dwRead; 
    if (!SetCommMask(hPort, EV_RXCHAR)) 
        MessageBox("Error setting port mask");
    OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (OverRead.hEvent == NULL) 
        MessageBox("Error creating write event");
    
    if  (!WaitCommEvent(hPort, &dwMask, &OverRead)) 
    {
        if (GetLastError() == ERROR_IO_PENDING)
            WaitForSingleObject(OverRead.hEvent, INFINITE);
        else 
            AfxMessageBox("Error waiting port event");
    }
   
    if (!ClearCommError(hPort, &dwError, &ComStat))
           MessageBox("Error clearing port"); 
    
    dwRead = ComStat.cbInQue; 
    
    if (dwRead > 0) 
    {
        if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead)) 
             MessageBox("Error reading port");
    }
    
    // В  Buf находятся прочитанные байты
    // Далее идет  обработка принятых байтов
}

заметил что переводит в состояние Ожидание байтов, и даже после выполнения функции и завершения потока я не могу записать в порт. поэтому в конце я стал ставить  
Код

if (!SetCommMask(hPort, 0)
        MessageBox("Error setting port mask");

тогда все нормально!
Но вот проблема начинается в другом! Задача у меня следующая: Есть кнопки Старт и Стоп. Нажимаю Старт и открывается поток с функией Write которая причом в цикле посылает команду опрашивать текущее значение!
Нажимаю клавишу Стоп цыкл останавливается. Сразу после открытия потока Write открывается поток с Read
Код

void CKistlerMeasuringHardwareDlg::OnStart()
{
    // TODO: Add your control notification handler code here
    HANDLE hstream  = (HANDLE)_beginthread(StaticWriteCOM,0,(void*)this);
    HANDLE hstreamr  = (HANDLE)_beginthread(StaticReadCOM,0,(void*)this);
}

Но в buf ничего не приходит тк ком порт занят Write, подскажите как мне разрулить эти два потока!

Это сообщение отредактировал(а) Gremlin - 6.10.2006, 18:22
PM MAIL   Вверх
Gremlin
Дата 6.10.2006, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



вот так реализован цикл
Код

void CKistlerMeasuringHardwareDlg::WriteCOM(void)
{
    if (!PurgeComm(hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR) )
        MessageBox("Error purging port");
    
    MultiAmpT1.hPort = hPort;

    CountMeasuring = 0;
    char CommandStart[5]= "RO1";
    char CommandStop[5]= "RO0";
    char Command[100] = "";
    if (!hPort)
    {
        MessageBox("Нет открытых портов!");
        return;
    }
    
    if(!MultiAmpT1.WriteABuffer(&CommandStart[0], strlen(CommandStart)))
        return;
    if (MultiAmpT1.m_Status1 == true)
        strcat(Command, "LV1;V=;");
    if (MultiAmpT1.m_Status2 == true)
        strcat(Command, "LV2;V=;");
    if (MultiAmpT1.m_Status3 == true)
        strcat(Command, "LV3;V=;");
    if (MultiAmpT1.m_Status4 == true)
        strcat(Command, "LV4;V=;");
    // Активизация кнопок 
    CButton* start = (CButton*) GetDlgItem(IDC_START);
    start->EnableWindow(false);
    CButton* stop = (CButton*) GetDlgItem(IDC_STOP);
    stop->EnableWindow(true);
    while (StopFlag == false)
    {
        MultiAmpT1.WriteABuffer(&Command[0], strlen(Command));
        Sleep(100);
        CountMeasuring++;
    }
    
    
    start->EnableWindow(true);
    stop->EnableWindow(false);

    StopFlag = false;
    CString str;
    str.Format("%i",CountMeasuring);
    
    //MessageBox(str);
    if (!SetCommMask(MultiAmpT1.hPort, 0)) 
        MessageBox("Error setting port mask");
    if(!MultiAmpT1.WriteABuffer(&CommandStop[0], strlen(CommandStop)))
        return;
    return;
}


Это сообщение отредактировал(а) Fixin - 7.10.2006, 09:03
PM MAIL   Вверх
Gremlin
Дата 8.10.2006, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



Это сообщение отредактировал Fixin - 7.10.2006, 09:03 ????????
PM MAIL   Вверх
Gremlin
Дата 8.10.2006, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



 и еше вопрос почему чтобы получить коректно данные мне приходится вводить Sleep и подбирать милисекунды хотя поидее назначая маску EV_RXCHAR (событие получение символа) а потом идет (!WaitCommEvent(hPort, &dwMask, &OverRead))  тоесть ждать до наступления события маски дак почему мне приходится искуственно вводить задержку?
PM MAIL   Вверх
GremlinProg
Дата 8.10.2006, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



писать то в цикле не надо, это читать может понадобится несколько раз.
пишешь 1 раз, затем начинаешь читать и пока не прочитаешь верный отклик от железки, ни чего писать в порт не надо. Дождись ответа, затем можно снова писать команду и снова читать и т.д. Сделай эту операцию парной чтение-запись, тогда все будет ок.

Добавлено @ 22:07 
поток, по сути нужен только для того, чтобы винду не вешать во время чтения.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 9.10.2006, 05:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



дак мне тогда придется чтобы послать кнопочку старт жать smile ведь мне нужно чтобы команды постоянно посылались до того момента пока я не выключу а как это реализовать без цыкла?????

Добавлено @ 05:30 
я то делаю поток на Write  именно для того чтоб из основного потока смог остановить цыкл и завершить поток
PM MAIL   Вверх
GremlinProg
Дата 9.10.2006, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Это-то понятно, но в любом случае, на каждую команду записи нужно дождаться отклика. Это можно сделать 2-мя способами:

1.  Использовать события. Создай 2 события с помощью функций CreateEvent, допустим hReadCommand и hAbort. В потоке чтения, после того как отклик получен, поднимаешь событие hReadCommand, на которое реагирует поток записи, он проверяет флаг fStopped и если флаг опущен, то посылает очередной запорс в железку. В конце программы поднимай событие hAbort, на которое реагируют оба потока, они по этому событию будут выходить из цикла, тем самым, савершая потоки. После того, как в основной программе поднимаешь событие hAbort, жди оба потока с помощью функции WaitForMultiplyObjects. Можно завести 3-тье событие hWriteCommand, вместо флага fStopped, которое поднимается при нажатии кнопки "Пролдолжить" и "Старт". На это событие будет реагировать поток записи, оно будет сигнализировать, чтобы начать цикл посылки команд в железо.

2. Использовать сообщения. То же самое, но только заводишь не события а дополнительные сообщения(либо с помощью RegisterWindowMessage, либо просто WM_USER + 500), которые обрабатываешь в основном окне, а вместо сигнализации посылаешь из потока чтения SendMessage самому себе, либо крутишь PostMessage. В этом случае достаточно и 1 потока.

Выбирай любой способ, который по душе. Конечно, не просто, но раз уж взялся за такое дело...

ЗЫ: мусор в буфере как раз и обуславливается бесконечной посылкой в железо команд: в то время, как первая команда начинает ложится в буфер, приходит вторая, в буфере собирается кусок первой и кусок второй и т.д., в конечном счете ни одну команду толком разобрать не можешь, поэтому и ставишь искусственно задержку слипом, не хорошо.


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Gremlin
Дата 19.10.2006, 07:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 119
Регистрация: 28.8.2006

Репутация: нет
Всего: нет



"В конце программы поднимай событие hAbort, на которое реагируют оба потока, они по этому событию будут выходить из цикла, тем самым, савершая потоки. "
Не понял как это реализовать тоесть потоки должны робить и одновременно ожидать этого события! Следовательно по аналогии с hReadCommand WaitForSingleObject(hAbort, 2000) использовать нельзя дак как мне в любом месте выполнения потока отловить это сообщение и закрыть потоки/циклы?


Это сообщение отредактировал(а) Gremlin - 29.10.2006, 10:04
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.2157 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.