delayMicroseconds не корректно работает
- Войдите на сайт для отправки комментариев
Пнд, 19/02/2018 - 03:51
стоит задача эмулировать кодовую посылку неизвестного протокола. считал ее логическим анализатором - тайминги такие - 7000 | 13.7 | 4.5 | 6.7 | 3.2 | 7 | 3 | 1.7 | 8.2 | 7 | 3.2 | 1.7
пытаюсь воспроизвести на ардуино уно -
PORTD |= (1 << 2); delay(7); PORTD &= ~(1 << 2); delayMicroseconds(13.7); PORTD |= (1 << 2); delayMicroseconds(4.5); PORTD &= ~(1 << 2); delayMicroseconds(6.7); PORTD |= (1 << 2); delayMicroseconds(3.2); PORTD &= ~(1 << 2); delayMicroseconds(7); PORTD |= (1 << 2); delayMicroseconds(3); PORTD &= ~(1 << 2); delayMicroseconds(1.7); PORTD |= (1 << 2); delayMicroseconds(8.2); PORTD &= ~(1 << 2); delayMicroseconds(7); PORTD |= (1 << 2); delayMicroseconds(3.2); PORTD &= ~(1 << 2); delayMicroseconds(1.7); PORTD |= (1 << 2);
но получаю полную ахинею. что не так?

