Перейти к содержанию
    

Как правильно объявить extern для typedef?

49 минут назад, MementoMori сказал:

Казалось бы, около 10 кбайт в секунду.

С чего бы такой странный вывод???  :fool:

Начинайте уже наконец-то думать!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подумал, разобрался, оптимизировал прием, все хорошо. До 10 пакетов в 200 байт туда и обратно за одну секунду.

Идем дальше, получаем проблемы с извлечением принятых данных.

 

tINFO_VAR ANSWER_INFO_VAR;
tINFO_VAR * pAnswerInfo;	 
pAnswerInfo=&ANSWER_INFO_VAR;
len_rx=0;
while(len_rx<sizeof(ANSWER_INFO_VAR)) // гоняем цикл пока не прочитаем всю структуру
		{
		   FData=Socket->ReceiveData(100); // получаем то, что есть в буфере на текухий момент.
			len_rx+=FData.Length;// увеличиваем счетчик прочитанных байт
			memcpy(pAnswerInfo,FData.data(),FData.Length); //копируем то, что есть, в ANSWER_INFO_WAR
		   pAnswerInfo+=FData.Length; //смещаем указатель на число прочитанных байт
		}

Указанный код запускается по таймеру раз в 50 мсек. При этом в начале кода таймер останавливается и вновь запускается в конце. То есть код запускается раз в 50 мсек, но выполняться может столько сколько нужно.

Принцип работы не мной написанной библиотеки таков - нельзя узнать сколько в буфере приема байт, нельзя просто дождаться, пока 200 байт накапает. Нужно читать  FData=Socket->ReceiveData(100). А когда данные прочел, содержимое буфера стирается.

То есть, повторюсь, нельзя дождаться всей посылки и прочесть ее разом. Читаем кусками и склеиваем. Получается 9-10 кусков, в зависимости от того, в какой момент приема сработает таймер

Так вот, первые 15-25 байт (видимо длина первой посылки) читаются нормально. В остальных нули. В процессе работы почти все эти байты заполняются верными данными. Но не все и не сразу. 

Где собака порылась?

 

Добавлено спустя 10 минут:

 

Собака порылась кажется здесь:

 pAnswerInfo+=FData.Length;

Эта команда дает прирост адреса указателя на 4000. Хотя должна приращивать на 15-25 байт

Вот строка для отладки Form1->Memo1->Lines->Add(IntToHex((__int32)pAnswerInfo)+" и "+IntToStr(FData.Length))+" байт");

Она выдает следующее

Quote

С0B73D6C и 20 байт

С0B74D0C и 20 байт

То есть "pAnswerInfo+20" это то же самое, что "адрес pAnswerInfo+4000"

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, MementoMori сказал:

pAnswerInfo+=FData.Length;

Эта команда дает прирост адреса указателя на 4000. Хотя должна приращивать на 15-25 байт

Может, все-таки, открыть учебник по Си?:bye: А то так не продвинуться дальше двух строчек кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, MementoMori сказал:

Хотя должна приращивать на 15-25 байт

Не должна.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/13/2023 at 5:17 PM, MementoMori said:

Собака порылась кажется здесь:

 pAnswerInfo+=FData.Length;

Эта команда дает прирост адреса указателя на 4000. Хотя должна приращивать на 15-25 байт

Изучайте арифметические операции с указателями

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, MementoMori said:
 FData=Socket->ReceiveData(100); // получаем то, что есть в буфере на текухий момент.
			len_rx+=FData.Length;// увеличиваем счетчик прочитанных байт
			memcpy(pAnswerInfo,FData.data(),FData.Length); //копируем то, что есть, в ANSWER_INFO_WAR
		   pAnswerInfo+=FData.Length; //смещаем указатель на число прочитанных байт

Коллега! Так нельзя. Нет, ну если очень хочется мордой в кучу дерьма, то пожалуйста.

ИМХО, использовать адресную арифметику со значениями, полученными через какую-то линию связи, категорически нельзя. Да ещё без единой проверки на то, что указатель ссылается на что-то осмысленное. Всё, что принято извне, содержит ошибки (пока неоднократно не доказано обратное), поэтому должно 100500 раз перепроверяться. Не согласны со мной и доверяете CSRC32? Вы обречены.

