Форум программистов, компьютерный форум, киберфорум
Delphi
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
1

Прием данных через COM: появляются лишние символы на приеме

26.11.2015, 15:19. Просмотров 1319. Ответов 15
Метки нет (Все метки)

Добрый день!
Имеется устройство (Arduino), которое раз в секунду пишет в порт целое число в виде ASCII строки (в конце символы конца строки и переноса). Через SerialMonitor (входи в комплект разработки Arduno) просматриваю полученные данные - все приходит нормально.
Далее я написал программу на Delphi (XE5), которая просто читает приходящие данные из соответствующего COM. Но тут возникает проблема. Данные считываются в массив символов раз в секунду но в буфер залетают символы конца строки и переноса. Например передается '123456' вместо ['1','2','3','4','5','6'] я могу получить в буфере ['1',#$D,#$A,'2','3','4','5','6'] или ['1','2','3','4',#$D,#$A,'5','6']. Порт открываю так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
procedure TForm1.ComOpen(PortName:String; PortSpeed:Integer);
var DCB:TDCB;
    TimeOuts:TCommTimeOuts;
begin
   ComPort:=CreateFile(PChar(PortName),               //имя порта
                       GENERIC_READ or GENERIC_WRITE, //доступ к порту на чтение/записть
                       0,                             //порт не может быть общедоступным (shared)
                       nil,                           //дескриптор порта не наследуется, используется дескриптор безопасности по умолчанию
                       OPEN_EXISTING,                 //порт должен открываться как уже существующий файл
                       FILE_FLAG_OVERLAPPED,          //этот флаг указывает на использование асинхронных операций
                       0);                            //указатель на файл шаблона не используется при работе с портами
   if ComPort = INVALID_HANDLE_VALUE then
   begin
      Application.MessageBox('Не удалось открыть порт.','Ошибка',MB_OK or MB_ICONERROR);
      Exit;
   end;
 
   DCB.DCBlength:=SizeOf(DCB);
   if not GetCommState(ComPort,DCB) then
   begin
      Application.MessageBox('Не удалось считать DCB.','Ошибка',MB_OK or MB_ICONERROR);
      Exit;
   end;
 
   DCB.BaudRate:=PortSpeed;
   DCB.Flags:=DCBFlagsUnit.SetDCBFlags([dcbBinary]);
   DCB.ByteSize:=8;                                //задаём 8 бит в байте
   DCB.Parity:=0;                                  //отключаем проверку чётности
   DCB.StopBits:=0;                                //задаём один стоп-бит
 
 
   if not SetCommState(ComPort,DCB) then
   begin
      Application.MessageBox('Не удалось задать параметры DCB.','Ошибка',MB_OK or MB_ICONERROR);
      ComClose();
      Exit;
   end;
 
   TimeOuts.ReadIntervalTimeout := 0;           //таймаут между двумя символами
   TimeOuts.ReadTotalTimeoutMultiplier := 0;    //общий таймаут операции чтения
   TimeOuts.ReadTotalTimeoutConstant := 0;    //константа для общего таймаута операции чтения
   TimeOuts.WriteTotalTimeoutMultiplier := 0; //общий таймаут операции записи
   TimeOuts.WriteTotalTimeoutConstant := 0;   //константа для общего таймаута операции записи
 
   if not SetCommTimeouts(ComPort, TimeOuts)  then
   begin
      Application.MessageBox('Не удалось задать таймауты.','Ошибка',MB_OK or MB_ICONERROR);
      ComClose();
      Exit;
   end;
 
   SetUpComm(ComPort,2000,2000);
 
   PurgeComm(ComPort, PURGE_RXCLEAR);
 
   ReadThread:=TReadThread.Create(False, @ComPort);
   ReadThread.FreeOnTerminate:=True;
end;
Поток чтения данных организован так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
unit ReadThreadUnit;
 
interface
 
uses
  Classes, Windows;
 
type
  TReadThread = class(TThread)
  private
    { Private declarations }
    OverlappedRD:TOverlapped;
    PComPort:PHandle;
  protected
    procedure Execute; override;
  public
    procedure Printing();
    constructor Create(CreateSuspended: Boolean; APComPort:PHandle);
  end;
 
var RDBuffer:array [0..255] of AnsiChar;
 
implementation
 
{ TReadThread }
 
constructor TReadThread.Create(CreateSuspended: Boolean; APComPort: PHandle);
begin
   inherited Create(CreateSuspended);
   PComPort:=APComPort;
end;
 
procedure TReadThread.Execute;
var ComStat: TComstat;
    Mask, Signal, Temp:DWORD;
begin
   OverlappedRD.hEvent:=CreateEvent(nil,True,True,nil);
   SetCommMask(PComPort^,EV_RXCHAR);
   while not Terminated do
   begin
      WaitCommEvent(PComPort^,Mask,@OverlappedRD);
      Signal:=WaitForSingleObject(OverlappedRD.hEvent, INFINITE);
      if Signal = WAIT_OBJECT_0 then
      begin
         if GetOverlappedResult(PComPort^,OverlappedRD,Temp,True) then
         begin
            if (Mask and EV_RXCHAR) <> 0 then
            begin
               ClearCommError(PComPort^,Temp,@ComStat);
               if ComStat.cbInQue <> 0 then
               begin
                  ReadFile(PComPort^,RDBuffer,ComStat.cbInQue,Temp,@OverlappedRD);
                  Synchronize(Printing);
               end;
            end;
         end;
      end;
   end;
   CloseHandle(OverlappedRD.hEvent);
end;
 
procedure TReadThread.Printing();
var S:String;
begin
   S:=RDBuffer;
   FillChar(RDBuffer,SizeOf(RDBuffer),0);
end;
 
end.
В чем моя ошибка? Откуда могут взяться эти символы?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.11.2015, 15:19
Ответы с готовыми решениями:

Появляются лишние символы после генерации таблицы
Добрый день! JS изучаю совсем недавно и при выполнении одного из заданий по созданию таблицы...

При выводе на экран появляются лишние символы
#include &lt;iostream&gt; // ??? printf #include &lt;string.h&gt; // ??? strtok bool IsPalindrom (char...

Появляются лишние символы при считывании текстового файла
Добрый день. Необходима помощь, имеется текстовый файл, в котором содержится информация о том или...

Ошибка считывания строки из StringGrid, появляются лишние символы
Вся суть проблемы вот в чём.... Я считываю строку из таблицы(StringGrid). Пробовал вначале как...

15
2645 / 2268 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
26.11.2015, 15:31 2
А есть ли вменяемый аргумент в пользу того что массив RDBuffer является глобальной переменной, а не полем объекта TReadThread ?
0
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
26.11.2015, 15:33  [ТС] 3
mss, вменяемого нет Но это не объясняет того, почему символы переноса и конца строки залетают в середину строки, а не находятся в ее конце.
0
2645 / 2268 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
26.11.2015, 15:40 4
Нет, сначала дай вменяемое либо убирай буфер внутрь объекта
0
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
26.11.2015, 15:43  [ТС] 5
mss, а в чем будет разница? Понять не могу. Это может влиять?
0
2645 / 2268 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
26.11.2015, 15:55 6
А я вот тоже понять не могу - вот нахрена делать буфер глобальным, если к нему нет обращений со стороны более чем одной нити)

