Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: RS232 и передача 0
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
kolisnichenko_r
Здравствуйте!
Использую для работы с СОМ портом потоки WINAPI и функции ResumeThread(), SuspendThread(). За основу взята программа с сайта http://www.piclist.ru/S-COM-THREAD-RUS/S-COM-THREAD-RUS.html. Разные значения отсылаются, но если есть где-то в посылке нолевое значение - отправка прерывается. Как можно передать 0? Дайте совет, пожалуйста.
Код передачи:
Код
//peredacha - 10 byte
   memset(bufwr,0,BUFSIZE);            //очистить программный передающий буфер, чтобы данные не накладывались друг на друга
   PurgeComm(COMport, PURGE_TXCLEAR);           //очистить передающий буфер порта
   for(unsigned char icd=0;icd<10;icd++){bufwr[icd]=comand[icd];}
   ResumeThread(writer);               //активировать поток записи данных в порт
MrYuran
Попробуйте поиграться с флажком fnull структуры DCB
Помнится, были с ним проблемы, правда, при приёме
kolisnichenko_r
Цитата(MrYuran @ Jul 12 2010, 15:21) *
Попробуйте поиграться с флажком fnull структуры DCB
Помнится, были с ним проблемы, правда, при приёме

Разрешение на прием 0 есть:
Код
dcb.fNull = FALSE;//разрешить приём нулевых байтов

Может где-то тут покопаться:
Код
reader = CreateThread(NULL, 0, ReadThread, NULL, 0, NULL);//создаём поток чтения, который сразу начнёт выполняться (предпоследний параметр = 0)
writer = CreateThread(NULL, 0, WriteThread, NULL, CREATE_SUSPENDED, NULL);//создаём поток записи в остановленном состоянии (предпоследний параметр = CREATE_SUSPENDED)


Нашел:
Код
//главная функция потока, выполняет передачу байтов из буфера в COM-порт
DWORD WINAPI WriteThread(LPVOID)
{DWORD temp, signal;    //temp - переменная-заглушка
overlappedwr.hEvent = CreateEvent(NULL, true, true, NULL);         //создать событие
while(1)
  {WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr);  //записать байты в порт (перекрываемая операция!)
    signal = WaitForSingleObject(overlappedwr.hEvent, INFINITE);      //приостановить поток, пока не завершится перекрываемая операция WriteFile
   if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlappedwr, &temp, true)))    //если операция завершилась успешно
     {
      Form1->StatusBar1->Panels->Items[0]->Text  = "Передача прошла успешно";    //вывести сообщение об этом в строке состояния
     }
   else {Form1->StatusBar1->Panels->Items[0]->Text  = "Ошибка передачи";}     //иначе вывести в строке состояния сообщение об ошибке
   SuspendThread(writer);
  }
}

В этой функции используеться функция
Код
WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr);  //записать байты в порт (перекрываемая операция!)

А в ней для определения длины посылки используеться функция strlen(bufwr). Заменил эту функцию явным количеством символов посылки, все заработало.
Genadi Zawidowski
Запретите формирование ошибки по приёму frame error. Иначе, пока не считаете состояние ошибок (сбравсываются они при этом) все операции ввода-вывода на ком-порте завершаются с ошибкой.

За образец пока не поздно предлагаю взять программу из аттачмента.

зы: только сейчас заметил что проблема не в передаче нуля как символа с нулём в стоп-бите... но в исходники копните.
Xenia
Всё гораздо проще. Стринги в языке C по определению заканчиваются нулем, который сам за символ не считается (нуль-терминированная строка). Отсюда следует очевидное следствие - строка символов не может содержать нуля, а буде такой в строку ставлен, то это привело бы лишь к тому, что строка стала бы короче, будучи обрезанной по первому же встреченному нулю.

То же касается функции strlen(), определяющей длину стринга. Она возвращает не число сиволов, которые вы туда понатыкали, а число ненулевых символов, начиная с нуля. Поэтому конструкция:
WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr);
так же оказывается завязана на функцию strlen(), поскольку именно она вычисляет число передаваемых байт. Отсюда и ваша ошибка.
Исправлять положение следует явным указанием числа передаваемых байт. Элегантным способом реализации которого может быть вариант создания специальной функции, помещающей байт в буфер, вместо механического копирования. Такая функция добавляла бы байт, одновременно инкрементируя счетчик. Этот же счетчик впоследствии использовался бы при сбросе буфера на вывод, после которого счетчик обнулялся.
Например так:

Код
// глобальные переменные:
char bufwr[1024];
int counter = 0;

void PushBuffer( char symbol)
{
  bufwr[counter++] = symbol;
}

При желании эту функцию можно объявить inline, тем самым превратив ее в прямую подстановку. А обнуление counter вставить в WriteThread() после успешного завершения передачи. А саму передачу производить так:
WriteFile(COMport, bufwr, counter, &temp, &overlappedwr);

Соответственно этому, пихать байты в буфер следует не так:
for(unsigned char icd=0;icd<10;icd++){bufwr[icd]=comand[icd];
а вот так:
for(unsigned char icd=0;icd<10;icd++) PushBuffer(comand[icd]);
AHTOXA
Цитата(Xenia @ Jul 13 2010, 03:27) *
конструкция:
WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr);
так же оказывается завязана на функцию strlen(), поскольку именно она вычисляет число передаваемых байт. Отсюда и ваша ошибка.

Эко вы всё здорово объяснили. Только вот кому? Автор темы в конце цитируемого вами сообщения пишет:
Цитата(kolisnichenko_r @ Jul 12 2010, 19:16) *
А в ней для определения длины посылки используеться функция strlen(bufwr). Заменил эту функцию явным количеством символов посылки, все заработало.

smile.gif
kolisnichenko_r
Че-то затормозил, жара достала.
Спасибо всем!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.