обмен данными с пк
- Войдите на сайт для отправки комментариев
Втр, 25/08/2020 - 20:36
подскажите пожалуйста как лучше и проще организовать схему обмена.
сейчас у меня вот так
void loop() { if (Serial.available() > 0) { Serial.readBytes(data, 10); if(dataFromApp[0] == 0x47){ //тут делаем что-то полезное } } }
и отправка со стороны компьютера -
@IBAction func send(_ sender: Any) { let data = Data([0x47]) self.serialPort?.send(data) }
но как я понимаю это не корректное решение
но как я понимаю это не корректное решение
Да, хрен же его знает. Задача не озвучена, а значит ХЗ подходит решение к ней или нет.
задача- принять от ардуино несколько байт, обработать их на стороне компьютера и вернуть ардуино несколько байт (до 20)
при этом компьютер не знает когда и сколько данных поступит и ардуино не знает как долго компьютер будет с ними работать и вернет ответ
Проще всего - трансформировать в строку, разделять переносом. Отлаживать будет проще и программировать тоже. Производительность вряд ли создаст проблемы.
я бы пересылал пакетом с заголовком в начале и контрольной суммой в конце. Возможно, в некоторых случаях это кажется избыточным, особенно когда вместо одного байта пересылаешь, скажем, восемь :) зато никаких проблем с отделением одного пакета от другого.
в качестве примера посмотрите библиотеку VirtualWire
с момента нажатия на кнопку до действия микроконтроллера проходит около секунды. это нормально? а если его занять обработкой прерывания значит и реакции не дождусь если она будет в этот момент. есть возможность обнаружения поступления данных в таком случае? или они в буфер в любом случае сохраняются (64 кб вроде) и можно после обработки прерывания просто прочитать его?
с момента нажатия на кнопку до действия микроконтроллера проходит около секунды. это нормально?
Это зависит от того как программы на обоих сторонах написаны. Ардуино может и быстрее.
В буфере сохраняются. Нормальный обработчик прерывания выполняется за десятки микросекунд, а то и быстрее.
если читать только 1 байт, то реакция моментальная. если читать 10 байт, то реально секунда уходит.
64 кб
В буфере сохраняются.
нет. конечно 64 байта.
если читать только 1 байт, то реакция моментальная. если читать 10 байт, то реально секунда уходит.
нет же никаких делеев
iorq, Вы значение слова "передаются" понимаете?
Или, может, тот факт, что байты не могут быть приняты раньше, чем они будут переданы, вызывает у Вас удивление?
PS. И вообще, приведенный Вами код может работать совсем не так, как Вы рассчитываете.
Дак это код для примера, в настоящем-то их полно.
совсем запутался.
byte data[11];
что тут может работать не так?
Лучше Вы расскажите, как по-Вашему этот код должен работать, а потом я уточню, что из этого соответствует истине, а что - нет.
мк в бесконечном цикле проверяет есть ли что прочитать из буфера. если
Serial
.available() вернула > 0 значит что то пришло. зайдем в условие и прочитаем в массив
Serial
.readBytes(data, 10);
единственное конечно может тут кроется ошибка а точнее мое не понимание работы чтения данных. я представляю буфер как массив на 64 байта т. е за раз передать больше этого не получится. а если я передаю 1 байт то в буфере будет находится 0х47, 0xFF ... 0xFF
либо там есть таймауты и если более байты не следуют то выход по таймауту 100 мкс и так 9 раз
ну да если читать байт ровно столько сколько отправляю то реакция моментальная. прихожу к выводу что нужно лмбо отправлять равные пакеты либо передавать вначале размер?
byte data[11];
что тут может работать не так?
ДО ХРЕНА ЧЕГО!
Например, ответьте на вопрос, кто, когда и при каких обстоятельствах сказал Вам, что пришло 10 байтов? В строке №3 Вы проверяете, что что-то пришло. Может 1 байт, может 2, а может 100500. С чего Вы взяли, что пришло 10 и их пора читать?
как определить сколько байт пришло?
как определить сколько байт пришло?
a) Читать по одному.
б) При передачи пакетов разной длины вначале передавать размер пакета.
есть у меня строка -
где первый байт это ее длина. если я делаю так -
то я что отправляю то и получаю
как мне дальше делать?
есть у меня строка -
где первый байт это ее длина. если я делаю так -
то я что отправляю то и получаю
как мне дальше делать?
Ну что нибудь вроде
спасибо. только нужно len-1 т. к 1 байт прочитан
спасибо. только нужно len-1 т. к 1 байт прочитан
Ну это как сообщение кодировать. Обычно передают количество последующих данных. Хотя по всякому бывает
мк в бесконечном цикле проверяет есть ли что прочитать из буфера. если
Serial
.available() вернула > 0 значит что то пришло. зайдем в условие и прочитаем в массив
Serial
.readBytes(data, 10);
единственное конечно может тут кроется ошибка а точнее мое не понимание работы чтения данных. я представляю буфер как массив на 64 байта т. е за раз передать больше этого не получится. а если я передаю 1 байт то в буфере будет находится 0х47, 0xFF ... 0xFF
либо там есть таймауты и если более байты не следуют то выход по таймауту 100 мкс и так 9 раз
ну да если читать байт ровно столько сколько отправляю то реакция моментальная. прихожу к выводу что нужно лмбо отправлять равные пакеты либо передавать вначале размер?
Далее: таймаут действует на всю команду. Т.е. функция ждет 1 с, если за это время она смогла принять 10 байт, - возвращает управление, если нет - выходит по таймауту. Один раз. Т.е. не по 0.1 с на байт, а 1 с - на все.
Ну и последнее: что будет находиться в буфере (кроме первого символа) мы не знаем.
как определить сколько байт пришло?
Кстати, можно и по-другому: if(Serial.available() >= 10)
как определить сколько байт пришло?
Прочитать, наконец, грёбанное описание функцию, которыми пользуетесь - http://arduino.ru/Reference/Serial/Available
Прочитать, наконец, грёбанное описание
Какой ты сёдня злющий. :)
Какой ты сёдня злющий. :)
Дык, жизнь же она "такова, какова она есть, и больше никакова" :-(
Ну что нибудь вроде
имхаю , что так делать не правильно :) надо как минимум дождаться, пока эти самые len байт придут , а то будем вычитывать всякие кракозябры.
Я , обычно, использую два подхода:
1) если скорость лупа не важна, то можно и повисеть в ф-ии приема данных, пока не придет весь пакет
2) если скорость важна - то вычитавать только те байты, что уже пришли. При этом обязательно иметь признаки начала и конца пакета.
имхаю , что так делать не правильно :) надо как минимум дождаться, пока эти самые len байт придут , а то будем вычитывать всякие кракозябры.
Я , обычно, использую два подхода:
1) если скорость лупа не важна, то можно и повисеть в ф-ии приема данных, пока не придет весь пакет
2) если скорость важна - то вычитавать только те байты, что уже пришли. При этом обязательно иметь признаки начала и конца пакета.
Если мы передаем данные одним пакетом подряд и в начале шлем его длинну, то откуда возьмуться кракозябры? И задержки, кроме как на прием пакета, не будет. 10 байт на 115200 передаются за 1 миллисекунду. Ну если такая задержка неприемлима, тогда можно и побайтно.
Если мы передаем данные одним пакетом подряд и в начале шлем его длинну, то откуда возьмуться кракозябры? И задержки, кроме как на прием пакета, не будет. 10 байт на 115200 передаются за 1 миллисекунду. Ну если такая задержка неприемлима, тогда можно и побайтно.
ну, во-первых, бодрейт не всегда 115200, а во-вторых тактовая частота не всегда 16МГц, в-третьих пакет бывает длиннее 10ти байт, поэтому кракозябры более чем возможны. Кстати по ай2си та же фигня.
можно вставить, конечно, while(Seial.available()< len);
Но это блокирующая фигня, и если пакет так и не придет, то проц так и останется висеть.
я иногда поступаю так:
А кто мешает написать if(Serial.available() >= len)... ?
Безо всяких задержек прочтет именно на том проходе loop(), когда в буфере накопится достаточно данных (при условии, что len меньше длины буфера).
ну, во-первых, бодрейт не всегда 115200, а во-вторых тактовая частота не всегда 16МГц, в-третьих пакет бывает длиннее 10ти байт, поэтому кракозябры более чем возможны. Кстати по ай2си та же фигня.
Кракозябры могут быть только если
Serial
.readBytes
отваливается по таймауту. Если данные передаются одним пакетом то таймаута не будет. Даже 300 бод. И если и с перерывами, но короче таймаута то не отвалится, а по дефаолту это целая секунда.А 16MГц, 8 или даже 1 тут совсем по барабану.
все работает четко.
а вообще я на ft232 буду переходить. напрягает выбор порта и устройству имя человеческое не дать.
все работает четко.
а вообще я на ft232 буду переходить. напрягает выбор порта и устройству имя человеческое не дать.
я что-то пропустил, в ft232 как и в cp2102 можно своё имя дать и драйвера свои под это имя подсунуть?
все работает четко.
а вообще я на ft232 буду переходить. напрягает выбор порта и устройству имя человеческое не дать.
я что-то пропустил, в ft232 как и в cp2102 можно своё имя дать и драйвера свои под это имя подсунуть?
драйвера же не по имени ставятся. cp2102 не знаю а в ft232 всю жизнь была такая возможность
в stm32 с аппаратной поддержкой usb тоже можно задавать свои дескрипторы
в stm32 с аппаратной поддержкой usb тоже можно задавать свои дескрипторы
можно. Только смысла никакого. С левыми дескрипторами она перестанет определяться в винде, вместо этого будет "неизвестное устройство"
я под macos. с serial port работать проще. с usb пока разбираюсь как хотя бы научиться управлять светодиодом на PB12
я под macos. с serial port работать проще. с usb пока разбираюсь как хотя бы научиться управлять светодиодом на PB12
не надо управлять светодиодом на PB12 через USB - этот пин при работе USB занят, управлять на нем ничем не получится. Выберите другой пин, кроме PB11-12
вы уверены?
То, что запрграмировать можно, ещё не значит что будет работать и поддерживать все возможные функции.
Я тут мимо проходил, и решил вставить свои 5 копеек. Ибо с сериалами я работаю постоянно и в промышленных масштабах - то есть тягаю 485-е на сотни метров, где они терпят мороз, жару, дождь, снег, гром и молнии. А у вас тут какой то сферический идеальный кабель с золотыми жилами, замороженный в жидком азоте для лучшей проводимости)
Во-первых, кто вам сказал, что на приемник придет именно то, что вы послали с передатчика? Совершенно не факт, и даже с кабелем в 20 сантиметров бывает потери и искажения данных. Редко, но бывают.
Во-вторых, кто вам сказал, что если вы объявили в начале посылки 10 байт, то все эти 10 байт пришли? Передатчик мог взорваться на 5-м байте, метеорит перерубил кабель на 7-м...
Посему, в начале посылки объявляем длину посылки (не обязательно), в конце посылки ставим CRC (обязательно). Если посылка короткая, то тупую байтовую сумму, которая совсем не грузит MK, если посылка длинная - ну там какой нить CRC16/32 на ваш вкус. Сам я, если честно, использовал CRC16 редко, но там реально посылки были в сотни и тысячи байт. В посылках на 5-10-20 байт байтовой суммы вполне хватает. CRC32 не использовал никогда.
Ну и как читать сериал. Читать по одному байту, это однозначно! Прочитал байт, отложил в буфер, читаешь следующий, если есть. Закончились байты - парсишь буфер на предмет что именно ты получил. Первым делом сверяешь CRC - не совпало, игнорим посылку или даем сигнал на повтор (как задумаешь). Потом уже обрабатываешь посылку на предмет осмысленных действий.
вы уверены?
Сорри, спутал с PA12
Тогда не понятно, в чем проблема ...
вы уверены?
Сорри, спутал с PA12
Тогда не понятно, в чем проблема ...
проблема в том что я не знаю как работать с usb и примеров на swift нет. единственное что нашел это вот такой фреймворк https://github.com/Arti3DPlayer/USBDeviceSwift но пока не получается разобраться что отправляется данной функцией
и где это ловить в stm32
пример отлично обнаруживает мой stm32