Можно ли собрать байт "за такт"
- Войдите на сайт для отправки комментариев
Пт, 28/10/2016 - 00:19
Есть способ собрать байт с 8 цифровых входов контроллера за 1 ход? Или это аппаратно не заложено?
Есть способ собрать байт с 8 цифровых входов контроллера за 1 ход? Или это аппаратно не заложено?
Если байт – это логические уровни на 8-ми контактах мк, то можно
Если байт – это логические уровни на 8-ми контактах мк, то можно
как?
пост №2
То есть я для этого должен на PD усы положить по биту согласно распиновке, а PIND в коде будет как готовый байт согласно этих данных в любой момент времени?
То есть я для этого должен на PD усы положить по биту согласно распиновке, а PIND в коде будет как готовый байт согласно этих данных в любой момент времени?
а, зачем ты спрашиваешь, если можно взять и проверить - здесь и сейчас?
*очевидно же - если можно записать в порт одной командой что-то, то очевидно можно и считать порт в переменную за один раз.
И записать можно одной командой весь байт?
Знаете, есть такая вещь, даташит называется....
LastHopeMan, Вы никогда не интересовались, временем выполнения команд digitalWrite и digitelRead?
Поинтересуйтесь - время их выполнения составляет 5-7 мкс т.е. порядка 100 тактов. Как Вы думаете, чем микроконтроллер занят все это время? Именно выколупыванием из байта, считанного из регистра, нужного бита (или чтением из регистра, установкой нужного бита в байте и запихиванием результата обратно в регистр).
LastHopeMan, Вы никогда не интересовались, временем выполнения команд digitalWrite и digitelRead?
Поинтересуйтесь - время их выполнения составляет 5-7 мкс т.е. порядка 100 тактов. Как Вы думаете, чем микроконтроллер занят все это время? Именно выколупыванием из байта, считанного из регистра, нужного бита (или чтением из регистра, установкой нужного бита в байте и запихиванием результата обратно в регистр).
рептилоид, к чему ты это всё рассказал? - ему нужно:
собрать байт с 8 цифровых входов контроллера за 1 ход
LastHopeMan, Вы никогда не интересовались, временем выполнения команд digitalWrite и digitelRead?
Поинтересуйтесь - время их выполнения составляет 5-7 мкс т.е. порядка 100 тактов. Как Вы думаете, чем микроконтроллер занят все это время? Именно выколупыванием из байта, считанного из регистра, нужного бита (или чтением из регистра, установкой нужного бита в байте и запихиванием результата обратно в регистр).
Это был мой следующий вопрос. Спасибо.
Ну .. Вы слишком пессимистчны. Заколупыванием и выколупыванием оно там занимается гораздо меньше времени. Большую часть оно занимается "защитой от дурака" и даже поболе чем 5-7мксек., вроде как.
И записать можно одной командой весь байт?
Вы когда-то говорили, что Вы программист. Позвольте мне в этом усомниться.
И записать можно одной командой весь байт?
Вы когда-то говорили, что Вы программист. Позвольте мне в этом усомниться.
Имею мнение в пользу переименовании персонажа из LastHopeMan -> HopelessMan.
Вот код digitalWrite() из одной из последних IDE.
Я хочу спросить, где <sensored> "защита от дурака". на <sensored> мкс.
Для интересующихся новичков я могу прокомментировать. Надеюсь, что не новичку коментарии не нужны.
Защита тут не от "дурака", а просто выключение ШИМа, если он включен.
А время тратится ТОЛЬКО на то, чтобы можно было использовать переменные в номерах пинов. Вот три первые строки и обращаются к макросам, переводящим числа в адреса портов и пинов, на основании таблиц.
Arhat109-2: Раз уж мне дали права .. ниже дано пояснение в чем абзац выше неверен
Вот именно это съедает время, но делает обращение к GPIO универсальным и платформо-независимым. То есть ИМЕННО это - основная фишка IDE. Для этого она (среда) и придумана.
ну .. где-то тут на мой скромный взгляд:
ежели вчё, оператор switch() компилятыр приобразуит в серию последовательных проверок .. :)
P.S. утверждение оказалось неверным. Этот switch() разворачивается в циклическую проверку. Смотреть - ниже.
Ну вот это например :
if
(port == NOT_A_PIN)
return
;
if
(timer != NOT_ON_TIMER) turnOffPWM(timer);
uint8_t oldSREG = SREG;
cli();
...
SREG = oldSREG;
Явно для защиты от дурака, ни для чего другого оно не служит.<sensored>
<sensored>
Там ещё кузявее. Мало того, что массивы перекодировки занимают память (для меги так 70 пинов определяется), вот это:
Как раз НЕ содержит "защиты от дурака" - выход за границу массива.. :)
А ещё разворачивается в "ближнее чтение", что для большой программы для Мега2560 тупо даст ошибку выполнения. Крайне трудно обнаружимую..
<sensored>
А время тратится ТОЛЬКО на то, чтобы можно было использовать переменные в номерах пинов. Вот три первые строки и обращаются к макросам, переводящим числа в адреса портов и пинов, на основании таблиц.
Вот именно это съедает время, но делает обращение к GPIO универсальным и платформо-независимым. То есть ИМЕННО это - основная фишка IDE. Для этого она (среда) и придумана.
Такие вещи делаются одним обращением к массиву по индексу, где здесь сложные алгоритмы на несколько микросекунд?
Пояснение:
Пожалуй я тоже усомнюсь в вашем "программистском навыке, опыте и знаниях". По причине вашей невнимательности (первый признак "не программиста"):
То, что Вы процитировали - в целом вовсе и НЕВЕРНО, ибо смотрим в код:
Собственно "записью" в порт занимаются строки 20 и 22, каждкая из которых транслируется в 3(три) команды МК: "считать порт", "логически домножить или сложить" и "записать в порт".
Строки с 16 по 25 - тупо обеспечение "консистентности" операции и выбор что пишем 0 или 1. Сама по себе консистентность тут никуда и не уперлась, это такая "перестраховка дурака", то бишь избыточность.
А вот теперь ВНИМАТЕЛЬНО смотрим на строку 14, которую автор вашей цитаты ДАЖЕ НЕ УПОМЯНУЛ! А ведь именно она и формирует тот самый "адрес порта", куда пишем .. да, обращением к массиву с индексом. Ибо она разворачивается вот так:
, где port .. всего лишь индекс.
что же таки тогда "делают первые 3 строки", ась? :)
Строка №3 - ищет таким же преобразованием в своем массиве .. номер ТАЙМЕРА, связанного с этой ногой .. ага, для того чтобы его ВЫКЛЮЧИТЬ. На всякий случай .. пользователь -- оно жеж дэ'билл, он жеж не знает что у него творится в его программе, а вдруг остался включен? Пожгет нафиг порт..
Это и есть "защита от дурака" - "раз"
Строка №4 - ищет тем же самым способом (по массиву с индексом), но уже по своему массиву .. номер бита в порту, соответствующий этой ноге.
Ну и строка №5 -- не, она ищет НАЗВАНИЕ порта, как индекс для последующего поиска ЕГО АДРЕСА.
Ну и строка №8 -- это ещё одна защита от дурака: а вдруг вы указали "не ту ногу" .. ещё один де'биллизм авторов, посколку проверки на выход ЗА границы массивов - нигде нет, что возможно для начинающего программиста куда как чаще. Ибо для расхожих плат нумерация ног идет "подряд" и "не той ноги" практически не бывает и вовсе.
P.S.
Эта "чудесная фишка", которую так превознес wdrakula - нумеровать ноги "подряд", дабы потом судорожно лазить по даташиту (они там ИМЕНОВАНЫ!) и приводит к ко всей этой галиматье. Кто-то уже считал в сети, что вызов digitalWrite() на мега2560 занимает .. около 400 тактов МК. Я - не пересчитывал, но верю. Двойная косвенность поиска адреса порта связана с желанием .. уменьшить размер массивов.
P.P.S.
И, если Вы - программист, то должны были уже 100раз найти откуда понадерганы тут коды, и найти среди них комментарий авторов, звучащий примерно так: "это очень плохо, но я не знаю как сделать по-другому".
Это первое, что я нашел примерно полтора года назад, когда впервые взял в руки плату и скачал Ардуино ИДЕ .. не устаю поражаться современным "программистам": Вы пользуетесь чужими разработками и даже не знаете что вам подсовывают в исходниках! Мало того, Вы даже и не знаете где они лежат зачастую .. про "даташиты" - я вообще молчу. Вам тут уже с месяц про них поют.. все "божья роса".
Смешно, как дилетанты в области программирования обсуждают мои навыки, так легко и непринужденно. Те, кто привык методом тыка работать и гордиться школьными знаниями до старости. Удачи вам в ваших великих достижениях.
ну .. где-то тут на мой скромный взгляд:
ежели вчё, оператор switch() компилятыр приобразуит в серию последовательных проверок .. :)
Точно в серию? Почему у меня мой switch() преобразовал в один jmp по таблице?
Упс..
Упс. Проверил. Конкретно этот switch() действительно разворачивается в цикл и переходы по таблице .. занятно, надо будет разобраться. Спасибо.
Когда делал свой twi.c, то обнаружил ровно обратный эффект: switch() разворачивается исключительно в кучу операторов if() и заставить развернуть в обход по таблице мне тогда его так и не удалось. В то время (март-апрель 2016), где-то читал, что типа avr-gcc "так не умеет". Ну, стало быть тоже повелся .. "на заборах и не такое пишут".
Значит предыдущий пост компилируется в более компактный код чем я считал. Но, это никак не отменяет всего остального: в худшем случае, цикл прокручивается весь, и это долго. Просто тут применение pwmOff() в целом, во первых нецелесообразно ибо пины или используется как ногодрыг или как аппаратная функция. В одном скетче увидеть и то и другое - достаточно редко, а кроме того, учитывая что библиотеки wiring - это по большей части программная эмуляция, то и вовсе "нонсенс". А во-вторых, такое выключение можно сделать одной командой после того как перекодировали номер пина на номер таймера в строке №3. Уже есть "какой таймер" и точно также можно получить "какой его вывод" и выключить одной командой без перебора и вовсе.
Собственно, по большому счету тут даже и не важно КАК компилируется этот switch(). Все одно: много, долго и незачем.
Удачи вам в ваших великих достижениях.
И Вам того же!