Посмотри на Модбас. Максимальная длина кадра ограничена. Поле, указывающее размер кадра, не_может превысить размер кадра в силу своей разрядности (256 байт и 8 бит). В кадре указаны параметры, которое однозначно связаны с параметрами запроса, а в конце ещё и CRC16. Предлагаю продумать протокол на предмет перекрёстных проверок правильности принятых данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 minutes ago, tonyk_av said:

Коллега!

Слишком лестно в мой адрес. Я любитель) В миру же я врач) А железки, байты, транзисторы - это моя вторая натура, ничего с этим не поделаешь)   И ведь как тяжело в возрасте после 40-ка вникать в то, что пропустил по молодости.  Всякому обучению свое время.

Стряхнул пыль с учебников по С++.  Блин, я наивно полагал, что если значение указателя это адрес, то и работать с ним можно как с адресом. А оказывается ptr++ увеличивает не на 1 байт, а на размер структуры, на которую ссылается указатель. Удивительное рядом.

В итоге работающее решение такое:

  
pAnswerInfo = (tINFO_VAR *)((char*)pAnswerInfo+FData.Length);

Я правильно понял суть проблемы и ее решения? Или это случай, когда неверными расчетами случайно пришел к правильному ответу?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/13/2023 at 8:16 PM, MementoMori said:

Я правильно понял суть проблемы и ее решения? Или это случай, когда неверными расчетами случайно пришел к правильному ответу?

Суть поняли правильно, но ваше решение какое-то не такое ))

Лучше так

tINFO_VAR ANSWER_INFO_VAR;
uint8_t* pAnswerInfo;	 
pAnswerInfo=(uint8_t*)&ANSWER_INFO_VAR;
len_rx=0;
while(len_rx<sizeof(ANSWER_INFO_VAR)) // гоняем цикл пока не прочитаем всю структуру
{
    FData=Socket->ReceiveData(100); // получаем то, что есть в буфере на текухий момент.
    len_rx+=FData.Length;// увеличиваем счетчик прочитанных байт
    memcpy(pAnswerInfo,FData.data(),FData.Length); //копируем то, что есть, в ANSWER_INFO_WAR
    pAnswerInfo+=FData.Length; //смещаем указатель на число прочитанных байт
}

Ваш же код, но изменены вторая и третья строчки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, MementoMori said:
			len_rx+=FData.Length;// увеличиваем счетчик прочитанных байт

А если при приёме склеится конец одного пакета и начало следующего? У вас излишек данных не переносится в следующий пакет, а просто затирает память за переменной ANSWER_INFO_VAR.

Так что вы потеряете кусок следующего пакета, после чего ВСЕ пакеты поедут со сбитыми границами (если конечно ваша программа не навернётся раньше из за испорченной памяти после ANSWER_INFO_VAR)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, xvr said:

А если при приёме склеится конец одного пакета и начало следующего?

А мое устройство молчаливо, говорит только тогда, когда его спрашивают, отвечает строго по уставу и затыкается, пока снова не спросят.

Но за замечание спасибо - надо будет перед отправкой запроса предварительно очистить буфер приема.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пробежался по теме. Что мешает реализовать Модбас? Ведь ТС пытается повторить, только по-своему, то же самое. Зачем?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...видимо, желание сделать собственный велосипэд 🙂 Ну чтож, это тоже похвально. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, EdgeAligned said:

 сделать собственный велосипэд 🙂 

Ну зачем ярлычки вешаете? Я тоже повешу свой ярлычок - MODBUS - это стрельба из пушки по воробью (коим является моя задача). 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

45 minutes ago, MementoMori said:

MODBUS - это стрельба из пушки по воробью

С чего бы это? В итоге всё равно получится что-то очень похожее на него. Для этой задачи достаточно реализовать команды записи-чтения регистров. Бонусом получится возможность протестировать написанное с помощью туевой хучи ОРС-серверов и утилит для тестов Модбаса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, tonyk_av said:

С чего бы это? В итоге всё равно получится что-то очень похожее на него. Для этой задачи достаточно реализовать команды записи-чтения регистров. Бонусом получится возможность протестировать написанное с помощью туевой хучи ОРС-серверов и утилит для тестов Модбаса

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

Осталось проработать обработку ошибок и автоматическое восстановление после разрыва связи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...