Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.79/14: Рейтинг темы: голосов - 14, средняя оценка - 4.79
0 / 0 / 3
Регистрация: 16.11.2009
Сообщений: 45

Перебор содержимого COM порта

26.01.2010, 17:13. Показов 2678. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ситуация такая.
Каждые пару миллисекунд на COM порт приходят команды вида "@03...\r","#01...\r","!01...\r". команд много и они разные.
Периодически, раз в 10 миллисекунд обращаюсь в COM порт за данными.
одной командой забираю содержимое порта. с этим проблем нет.
для проверки закидываю содержимое ком порта в поле мемо. Все отлично, приходит без ошибок, буфер ком порта не переполняется.
Почти всегда читаю с ком порта неполные команды, где начало в одной посылке (символы !03 или другие), а конец (\r) в следующей. когда команды сливаются в мемо, видно, что они правильные.

Логика такова - команда начинается после \r и заканчивается им же. (теряю самую первую посылку ну и хрен с ней)

Теперь вопрос. Какой придумать алгоритм, чтобы обрабатывая посылку с ком порта, при нахождении \r начинать запись в какую то переменную, а при следующем нахождении \r в следующей посылке или в нынешней передавать полученную команду далее(например разбирать команду побитово-это прога телемеханики), и одновременно начинать запись в эту же переменную новой команды.

Для тех, кто заинтересуется, пользуюсь ComPort Library version 3.10 для Билдера

Я не прошу код, прошу подсказать идею, всем отделом сегодня мучались, так и не придумали. Вот чувствую, что тут просто, но додуматься уже не могу.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.01.2010, 17:13
Ответы с готовыми решениями:

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

Перебор содержимого LIST<>: попарно сравнить все элементы листа исключая возможность повторения
Задача такова. В листе хранятся адреса файлов, есть отдельный метод сравнения этих файлов. Необходимо попарно сравнить все элементы листа...

Полный перебор и сокращенный перебор, путем исключения одного цикла
1) Разработать на основе метода полного перебора программу razmen1 для решения задачи о способах размена купюры достоинством 100 условных...

10
 Аватар для Зоти Сергей
230 / 227 / 65
Регистрация: 18.12.2009
Сообщений: 316
26.01.2010, 17:49
Ну.. можно сделать так:
В потоке, где вы читаете данные с ком порта:
Предположим, что ваша функция, которая читает данные с порта называется
int ReceiveData(char * InputBuffer)
Она заполняет InputBuffer данными из COm порта и возвращает число считанных эллементов.
тогда:


C++
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
        typedef vector<char> CCharVector;
        CCharVector VectorOfChar;  // вектор переменных типа char для обработки комманд
 
    char DatasFromComport[255];          // буфер, в который будут получаться данные с ком порта для 
 
        int ReceivedLength = ComPort->ReceiveData(DatasFromComport);  //Получили какие-то данные с порта и размер считанных данных записали в ReceiveLength.
 
        for(int i=0;i<ReceivedLength;i++)    //Проходимся по всем данным
        {
            if(DatasFromComport[i]=='\r')  //если вдруг нашли '/r' символ
                {
                    for(int j=i+1;j<ReceivedLength;j++)   //начиная, со следующего после него эллемента дальше перебирать массив
                        {
                            if(DatasFromComport[j]!='\r') //если следующий символ отличен от '\r', то добавляем его в список
                                {
                                    VectorOfChar.push_back(DatasFromComport[j]);                                    
                                }
                                else  //иначе дошли до следующего '\r'
                                {
                                        ProcessCommand(VectorOfChar); //делаем что-то с получившимся списком символов.                                        
                                    i=j;     //сбрасываем устанавливаем новый индекс для цикла "i" и возвращаемся к преведущему циклу 
                                        break;
                                    
                                }
                        }
                }
        }
а ProcessCommand может выглядить например вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
void ProcessCommand(CCharVector VectorToAnalyse)
{
          for(int i=0;i<(int)ProcessCommand.size();i++)       //проходимся по всем байтам, комманды, считанной с ком порта:
          {
                     char Letter=ProcessCommand[i];
                     if((Letter<<8)&0x01)// например проверить, установлен ли первый бит байта
                     {
 
                     }
          }
}
1
0 / 0 / 0
Регистрация: 25.01.2010
Сообщений: 7
26.01.2010, 18:07
Доброго времени суток!!!
Считывайте по одному биту из буфера КОМ порта. До первого приема "/r" все выкидываем (
Цитата Сообщение от wolf_soloist Посмотреть сообщение
теряю самую первую посылку ну и хрен с ней
). Приняли "/r", значит далее идет пакет (посылка), который нужно сохранять. Если длина пакета (посылки) всегда одинакова, то можно прием организовать через цикл. Если длина меняется, то отслеживаем по приему "/r".
0
 Аватар для Зоти Сергей