А если есть, то при этом любые "чудеса" могут происходить.
1
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
26.11.2015, 16:01  [ТС] 7
Больше обращений к этому буферу нигде нет 100%. Сначала была мысль, сделать буфер глобальным, но потом от нее отказался за ненадобностью (Printing()). Попробую перенести внутрь объекта. Посмотрим, что получится. Позже отпишусь.
0
пофигист широкого профиля
4210 / 2743 / 780
Регистрация: 15.07.2013
Сообщений: 15,939
26.11.2015, 16:09 8
Я лично из приведенного кода не понимаю как и где смотрится то что принято?
0
2645 / 2268 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
26.11.2015, 16:18 9
почему буфер на 256 байт, а читаешь в него при этом ComStat.cbInQue байт ?

Надо понимать, что тебе твое буратино-тарантино поклялось не слать за раз больше 256 байт ?)

И кто там на стороне бабуино посылает строки - твоя программулина ?
Если твоя, то с чего ты так уверен что она у тебя непогрешима и не может втыкать где ни попадя всякую хрень ?)

Добавлено через 9 минут
northener, ну он типо в отладжчике тормознул где-то, навел мыша на переменную-буфер и увидел там хрень).. которую, что-то мне сдается, он сам же и послал
0
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
26.11.2015, 16:20  [ТС] 10
Пока на плате только одна простенькая программа: шлет кол-во миллисекунд с момента подачи питания. Больше двух минут я ее не гоняю, поэтому такого буфера вполне достаточно. Размер буфера это другой вопрос. Я пока разбираюсь со всем этим. Вопрос у меня был в другом. Какого лешего '#$D#$A' торчат в середине буфера, хотя должны лежать в конце?
0
2645 / 2268 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
26.11.2015, 16:25 11
Цитата Сообщение от Vabos Посмотреть сообщение
на плате только одна простенькая программа
Ну так покажи нам ее исходник с твоими комментариями ..
0
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
26.11.2015, 16:29  [ТС] 12
Посылка идет вида строкой ASCII: '12345'+'\r'+'\n'. К тому же в SerialMonitor находится то, что и должно быть. Я в отладчике вижу и в Memo вывожу. Данные правильные, но вот служебные символы не в тему вааще!

Добавлено через 2 минуты
Вот код на ардуине:
C++
1
2
3
4
5
6
7
8
9
10
void setup()
    {        
        Serial.begin(9600);//скорость общения с портом
    }
     
    void loop()
    {
        Serial.println(millis()); // Отправляем время с момента включения
        delay(1000);// Делаем паузу
    }
0
2645 / 2268 / 278
Регистрация: 24.12.2010
Сообщений: 13,725
26.11.2015, 19:35 13
millis() - это что ?
0
пофигист широкого профиля
4210 / 2743 / 780
Регистрация: 15.07.2013
Сообщений: 15,939
27.11.2015, 02:36 14
Цитата Сообщение от Vabos Посмотреть сообщение
Я в отладчике вижу и в Memo вывожу.
В отладчике смотреть результаты асинхронных операций бессмысленно. Точнее - глупо по многим причинам. Вывод в мемо лучше бы помог. Но как ты выводишь в мемо - неизвестно.
0
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
27.11.2015, 13:15  [ТС] 15
Цитата Сообщение от mss Посмотреть сообщение
millis() - это что ?
Возвращает кол-во миллисекунд с момента подачи питания. millis(), Serial.println() - пишет в порт данные в виде ASCII строки, в конце добавляет символы переноса и конца строки. println()
В отладчике смотреть результаты асинхронных операций бессмысленно.
Смотрю в процедуре TReadThread.Printing(), там где S:=RDBuffer; Потом добавил Memo.Lines.Add(S); В общем, что в буфере, то и в Memo и в строке. Полученная строка разделяется спец символами. Может что-то с настройками порта не то? ХЗ короче. Буду разбираться. northener, mss спасибо!
0
132 / 129 / 31
Регистрация: 12.12.2011
Сообщений: 456
04.12.2015, 14:50  [ТС] 16
Разобрался. Ошибка была здесь:
Delphi
1
2
3
...
if ComStat.cbInQue <> 0 then
...
Нужно было дожидаться приема всех символов, а не читать сразу буфер.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.12.2015, 14:50

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

Ошибка при приеме данных через COM (Arduino-Xbee-PC)
Добрый день! Передаю данные с ардуины (Mega2560) через Xbee (EndDevice) на компьютер. К компу...

Прерывание таймером при приёме и передаче данных через UART
Разрабатываю программу для RS485 на базе контроллера STM32F100xx. Ступор настал когда нужно входные...

Обновление элемента label при приёме данных через serialport
Доброго времени суток! На форме имеются компоненты label и serialport. Через ком порт на комп...

Лишние символы при выводе текста, полученного передачей через сокеты
Здравствуйте. Совсем недавно начал изучать программирование сокетов на С++. Проблема заключается в...

Добавляются лишние символы при выводе данных в поток
Есть char buff; куда пишутся данные с сети. вывожу на печать: cout &lt;&lt;&quot;IMEI- &quot; &lt;&lt; &quot;--&quot; &lt;&lt;...

Лишние символы при выводе значений из базы данных (postgresql)
Возникла такая проблема: при выводе значений таблицы из БД на html страницу значения &quot;обрамляются&quot;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.