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

MementoMori

Свой
  • Постов

    1 340
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные MementoMori


  1. 3 minutes ago, tonyk_av said:

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

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

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

  2. 2 hours ago, xvr said:

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

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

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

  3. 13 minutes ago, tonyk_av said:

    Коллега!

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

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

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

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

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

  4. Подумал, разобрался, оптимизировал прием, все хорошо. До 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"

     
  5. 2 hours ago, TOG said:

    У меня тоже была шляпа с HM-13. В нашем модуле с завода был не правильно установлен класс устройства(0xD0, 0xD0, 0xD0), а должен быть 0x00, 0x1F, 0x00. Дал команду на смену класса: "AT+COFD001F00" и все стало хорошо.

    (вот нормальный полный даташит):

    bluetoothdual_en.pdf 895.63 kB · 3 downloads

    Скажите а софт для работы на чем писали? Я имею в виду не для модуля HM-13, а для приложения на телефоне? Мне бы проконсультироваться и на этот счет.

  6. Потихоньку ковыряю дальше.

    Выровнял структуру, из 224 байт сэкономил 24. Теперь структура весит 200 байт.

    Решил поиграть в "эхо" - передаю данные и принимаю их же обратно. Передаю на скорости 115200 бод. Казалось бы, около 10 кбайт в секунду.

    Цикл следующий - отправка 200 байт с телефона -> прием блютузом -> передача на контроллер -> передача из контроллера в блютуз -> прием в телефоне.

    Процесс занимает около 1 секунды.

    Так и должно быть?  В скорости передачи собственно байт сомневаться не приходится.  Так может быть начало и конец приема и передачи накладывают какие-то задержки?

    В контроллере модуль HM-13, если что.

  7. 13 minutes ago, Сергей Борщ said:

    Вы что-то где-то списали неправильно.

    Вы правы, был невнимателен, не везде удалил указатели. Поправил - все работает, без new. У меня размер буфера маленький (я сейчас набросал в максимально близком к конечному виде, получилось 224), разницы, естественно, незаметно, но, верю вам, что так лучше.

  8. 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>')
     

  9. 30 minutes ago, dimka76 said:

    Пока ТС не признается, гадать можно долго )))

    Блин, да в C++ Builder я программирую. И в библиотеках для написания программ под Андроид дух Явы таки имеет место быть, ибо в созданном проекте есть такая строка #include <AndroidApi.JNI.JavaTypes.hpp>

    • Like 1
  10. 12 minutes ago, Сергей Борщ said:

    удет работать ничуть не хуже, но будет короче и быстрее.

    Возможно после компиляции он и мог бы работать быстрее. Но компилятор протестует. Г

    14 minutes ago, Сергей Борщ said:

    Неужели в Java все-все переменные должны объявляться через new?

    В примере кода для bluetooth от разработчика очень много чего объявляется через new

     

  11. 1 hour ago, Сергей Борщ said:

    Зачем вы создаете объект в динамической памяти через new?

    Я писал выше:

    Quote

    Сразу скажу тем, кто будет предлагать альтернативу - буфер должен быть объявлен так и только так, этого требует библиотека под Андроид, работающая с Bluetooth.

     

    1 hour ago, Сергей Борщ said:

    А теперь читайте по губам

    Опять же, выше я уже написал, что понял это и исправил, все работает.

    3 hours ago, jcxz said:

    Не читали в учебнике по языку си о структурах и выравнивание их членов.

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

     

  12. 27 minutes ago, dimka76 said:

    А если у вас принимающая и передающая платформы будут иметь разную разрядность ? И не только.

    Делается под конкретную платформу. Для себя, если быть точным.

    Но намек ясен, будут предложения по унификации, с целью платформонезависимости?  Где у меня слабое место?

  13. 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));

     

  14. 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

  15. 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;

    Буфер с байтами передается без проблем, преобразование в текст не требуется. Разбирать и собирать можно байты.

    Я бы уже давно всю структуру (она у меня сложнее, тут я сократил ее с целью облегчения восприятия) таким же образом заполнил, но я хочу понять, как это делается проще, через указатели.

     

  16. 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>; ?

  17. Новый вопрос.

    Есть буфер, объявленный следующим образом

    	  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  -ругается на несоответствие типов.

  18. Друзья, есть у меня модуль HM-13  , в нем 2 блютусины сразу, одна обычная, другая BLE

    С обычной сопряжение (штатными средствами телефона) происходит без проблем, спрашивается PIN, вводится и устройство сопряжено).

    А вот при обнаружении устройства BLE телефон мне предлагает "Перейдите в приложение с этого устройства, чтобы сопрячь с ним).  А "это устройство" - напомню, это модуль, ни с каким приложением он не работает.

    Может есть какие команды настройки, позволяющие автоматически сопрягать? Чтение даташита https://files.seeedstudio.com/wiki/Grove-BLE-dual_model-v1.0/res/Bluetooth_HM-13_en.pdf  ничего не дало.

  19. 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)
              
    
            }

     

  20. Друзья, ваш спор перешел в разряд "с какого конца разбивать яйцо, с острого или тупого".  Я решение выбрал, призываю вас не спорить.

     

    У меня следующий вопрос.

    А как бы мне передать структуру по 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 и это считается текстовой командой.  

    Там сложностей не возникало. А вот со структурами как быть? Там ведь уже не используешь символы конца строки, ибо символы с этим кодом могут быть в структуре.

     

     

  21. 2 hours ago, EdgeAligned said:

    Положите этот typedef в файл заголовочника и подключите его (файл) к файлу исходника и к остальным файлам, куда его надо подключать.

    Уже так и сделал.

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

    2 hours ago, EdgeAligned said:

    Ну и освойте написание многофайловых проектов, чтобы не валить всё в один main.c.

    Так у меня эта переменная только в main.c и stm32f1xx_it.c  используется. Проектик маленький, из-за 3-х функций еще какой-то файл создавать я не стал. А вообще так и делаю - отделяю функционал от распределения.

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