230 / 227 / 65
Регистрация: 18.12.2009
Сообщений: 316
26.01.2010, 18:40
Цитата Сообщение от goodvin26 Посмотреть сообщение
Доброго времени суток!!!
Считывайте по одному биту из буфера КОМ порта
это шутка?
Это сколько обращений к порту необходимо будет сделать, чтобы считать несколько килобайт?
И вообще не понятно, зачем. разве нельзя считать пару сотен байт, а потом их проанализировать, пробежав по массиву?
0
0 / 0 / 3
Регистрация: 16.11.2009
Сообщений: 45
27.01.2010, 15:39  [ТС]
Зоти Сергей, на попытку засунуть код в прогу, компилятор ругается с ошибками:
typedef vector<char> CCharVector; - [C++ Error] Unit1.cpp(14): E2257 , expected
CCharVector VectorOfChar; - [C++ Error] Unit1.cpp(15): E2141 Declaration syntax error

а за идею спасибки!!

typedef vector<char> CCharVector;
CCharVector VectorOfChar;
А что это? в первый раз с этим встречаюсь
0
 Аватар для Зоти Сергей
230 / 227 / 65
Регистрация: 18.12.2009
Сообщений: 316
27.01.2010, 15:56
добавьте #include<vector.h>

Добавлено через 1 минуту
и сразу за этим напишите:
typedef vector<char> CCharVector;

а уже остальное в вашей функции чтения с ком порта...
типа

C++
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
void ReadDataFromComPort()
{
        CCharVector VectorOfChar;  // вектор переменных типа char для обработки комманд
 
        char DatasFromComport[255];          // буфер, в который будут получаться данные с ком порта для 
 
        int ReceivedLength = ComPort->ReceiveData(DatasFromComport);  //Получили какие-то данные с порта и размер считанных данных записали в ReceiveLength.
 
        for(int i=0;i<ReceivedLength;i++)    //Проходимся по всем данным
        {
                if(DatasFromComport[i]=='\r')  //если вдруг нашли '/r' символ
                {
                        for(int j=i+1;j<ReceivedLength;j++)   //начиная, со следующего после него эллемента дальше перебирать массив
                        {
                                if(DatasFromComport[j]!='\r') //если следующий символ отличен от '\r', то добавляем его в список
                                {
                                        VectorOfChar.push_back(DatasFromComport[j]);                                    
                                }
                                else  //иначе дошли до следующего '\r'
                                {
                                        ProcessCommand(VectorOfChar); //делаем что-то с получившимся списком символов.                                        
                                        i=j;     //сбрасываем устанавливаем новый индекс для цикла "i" и возвращаемся к преведущему циклу 
                                        break;
                                        
                                }
                        }
                }
        }
}
Добавлено через 8 минут
А не счет
typedef vector<char> CCharVector;

Мы ведь не знаем, сколько комманд получим с ком порта, по этому создавать фиксированный массив
для хранения данных типа BYTE было бы не удобно.

С помощью vector<char>
вы содаете "список" переменных типа char (по сути это тоже самое. просто работать удобней)
Чтобы добавить новый символ используется ф-ция push_back.
Чтобы получить актуальный размер списка, просто опрашиваете функцией size().
Например:

C++
1
2
3
4
5
6
7
8
vector<char>MyList;
char a='A';
char b='B';
char c='C';
MyList.push_back(a); //добавим элемент.
MyList.push_back(b);
MyList.push_back(c);
int SizeofArray=(int)MyList.size();
SizeofArray равен 3
0
0 / 0 / 3
Регистрация: 16.11.2009
Сообщений: 45
27.01.2010, 16:07  [ТС]
Тогда следующий вопрос. как мне извлечь из вектора команд сами команды типа char?

Заранее простите за глупые вопросы, не изучал эту тему, а решение нужно найти быстро.
0
 Аватар для Зоти Сергей
230 / 227 / 65
Регистрация: 18.12.2009
Сообщений: 316
27.01.2010, 16:49
например так:

Edit1->Text=(char*)&VectorOfChar[0];
или
Memo1->Lines->Add((char*)&VectorOfChar[0]);

Тоесть, где я написал "ProcessCommand(VectorOfChar);",
в этом месте VectorOfChar состоит из готовой команды.
и если вы там напишите
Memo1->Lines->Add((char*)&VectorOfChar[0]);
то пришедшие команды будут добавляться в Memo1
0
0 / 0 / 3
Регистрация: 16.11.2009
Сообщений: 45
27.01.2010, 19:28  [ТС]
Очистил вектор командой .Clear();