ахинея - это вот такая запись: delayMicroseconds(3.2);
Слабо сначала посмотреть в референсе тип параметра delayMicroseconds() ?
unsigned int
т.е мне не задать менее 3 микросекунд? да и при записи целых чисел лучше не становится
unsigned int
т.е мне не задать менее 3 микросекунд? да и при записи целых чисел лучше не становится
Вот как ты думаешь, только честно - если параметр функции беззнаковое двухбайтовое целое, то подставляя туда число с плавающей точкой - ты задавишь функцию авторитетом и она ВНЕЗАПНО начнёт работать с float? Нет дробных задержек в delayMicroseconds, только целые.
Что касается эмуляции конкретной посылки, то решение в лоб - написать код, который будет занимать столько тактов процессора, чтобы обеспечить нужные наносекундные задержки. Т.е. сколько-то NOP подряд, например. Один clock cycle на 16 МГц - это 62.5 наносекунды, емнип. Перемножай, дели - и получишь кол-во циклов, которое надо прогнать, чтобы получить требуемые тебе чёткие задержки.
да я же говорю - поокруглял все а она все равно как хочет так и работает
а можно пример такого кода а то я что то не пойму как это так
Помни, что
This function works very accurately in the range 3 microseconds and up. We cannot assure that delayMicroseconds will perform precisely for smaller delay-times.
а можно пример такого кода а то я что то не пойму как это так
Пример кода, как вставить нужное кол-во NOP? В гугль, видимо, сегодня только по продовольственным карточкам допуск...
Задержка 62.5 наносекунды. Дальше - сам, пожалуйста; думаю, с арифметикой справишься.
Собственно всё верно. delayMicroseconds() плохо работает с задержками менее 3мксек, потому как время задержки в ней вычисляется БЕЗ учета вызова и возврата в функцию. А это 5 и 5 тактовой. итого 625нсек или 0.625мксек.
Если нужно точнее, то как Вам уже написали - ассемблерная вставка в тело нужного количества nop или использовать макрос типа _delay_loop_1() из utils/delay_basic.h или _delay_loop_2(), смотря что Вам больше подходит. Первый втыкает задержки из 8-и байтовой переменной по 3 такта, а второй из 16-байтовой по 4 такта. Давным-давно уже выносил их себе в arhat.h как макросы delay8() и delay16(). Тупо, просто и очень понятно "сколько это".
а можно пример такого кода а то я что то не пойму как это так
Ну, например, так: http://arduino.ru/forum/proekty/analog-analogovogo-sintezatora#comment-261101
Помни, что
This function works very accurately in the range 3 microseconds and up. We cannot assure that delayMicroseconds will perform precisely for smaller delay-times.
ПРактика показывает, что на 16-МГц контроллерах уже 1 мкс выполняется с приемлемой точностью.
у меня получилось 20 asm("nop"); для задержки 1,5 микросекунды
но оно тоже работает как ему угодно. допустим 1 ноп дает задержку 250 наносекунд. 2 нопа продолжают давать такую же задержку и только 5 нопов дают задержку 500 наносекунд
но оно тоже работает как ему угодно. допустим 1 ноп дает задержку 250 наносекунд. 2 нопа продолжают давать такую же задержку и только 5 нопов дают задержку 500 наносекунд
а можно поинтересоваться. чем вы это измеряли?
логический анализатор показывает тайминги
логический анализатор показывает тайминги
выложите скетч - у вас между импульсами, возможно, попадают вызовы прерываний
не вижу кода с "nop"
В строке 7 замените delay на delayMicroseconds(7000);
А в setup вставьте
cli();
У Вас каждые 4 микросекунды происходит прерывание и начинает miilis считаться. Кстати, после правок, о которых я сказал, millis'у скажите до свидянья.
к сожалению ничего не изменяется. и даже asm("nop"); не дает точности - то 250 то 500 наносекунд. может подход у меня не верный в плане эмуляции? как то же ардуина общается с периферией - может надо все же реализовать протокол?
Так не может быть. Что-то Вы или не доделали , или не договариваете. Не может 1 nop давать задержку 250ns, и два столько же. Один даёт 62,5 нс, а два 125 - только что проверил.
дайте ваш код
Так не может быть. Что-то Вы или не доделали , или не договариваете. Не может 1 nop давать задержку 250ns, и два столько же. Один даёт 62,5 нс, а два 125 - только что проверил.
Женя! Он это в цикле делает! ;););)
тогда 4 такта: 1 на NOP, 1 - на инкремент счетчика, 1 на сравнение, 1 - на переход.
4 и есть - что равно 250 нс. ;) ;) ;)
=================
Евгений! Нужно прекращать возиться с новичками - "Кошка бросила котят, пусть е..ться как хотят!".
Новичек, он, как солдат - его куда ни целуй, везде жопа.
вообщем происходит какая то чертовщина. отказался я от первой затеи и сделал вот так -
при отправке SendBit(0b00000000); с этими нулями происходит невероятное - тайминг первого нуля = 4,5 микросекунды и далее все уменьшается и уменьшается и на последнем нуле уже = 1,750 микросекунды т.е более чем в два раза уменьшается. при чем если отправлять только нули - все замечательно. я уже пробовал по всякому- и прерывания отключал, и delayMicroseconds и _delay_us и ноп - все дает один и тот же результат
Блин деревянный. У тебя loop вызывается постоянно. Затраты на вызов функции сам посчитаешь, или как? NOP прекрасно работает, если есть прямые руки и светлая голова.
еще один, у кого "некорректно работает".... мозг.
Вот неужели сложно просто сказать что я делаю не так чем говорить загадками ещё больше путая? Все прям родились с ардуиной
Какие загадки? loop вызываетя постоянно, при этом накладные расходы - это вызов этой функции. Так понятней? Если хочешь генерить без накладных расходов, то:
Ещё прерывания запретить перед while(1) - и всё.
ничего не меняется. у меня сейчас проблема уже не с точностью задержек а с плавным уменьшением тайминга при отправке 00000000
Т.е. NOP уже ВНЕЗАПНО работает так, как и обязан, т.е. даёт нужную задержку в 62,5 наносекунды? Так и запишем.
да какой ноп - полный код выложен выше (23 сообщение). короче есть какой нибудь форум для особоодаренных? я туда пойду
как будто хер знает работу что ли у вас отбираю или деньги? сижу разобраться пытаюсь что в этом плохого?
Ооох. Про накладные расходы на вызовы функций/циклов ты пропустил мимо ушей? Тогда да - тебе на другой форум, например, на форум отоларингологов - там помогут разобраться, почему в уши ничего не входит.
Пойми - вычисления надо производить ДО критичных ко времени действий. Это как минимум. Либо - корректировать время задержки, в зависимости от времени, занимаемого вычислениями. Смекаешь?
Твою SendBit лучше переписать примерно так:
я реально походу тупой что ли? а как мне выполнять мой код без loop? то что вы привели в 27 сообщении тоже ведь содержит loop. и разницы я никакой не заметил -
Разницы не заметил, но она есть, поверь. В моём случае в loop заходит только однажды и далее в нём и живёт. В твоём - каждый раз туда заходит, более того, если ты посмотришь исходники - ты увидишь, что после loop там ещё вызываются всякие serialEvent - тоже трата времени.
По поводу SendBit я выше отредактировал сообщение.
я реально походу тупой что ли? а как мне выполнять мой код без loop? то что вы привели в 27 сообщении тоже ведь содержит loop. и разницы я никакой не заметил -
Ежели внутри loop(). как и любой другой функции, впрочем, есть бесконечный цикл, то постоянных входов в нее и выходов из нее не осуществляется, т.е. накладные расходы на эти операции отсутствуют. Получается вот такое:
Так понятней?
iopq - в функции SendBit каждый шаг For - инкремент i. сравнение If - все знамает время и все задержки нужно корректировать с учетом этого. Если вы отсылаете 1-2 байта. можно вообще отказался от функции и for и записать код линейно
я реально походу тупой что ли?
Да, не тупой, просто опыта нет и читаете невнимательно.
Ну, давайте я попробую объяснить.
Если задержкий у Вас достаточно большие (миллисекунды, скажем), то можно плевать на накладные расходы. Если э задержки маленьки, то плевать нельзя, из надо учитывать.
И вот теперь смотрите. Я возьму код, похожий на Ваш, пока без while:
При любых расчётах Вы должны понимать, что строки 1, 5, 8 и 10 тоже выполняются не мгновенно и это время надо учитывать.
Этот код странслируется в такие машинные команды:
Длительность исполнения nop - 1 такт (62,5 нс).
Длительность исполнения команд cbi и sbi - 2 такта (125 нс)
Таким образом, весь приведённый кусок кода исполнится за 14 тактов, т.е. за 875 наносекунд.
Вот так и надо считать, каждую команду. Тогда Вы точно получите то, что хотите.
Если Вы добавите while или ещё чего - это всё команды. Их тоже надо также выписать и считать.
Стало понятнее?
длинные последовательности NOP удаляет оптимизатор при стандартной настройке "-Os" ;) ;) ;)
так что учите новичка #PRAGMA GCC optimize ("-O0") или правильным ассемблерным вставкам с волатилью... ;)
------------------------
его первый код можно вот так переделать, тогда работает при неизмененной ИДЕ.
вот такая картинка получится... у меня как раз полчаса свободные были...
правильным ассемблерным вставкам с волатилью... ;)
Так вроде ж _NOP();- как раз такая хрень и есть (хотя лезть смотреть лень)
Вы только поясните человеку, что Ваш код нормально сможет работать только и исключительно только с константными параметрами в вызовах my_delay(), а то он туда как забабахает float переменную.. )
DIYMan спасибо с вашим кодом отправки мне удалось подогнать тайминг под образец. пока что на мою посылку устройство не отвечает. разбираюсь
"...Раз пошла такая пьянка", то вот вам самое правильное решение подобной задачи:
Пользуем SPI - каждый байт - это бит нашего кода. Выход на MOSI, ессно.
Ну и картинка с логаналайзера.
не плохой код. как увеличить тайминг с 1,5 мкс до 3 мкс? и не могу понять почему на оригинальный запрос устройство отвечает а на мой не хочет -
я понимаю что это не UART. это для наглядности
не плохой код. как увеличить тайминг с 1,5 мкс до 3 мкс? и не могу понять почему на оригинальный запрос устройство отвечает а на мой не хочет -
1. сними всю посылку логаналайзером и выложи в каком-нибудь читаемом виде. Если у тебя стандартный китаец за 300руб (типа Saleaelogic), то в программе есть экспорт в CSV.
2. как увеличить?: подключай ардуино, логаналайзер и комп - и подбирай скорость SPI и коды для передачи "1" и "0".
...Я что-то начал подозревать, что ты все это не в железе, а в "протеусе" делашь... если так, то этот онанизм - без меня.
3. устройство твое может не принимать из-за неправильного "обрамления" передачи... как вариант бывает нужно сперва выдать некий условный "ресет" - это может быть высокий( или низкий ;) ) уровень аж на 500мс. Поэтому и говорю - сними тайминг аккуратно.
никакого протеуса - все в чистейшем железе. http://my-files.ru/x2xniu ссылка на лог
никакого протеуса - все в чистейшем железе. http://my-files.ru/x2xniu ссылка на лог
Это или неудачная шутка или издевательство. 500К лога, да? Две с чем-то секунды... круто!
сделай его читаемым и в таблице пометь моменты начала и конца кода, на который реагирует твой прибор.
Просто открой этот CSV в ехеле или опенофисе и пометь все, что нужно. тогда можно подбирать.
я могу сделать файл поболее только для чего если все что происходит занимает даже меньше времени просто я не могу быстрее руками и кнопку в программе нажать и питание подать и еще раз нажать. что то я не пойму с этим файлом - там же ничего не понятно - нули и единицы и время
наверное я что то недопонял. у меня полученный файл выглядит вот так- тут же месяц сидеть надо что бы проставить что у меня происходит
что то я не пойму с этим файлом - там же ничего не понятно - нули и единицы и время
ты забавный! Ты его в Exel открой...
Я тебе написал, что он слишком большой для анализа, нахрена нужно целых 2 секунды данных?
1. вот твой причесаанный файл. (первая 1000 строк)
Уже все не так, как ты написал, все "0" имеют длительность округленно 1 мкс.
http://my-files.ru/kmbig4 не знаю так или не так