![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
MementoMori
-
Постов
1 340 -
Зарегистрирован
-
Посещение
Сообщения, опубликованные MementoMori
-
-
2 hours ago, EdgeAligned said:
сделать собственный велосипэд 🙂
Ну зачем ярлычки вешаете? Я тоже повешу свой ярлычок - MODBUS - это стрельба из пушки по воробью (коим является моя задача).
-
2 hours ago, xvr said:
А если при приёме склеится конец одного пакета и начало следующего?
А мое устройство молчаливо, говорит только тогда, когда его спрашивают, отвечает строго по уставу и затыкается, пока снова не спросят.
Но за замечание спасибо - надо будет перед отправкой запроса предварительно очистить буфер приема.
-
13 minutes ago, tonyk_av said:
Коллега!
Слишком лестно в мой адрес. Я любитель) В миру же я врач) А железки, байты, транзисторы - это моя вторая натура, ничего с этим не поделаешь) И ведь как тяжело в возрасте после 40-ка вникать в то, что пропустил по молодости. Всякому обучению свое время.
Стряхнул пыль с учебников по С++. Блин, я наивно полагал, что если значение указателя это адрес, то и работать с ним можно как с адресом. А оказывается ptr++ увеличивает не на 1 байт, а на размер структуры, на которую ссылается указатель. Удивительное рядом.
В итоге работающее решение такое:
pAnswerInfo = (tINFO_VAR *)((char*)pAnswerInfo+FData.Length);
Я правильно понял суть проблемы и ее решения? Или это случай, когда неверными расчетами случайно пришел к правильному ответу?
-
Подумал, разобрался, оптимизировал прием, все хорошо. До 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"
-
2 hours ago, TOG said:
У меня тоже была шляпа с HM-13. В нашем модуле с завода был не правильно установлен класс устройства(0xD0, 0xD0, 0xD0), а должен быть 0x00, 0x1F, 0x00. Дал команду на смену класса: "AT+COFD001F00" и все стало хорошо.
(вот нормальный полный даташит):
Скажите а софт для работы на чем писали? Я имею в виду не для модуля HM-13, а для приложения на телефоне? Мне бы проконсультироваться и на этот счет.
-
Потихоньку ковыряю дальше.
Выровнял структуру, из 224 байт сэкономил 24. Теперь структура весит 200 байт.
Решил поиграть в "эхо" - передаю данные и принимаю их же обратно. Передаю на скорости 115200 бод. Казалось бы, около 10 кбайт в секунду.
Цикл следующий - отправка 200 байт с телефона -> прием блютузом -> передача на контроллер -> передача из контроллера в блютуз -> прием в телефоне.
Процесс занимает около 1 секунды.
Так и должно быть? В скорости передачи собственно байт сомневаться не приходится. Так может быть начало и конец приема и передачи накладывают какие-то задержки?
В контроллере модуль HM-13, если что.
-
9 hours ago, khach said:
прилетело по машинке коллеге вчерась.
На кошерных шлагбаумах демпфер внизу стоит. Понятно, что он не защищает полностью, но все же.
-
13 minutes ago, Сергей Борщ said:
Вы что-то где-то списали неправильно.
Вы правы, был невнимателен, не везде удалил указатели. Поправил - все работает, без new. У меня размер буфера маленький (я сейчас набросал в максимально близком к конечному виде, получилось 224), разницы, естественно, незаметно, но, верю вам, что так лучше.
-
4 minutes ago, Сергей Борщ said:
Нам предлагается угадать, как именно он ругается?
Матом ругается. По-русски причем.
А если серьезно, я, опять таки, писал об этом ранее.
[bccaarm Error] Unit1.cpp(253): no viable conversion from 'TArray__1<System::Byte> *' (aka 'System::DynamicArray<unsigned char> *') to 'System::TArray__1<System::Byte>' (aka 'System::DynamicArray<unsigned char>')
-
30 minutes ago, dimka76 said:
Пока ТС не признается, гадать можно долго )))
Блин, да в C++ Builder я программирую. И в библиотеках для написания программ под Андроид дух Явы таки имеет место быть, ибо в созданном проекте есть такая строка #include <AndroidApi.JNI.JavaTypes.hpp>
-
1
-
-
12 minutes ago, Сергей Борщ said:
удет работать ничуть не хуже, но будет короче и быстрее.
Возможно после компиляции он и мог бы работать быстрее. Но компилятор протестует. Г
14 minutes ago, Сергей Борщ said:Неужели в Java все-все переменные должны объявляться через new?
В примере кода для bluetooth от разработчика очень много чего объявляется через new
-
1 hour ago, Сергей Борщ said:
Зачем вы создаете объект в динамической памяти через new?
Я писал выше:
QuoteСразу скажу тем, кто будет предлагать альтернативу - буфер должен быть объявлен так и только так, этого требует библиотека под Андроид, работающая с Bluetooth.
1 hour ago, Сергей Борщ said:А теперь читайте по губам
Опять же, выше я уже написал, что понял это и исправил, все работает.
3 hours ago, jcxz said:Не читали в учебнике по языку си о структурах и выравнивание их членов.
Знаю я про упаковку, я не знаю пока какой окончательный вид будет иметь структура. А узнаю я это в процессе разработки, в процессе испытания устройства, а для этого нужно погонять данные. А это тоже нужно организовать, лоск наведу потом.
-
27 minutes ago, dimka76 said:
А если у вас принимающая и передающая платформы будут иметь разную разрядность ? И не только.
Делается под конкретную платформу. Для себя, если быть точным.
Но намек ясен, будут предложения по унификации, с целью платформонезависимости? Где у меня слабое место?
-
21 minutes ago, Сергей Борщ said:
По вашим примерам видно, что этот класс переопределяет operator[]. Можно, конечно, воспользоваться им, но есть подозрение, что этот класс предоставляет какой-то более удобный в данном случае способ доступа к буферу.
ВОТ ОНО!!!!!!
Вот те самые золотые слова, которые толкнули меня в правильном направлении!!!
Есть у TArray__1<System::Byte> операция, которая превращает этот массив в массив unsigned char !
Вот как надо было обращаться к массиву: buffer->data()
memcpy(buffer->data(),pInfo,sizeof(INFO_VAR));
Итак, передача:
typedef struct { unsigned int TimePosition; unsigned char WORK_STATE; unsigned char POWER_REGULATION_MODE; }tINFO_VAR; tINFO_VAR INFO_VAR; .................................. INFO_VAR.TimePosition=0xCCDD; INFO_VAR.POWER_REGULATION_MODE=0xAA; INFO_VAR.WORK_STATE=0xBB; tINFO_VAR * pInfo; pInfo=&INFO_VAR; ................... TArray__1<System::Byte> * buffer = new TArray__1<System::Byte>; buffer->set_length(sizeof(INFO_VAR)); memcpy(buffer->data(),pInfo,sizeof(INFO_VAR)); Socket->SendData(*buffer); delete buffer;
прием
tINFO_VAR * pInfo; ..... pInfo=&INFO_VAR; usart_buf[usart_bit++] = received_byte; // прием последнего байта memcpy(pInfo,usart_buf,sizeof(INFO_VAR));
-
7 minutes ago, Сергей Борщ said:
1) получить указатель на буфер (именно на буфер, а не на ваш объект каласса TArray1<System::Byte>)
2a) memcpy()
2b) явно привести этот указатель на буфер к типу "указатель на tINFO_VAR" и присвоить структуру по приведенному указателю.
Ну дык вот, делал уже
tINFO_VAR INFO_VAR; tINFO_VAR * pInfo; pInfo=&INFO_VAR; TArray__1<System::Byte> * buffer = new TArray__1<System::Byte>; buffer->set_length(8); memcpy(buffer,pInfo,sizeof(INFO_VAR);
Не ругается при компиляции, но ловит какую-то ошибку при работе приложения во время memcpy
-
14 minutes ago, artemkad said:
в текст вида
Да зачем в текст?
Я ж писал выше:
TArray__1<System::Byte> * buffer = new TArray__1<System::Byte>; buffer->set_length(6); (*buffer)[0] = INFO_VAR.POWER_REGULATION_MODE; (*buffer)[1] = INFO_VAR.WORK_STATE; (*buffer)[2] = INFO_VAR.TimePosition & 0xFF; (*buffer)[3] = INFO_VAR.TimePosition >> 8; (*buffer)[4] = 0xEE; (*buffer)[5] = 0x0D; Socket->SendData(*buffer); delete buffer;
Буфер с байтами передается без проблем, преобразование в текст не требуется. Разбирать и собирать можно байты.
Я бы уже давно всю структуру (она у меня сложнее, тут я сократил ее с целью облегчения восприятия) таким же образом заполнил, но я хочу понять, как это делается проще, через указатели.
-
Ну может вы прекратите уже спорить? Я тему создал не для выяснения отношений.
-
1 hour ago, xvr said:
В частности её не поплохеет если вместо текстовой строки от вашего BT приедет 'нечто' (совсем бинарное и на текст не похожее) ?
Вот:
(*buffer)[0] = 0xAA; (*buffer)[1] = 0xBB; (*buffer)[2] = 0xCC; (*buffer)[3] = 0xDD; (*buffer)[4] = 0xEE; (*buffer)[5] = 0x0D;
И программа это проглотила, и железо передало, а другое железо приняло.
Может все таки на вопрос ответите?
typedef union { struct data { unsigned int TimePosition; unsigned char WORK_STATE; unsigned char POWER_REGULATION_MODE; }; unsigned char buffer[sizeof(struct data)]; }tINFO_VAR;
Хорошо, сделал я так, потом объявил переменную
И как тогда обращаться к TimePosition?
И как это копировать в buffer, который объявлен в TArray__1<System::Byte> * buffer = new TArray__1<System::Byte>; ?
-
35 minutes ago, xvr said:
приедет 'нечто' (совсем бинарное и на текст не похожее)
Как на Ваш взгляд, байт - это бинарное, на текст не похожее?
-
Новый вопрос.
Есть буфер, объявленный следующим образом
TArray__1<System::Byte> * buffer = new TArray__1<System::Byte>;
Сразу скажу тем, кто будет предлагать альтернативу - буфер должен быть объявлен так и только так, этого требует библиотека под Андроид, работающая с Bluetooth.
Заполнил буфер классически, для эксперимента
buffer->set_length(6); (*buffer)[0] = 'r'; (*buffer)[1] = 'e'; (*buffer)[2] = 's'; (*buffer)[3] = 'e'; (*buffer)[4] = 't'; (*buffer)[5] = 0x0D;
Работает, ура, микроконтроллер принимает строку "reset"
Но, идем дальше, вот структура
typedef struct { unsigned int TimePosition; unsigned char WORK_STATE; unsigned char POWER_REGULATION_MODE; } tINFO_VAR; tINFO_VAR INFO_VAR;
Как ее скопировать в buffer? Выделить из структуры каждую переменную, разобрать на байты и записать побайтово буфер я могу, но хочется поизящнее.
Если пробовать в лоб - buffer=&INFO_VAR -ругается на несоответствие типов.
-
Друзья, есть у меня модуль HM-13 , в нем 2 блютусины сразу, одна обычная, другая BLE
С обычной сопряжение (штатными средствами телефона) происходит без проблем, спрашивается PIN, вводится и устройство сопряжено).
А вот при обнаружении устройства BLE телефон мне предлагает "Перейдите в приложение с этого устройства, чтобы сопрячь с ним). А "это устройство" - напомню, это модуль, ни с каким приложением он не работает.
Может есть какие команды настройки, позволяющие автоматически сопрягать? Чтение даташита https://files.seeedstudio.com/wiki/Grove-BLE-dual_model-v1.0/res/Bluetooth_HM-13_en.pdf ничего не дало.
-
3 minutes ago, EdgeAligned said:
Обычно для разделения пакетов существует пауза в передаче длиной более одного байта - Break frame. Эта пауза даже аппаратно может быть распознана приемником по состоянию Idle line и будет служить признаком начала и конца передечию
Получилось:
if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET ) //Judging whether it is idle interruption { __HAL_UART_CLEAR_IDLEFLAG(&huart2); //Clear idle interrupt sign (otherwise it will continue to enter interrupt) }
-
Друзья, ваш спор перешел в разряд "с какого конца разбивать яйцо, с острого или тупого". Я решение выбрал, призываю вас не спорить.
У меня следующий вопрос.
А как бы мне передать структуру по UART? Точнее, как передать, я представляю, беру указатель и по указателю передаю количество байт равное размеру структуры.
Что-то вроде этого:
void USART_Transmit_block( void *ptr, size_t size) { uint8_t *p = (uint8_t*)ptr; while(size--) USART_Transmit( *p++); } ... USART_Transmit_block((unsigned char*) &TX_Data, sizeof(TX_Data) );
А вот как быть с приемом?
Там ведь как - если приходит 0x00, то это считается концом строки. А если в структуре есть байт 0x00? Как быть? Как синхронизировать начало посылки?
У меня есть самопальный рабочий пример с передачей текстовых команд - в буфер принимаются байты, пока один из них не равен 0x0D. Как только этот байт ловится, читается все что принято после предыдущего байта 0x0D и это считается текстовой командой.
Там сложностей не возникало. А вот со структурами как быть? Там ведь уже не используешь символы конца строки, ибо символы с этим кодом могут быть в структуре.
-
2 hours ago, EdgeAligned said:
Положите этот typedef в файл заголовочника и подключите его (файл) к файлу исходника и к остальным файлам, куда его надо подключать.
Уже так и сделал.
Как это обычно бывает - долго бьешься над проблемой, но как только задашь вопрос на форуме, еще до того как кто-то ответит, решение приходит само собой.
2 hours ago, EdgeAligned said:Ну и освойте написание многофайловых проектов, чтобы не валить всё в один main.c.
Так у меня эта переменная только в main.c и stm32f1xx_it.c используется. Проектик маленький, из-за 3-х функций еще какой-то файл создавать я не стал. А вообще так и делаю - отделяю функционал от распределения.
Как правильно объявить extern для typedef?
в В помощь начинающему
Опубликовано · Пожаловаться
Не хочу с вами спорить, но мне, с учетом моей задачи, с учетом того, что я все же любитель и некоторые вещи мне нужно, не поверите, осваивать с нуля, с учетом того, что к маю мне бы эту поделку хотелось бы уже эксплуатировать, мне проще сделать следующим образом - взять мой же старый, доказавший свою надежность, проект, в котором обмен осуществлялся текстовыми строками, переделать его с работы со строками на работу со структурами. Это уже получилось.
Осталось проработать обработку ошибок и автоматическое восстановление после разрыва связи.