посмотрел на ситуацию... Зоти Сергей, вы молодец, очень интересный способ, он почти работает, только есть одно но.
по работе программы я понял, что получается не совсем то. В вашем методе при обработке КАЖДОЙ посылки с ком порта теряется самая первая команда.
а я задумывал, что самая первая команда в самой первой посылке от ком порта теряется, а остальные, если не влезли в буфер команды запроса данных, обработаются в остальных посылках...
Например.
прислалось @0432234\r@0432234\r@0432234\r@0432234\r @0432234\r@043 - тут не влез в буфер, остался в ком порте...
2234\r@0432234\r@0432234\r@0432234\r- следующая посылка с ком порта,и тут остаток предыдущей команды. В идеале, я теряю самый первый @0432234\r в первой посылке. остальные я должен обрабатывать.
согласно алгоритма, из первой посылки я извлекаю 4 команды (самая первая теряется), а во второй посылке извлекается 4 команды (остаток "2234\r" я не должен потерять)

а в вашем алгоритме, к сожалению, такого нет.
0
 Аватар для Зоти Сергей
230 / 227 / 65
Регистрация: 18.12.2009
Сообщений: 316
27.01.2010, 23:28
А ёё... да. согласен. Просто писать вслепую.. По этому не учел.
В данном случае тогда вообще просто:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef vector<char> CCharVector;
CCharVector VectorOfChar;                              //VectorOfChar обязательно объявите глобально (не в функции).
void ReadDataFromComPort()
{
        char DatasFromComport[255];
        int ReceivedLength = ComPort->ReceiveData(&DatasFromComport[0]);
 
        if(!ReceivedLength)
            return;
        for(int i=0;i<ReceivedLength;i++)
        {
            if(DatasFromComport[i]!='\r')
                VectorOfChar.push_back(DatasFromComport[i]);
                else
                {
                    VectorOfChar.push_back('\0');                 //нулевой символ впрошлый раз забыл добавить
                    ProcessCommand(VectorOfChar);
                        VectorOfChar.clear();
                }
 
        }
}
0
0 / 0 / 3
Регистрация: 16.11.2009
Сообщений: 45
01.02.2010, 10:06  [ТС]
Большое спасибо за ответы. Метод действует великолепно. Приведу окончательный код, т.к. в предыдущих были мелкие ошибки.
написал 2 метода, один помельче, другой покрупнее.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
AnsiString Str; // посылка чтения КОМ порта
char Komanda[255];
 
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
ComPort1->Open();
int ReceivedLength = ComPort1->ReadStr(Str,2048);
Memo2->Text= Memo2->Text + Str;//контейнер чисто для удобства
if(!ReceivedLength) // проверочка на пустую посылочку
   return;
for(int i=1;i<=ReceivedLength;i++) //Проходимся по всем данным
 {
  if(Str[i]!='\r')  //если вдруг не нашли '/r' символ
    Memo1->Text= Memo1->Text + Str[i]; // засовываем в контейнер для отбора команд))
  else
   {
    ListBox1->Items->Add(Memo1->Text);
    Memo1->Clear();                
   }
 }
 
}
Добавлено через 3 минуты
второй способ

C++
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
#include<vector.h>
typedef vector<char> CCharVector;
 
AnsiString Str; // посылка чтения КОМ порта
CCharVector VectorOfChar;  // вектор переменных типа char для обработки комманд
char Komanda[255];
 
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
ComPort1->Open();
int ReceivedLength = ComPort1->ReadStr(Str,2048);
ListBox2->Items->Add(Str);
 
if(!ReceivedLength)
   return;
for(int i=1;i<=ReceivedLength;i++) //Проходимся по всем данным
 {
  if(Str[i]!='\r')  //если вдруг не нашли '/r' символ
    VectorOfChar.push_back(Str[i]);
  else
   {
    VectorOfChar.push_back('\0');                 
    for(int i=0;i<(int)VectorOfChar.size();i++)//проходимся по всем байтам, комманды, считанной с ком порта:
     {
      if(VectorOfChar[i]!='\0') Memo1->Text= Memo1->Text + VectorOfChar[i];
      else
       {
        ListBox1->Items->Add(Memo1->Text);
        Memo1->Clear();
       }
      }
    ListBox2->Items->Add(Str);
    VectorOfChar.clear();
   }
 }
Собственно, два способо почти идентичны, а такой вопрос, чем мне грозит использование в качестве контейнера класс Tmemo Builder`а?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
01.02.2010, 10:06
Помогаю со студенческими работами здесь

Чтение из COM порта, При чтении из порта зависает read()
Каждому рано или поздно приходится программировать com порт. Вот и мой черед пришол. Я ужу умею: Откривать,закривать, писать. а читать не...

Перемещение содержимого ячейки Б в ячейку А при удалении содержимого в ячейке А
Суть проблемы следующая. Имеется диапазон ячеек с текстом в каждой. При выделении любой из ячеек и удалении содержимого в ней, содержимое...

Вывод содержимого папки(такой то) и содержимого дисков
задание выглядит так &quot;Выведите на окно консоли содержимое дисков, а также папки «Мои документы» с информацией о размере имеющихся в ней...

Отправка содержимого поля в файл при нажатии кнопки без потери этого содержимого с поля
Привет всем!) Я отправляю содержимое textarea в файл при нажатии кнопки, после нажатия на кнопку содержимое стирается с этого поля. Как...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru