Прерывания в коде
- Войдите на сайт для отправки комментариев
Пнд, 27/09/2021 - 13:15
Есть небольшой скетч. Плата Nano (пробовал и на Uno).
int on = B00000001; int off = B00000000; void setup() { DDRB = on; } void loop() { noInterrupts(); PORTB = on; //Turn LED on. delayMicroseconds(5); PORTB = off; //Turn LED off. delayMicroseconds(5); interrupts(); }
Итог - на D8 импульсы и среди них небольшие пробелы по 10мкс с интервалом чуть больше миллисекунды.
Смотрел логическим анализатором, частота выборки 8МГц. noInterrupts(); потом добавил, не помогло. Как избавиться от этих пробелов?
даже не знаю, как на это отвечать :) Вроде человек ПОЛТОРА ГОДА занимается программирование ардуино :)
Вы в курсе. что loop() - это цикл? :)
Я не занимаюсь программированием полтора года.
Знал бы ответ, не задавал бы глупые вопросы.
вы выключили прерывания между строчками 11 и 18. Но луп - это цикл, он закольцован. После строчки 19 он идет на строку 10. и между строкой 18 и 11 у вас прерывания разрешены.
Вы можете совсем выключить прерывания. Но тогда у вас перестанет работать миллис и любые другие функции, завязанные на прерывания.
Простой ответ на вопрос, можно или нет?
Просмотрел ответ)
Простой ответ на вопрос, можно или нет?
можно
Простой ответ на вопрос, можно или нет?
можно
но не нужно...
Простой ответ на вопрос, можно или нет?
можно
Можете подсказать? Сам не допилю.
С digitalWrite вроде разобрался как мог. Дальше сложнее.
Можете подсказать? Сам не допилю.
Выключите прерывания и больше не включайте. - строку 18 сотрите да и все.
только это дурость - превращать целый МК в генератор одного сигнала. А ничего другого вы на этом МК уже делать не сможете - любое действие будет нарушать период.
Это не так делается - изучайте таймеры
Простой ответ на вопрос, можно или нет?
можно
но не нужно...
Мне вообще нужно получить на выходе пачку импульсов с разными длительностями.
Не силён в программировании, думал собрать таким образом один за другим импульсы.
Но после увидел то, о чем тема. Будет мешать. Как обойти или может есть более грамотный способ собрать пачку?
Можете подсказать? Сам не допилю.
Выключите прерывания и больше не включайте. - строку 18 сотрите да и все.
только это дурость - превращать целый МК в генератор одного сигнала. А ничего другого вы на этом МК уже делать не сможете - любое действие будет нарушать период.
Это не так делается - изучайте таймеры
Это не нужно, только для наглядности.
Часто делаю блинк, особенно на отдельном МК. Чисто для наглядности. Что бы видеть правильность фьюзов у заказчика.
every(1000 / 2)
toggle(LED);
Совсем никого не напрягает.
я делал что то подобное - генератор сигнала датчиков коленчатого и распределительных валов. На разных автомобилях сигналы датчиков распредвала разные , поэтому написал универсальный скетч, чтобы собирать пачки нужных импульсов. Настройка пачек импульсов делается путем заполнения массива в начале скетча, может это вам чем то поможет.
смысл скетча такой. аппаратный таймер постоянно генерирует кванты (в моем случае по времени соответствующие 1 градусу поворота коленвала), мы считаем эти кванты и в момент нужных порядковых номеров квантов рулим портами, образуя необходимые пачки сигналов. В принципе если поймете суть скетча, переделать под ваши хотелки не сложно.
А точнее "с интервалом 1024 мкс".
Это включается подсчёте millis.
Если millis Вам не нужен - выключите и проблема уйдёт.
Если же millis нужен, то надо делать по-другому - через настройку таймеров. Но там всё непросто.
я делал что то подобное - генератор сигнала датчиков коленчатого и распределительных валов. На разных автомобилях сигналы датчиков распредвала разные , поэтому написал универсальный скетч, чтобы собирать пачки нужных импульсов. Настройка пачек импульсов делается путем заполнения массива в начале скетча, может это вам чем то поможет.
смысл скетча такой. аппаратный таймер постоянно генерирует кванты (в моем случае по времени соответствующие 1 градусу поворота коленвала), мы считаем эти кванты и в момент нужных порядковых номеров квантов рулим портами, образуя необходимые пачки сигналов. В принципе если поймете суть скетча, переделать под ваши хотелки не сложно.
Спасибо, посмотрю.
А пока собрал скетч отдельными блоками на 4 разных кода по тому, что выше сам показал. На каждый блок прерывания выключал, так было без ошибок. Сделал по команде с цифровых пинов.
Еще искал как сделать однократную посылку собранной пачки при сохранении условия на цифровом пине, ничего понятного мне не нашел. В loop всё повторяется. Решение нашел - одновибратор с длительностью заведомо меньшей, чем длительность пачки, аппаратно. Мне с электроникой проще.
Наверное это как-то можно программно организовать, не мог сообразить как это в поиске правильно обозвать.
Наверное это как-то можно программно организовать, не мог сообразить как это в поиске правильно обозвать.
заводите переменную флаг . дёргаете лаптями только в случае поднятого флага. Если флаг опустить, нога не будет дрыгаться.
ЗЫ. Только в лупе такие вещи не делаются. При больших частотах сигнала - только в обработчике прерывания.
Наверное это как-то можно программно организовать, не мог сообразить как это в поиске правильно обозвать.
заводите переменную флаг . дёргаете лаптями только в случае поднятого флага. Если флаг опустить, нога не будет дрыгаться.
ЗЫ. Только в лупе такие вещи не делаются. При больших частотах сигнала - только в обработчике прерывания.
Всё это сложновато для меня, на простой логике соберу.
Спасибо за помощь.
Пока разбирался как собрать, сделал открытие.
В LOOP delay не работает, а delayMicroseconds - да.
Добавлено.
Может что-то не так понимаю.
Вернее не в LOOP, а когда прерывания выключены.))
Интересно посмотреть как разные пачки импульсов на логике собирать.. Имхо проще таймер изучить
Если нарисуете какой нужен сигнал, попробую сделать, сам только учусь ковыряться в таймерах, полезно будет.
Нужно уметь и то и другое, но таймером на ардуине проще и дешевле
Вернее не в LOOP, а когда прерывания выключены.))
Delay использует millis. А как тут уже говорили не раз - millis не работает когда прерывания запрещены.
А delayMicroseconds не использует millis, а просто крутит цикл необходимое число раз для выбранной задержки, поэтому от прерываний не зависит.
по моему тут надо без delay() это реализовывать
по моему тут надо без delay() это реализовывать
тут их и нет
Я здесь только про одноразовую посылку говорил.
Одновибратор с временем меньше, чем время всей пачки.
Пачку импульсов на логике я бы не стал собирать.
Вот код. Собирал по каким-то примерам.
Время в мкс выяснил опытным путём по лог. анализатору.
Еще нашел код для кнопки с однократным выполнением условия. Проверял, рабочий.
Это наверное о нем выше шла речь. Поправил под себя, но не мог сообразить как правильно
вставить в LOOP.
andrey3824 - и не лень было набивать 500 строк практически одинаковых операторов? про массивы и циклы не слыхали? код можно сократить раз в 10. ничего не меняя в алгоритме - просто за счет исключения повторов
Я здесь только про одноразовую посылку говорил.
Одновибратор с временем меньше, чем время всей пачки.
Пачку импульсов на логике я бы не стал собирать.
это делается на двухвходовом элементе И, при сформированном сигнале пачки, куда уж проще )))
Я выше отметил, что мне с электроникой проще.
andrey3824 - и не лень было набивать 500 строк практически одинаковых операторов? про массивы и циклы не слыхали? код можно сократить раз в 10. ничего не меняя в алгоритме - просто за счет исключения повторов
Про массивы знаю (читал), нужно знать как применить.
Примеры подходящие не нашел.
Еще нужно правильно обозвать в поисковике то, что именно нужно.
andrey3824, не заметил сразу пары крайне грубых ошибок в вашем коде, из-за которых он просто не будет работать. Вы управляете выходом строчками типа PORTB = off; или PORTB = on;
Если посмотреть самую первую строку вашего кода, мы видим что
on = B00000001;
То есть полностью ваше выражение получается таким
PORTB = B00000001;
Вы понимаете, что происходит в этой строке? - думаю нет. Я вам обьясню. Этой записью вы не только выставляете единицу на пине B0, но и обнуляете все пины от B1 до B7. Положим, не все из них есть на Нано, но пины с B1 по B5 - это пины 9-13 ардуино.
А теперь посмотрите в свой код. Разве эти пины у вас не используются? Ваш пин SW - это пин 10, а SW2 - это пин 9. Записывая разом весь порт B - вы можете попрощаться с любыми разумными значениями на этих двух входах.
Ровно тоже самое относится к выставлению режима в регистре DDRB в строке 14 - присваивая ему единицу, вы тупо стираете результат коман pinMode() на пару строк выше
присваивать целиком весь порт командой PORTB = B00000001;, когда вам нужно поменять один пин - в корне неверно. вам нужно записывать единицу не во весь порт, а только в младший бит порта, не трогая при этом остальные биты. Как это делать - ищите в разделе справки Ардуино "битовые операции"
andrey3824, не заметил сразу пары крайне грубых ошибок в вашем коде, из-за которых он просто не будет работать. Вы управляете выходом строчками типа PORTB = off; или PORTB = on;
Если посмотреть самую первую строку вашего кода, мы видим что
on = B00000001;
То есть полностью ваше выражение получается таким
PORTB = B00000001;
Вы понимаете, что происходит в этой строке? - думаю нет. Я вам обьясню. Этой записью вы не только выставляете единицу на пине B0, но и обнуляете все пины от B1 до B7. Положим, не все из них есть на Нано, но пины с B1 по B5 - это пины 9-13 ардуино.
А теперь посмотрите в свой код. Разве эти пины у вас не используются? Ваш пин SW - это пин 10, а SW2 - это пин 9. Записывая разом весь порт B - вы можете попрощаться с любыми разумными значениями на этих двух входах.
Ровно тоже самое относится к выставлению режима в регистре DDRB в строке 14 - присваивая ему единицу, вы тупо стираете результат коман pinMode() на пару строк выше
присваивать целиком весь порт командой PORTB = B00000001;, когда вам нужно поменять один пин - в корне неверно. вам нужно записывать единицу не во весь порт, а только в младший бит порта, не трогая при этом остальные биты. Как это делать - ищите в разделе справки Ардуино "битовые операции"
Сделал так.
Сделал так.
Напрасно. Это те же яйтса.
Проверил, так работает.
С массивами не стал разбираться, сложновато для меня.
Раз в год нужно что-то собрать. Просишь помощи, камнями забросают.
С таким подходом
Еще и валунами завалят. Жди.
Проверил, так работает.
неа, вам это кажется. Не работает.
Теперь sw и sw1 всегда HIGH
Вот вы жалуетесь, что вам не помогают. А нафига вам помогать, если даже при прямом указании, что надо исправить и как - вы этого не делаете? Для кого я написал "Как это делать - ищите в разделе справки Ардуино "битовые операции". Вы этот раздел читали?
Посмотрите здесь https://doc.arduino.ua/ru/prog/BitSet и здесь https://doc.arduino.ua/ru/prog/BitClear - установит и сбросить бит не задевая другие. Всё делается на уровне ассемблера - быстро. Ещё надо помнить какой бит - номер, а не значение. Ваш долгий digitalWrite(swo, HIGH); swo - 11 нога это PB3 заменяется на быстрый bitSet(PORTB,3); и LOW в bitClear(PORTB,3). Другие биты не изменяются. Перед началом вывода надо переключить ногу порта на вывод командой bitSet(DDRB,3); .
Ещё очень полезная функция https://doc.arduino.ua/ru/prog/Bit - не надо помнить двоичное значение.
C for просто - набиваем массивы задержек и крутим.
nik182 вангую не в коня корм :) Ему по буквам разжевывать надо :)
Посмотрим. Вроде по буквам разжевал.
Посмотрим. Вроде по буквам разжевал.
Не могу понять в каком случае выражение в строке 10 имеет смысл, т.е. для какого это примера?
if (bitRead(PIND, 6) != bit(6)) // D10 - бит 6 порта D, bit(6) только для примера, если надо сравнить с единицей.
bitRead(PIND, 6) равен или 0 или 1
bit(6) равен всегда 64 и они не могут быть равны.
Да. Это я тупанул. Действительно bitRead 0 или 1. Это я по привычки когда сравниваешь регистр PIND == B100000 проще написать PIND == bit(6) - нули считать не надо. А правильно вообще длинно (PIND & B100000) == B100000 . Написать bitRead(PIND, 6) == 1 проще а после компиляции результат получится одинаковым. Написать можно if(!bitRead(PIND, 6)).
Пока разбирался как собрать, сделал открытие.
В LOOP delay не работает, если прерывания отключены, а delayMicroseconds - да.
Надо правильный делей() юзать))
Только это зло))
Проверил, так работает.
неа, вам это кажется. Не работает.
Теперь sw и sw1 всегда HIGH
Вот вы жалуетесь, что вам не помогают. А нафига вам помогать, если даже при прямом указании, что надо исправить и как - вы этого не делаете? Для кого я написал "Как это делать - ищите в разделе справки Ардуино "битовые операции". Вы этот раздел читали?
Я объясню, что видел.
В старом коде после первого LOW на входе там появлялся минус. Объяснили, понял - почему.
Сделал поправку, проверил. Массу на ногу - работает. Убираю массу - не работает. Снова масса - работает.
Мне пока больше и не нужно. Последняя пачка улетела после убирания массы, на входе снова "1". Дальше всё в рабочем состоянии.
А по битовым пробовал, тоже получалось, переделывать больше. Сложение, умножение.
Последний вариант удобнее показался.
nik182 вангую не в коня корм :) Ему по буквам разжевывать надо :)
Вникаю как могу. Кто на что учился.
Посмотрите здесь https://doc.arduino.ua/ru/prog/BitSet и здесь https://doc.arduino.ua/ru/prog/BitClear - установит и сбросить бит не задевая другие. Всё делается на уровне ассемблера - быстро. Ещё надо помнить какой бит - номер, а не значение. Ваш долгий digitalWrite(swo, HIGH); swo - 11 нога это PB3 заменяется на быстрый bitSet(PORTB,3); и LOW в bitClear(PORTB,3). Другие биты не изменяются. Перед началом вывода надо переключить ногу порта на вывод командой bitSet(DDRB,3); .
Ещё очень полезная функция https://doc.arduino.ua/ru/prog/Bit - не надо помнить двоичное значение.
C for просто - набиваем массивы задержек и крутим.
Спасибо за помощь)
Насчет D10 - это вроде порт В, а не D (8-13)
Я сам когда пытался с массивом сделать, не мог найти как правильно в delayMicroseconds массив прописать.
Да. Как то как. D10 это PB2. Куда то я не туда посмотрел. Будет
if
(!bitRead(PINВ, 2).
А PB3 это D11, который я как выход прописывал.Фига-се!
«Если у тебя спрошено будет: что полезнее, солнце или месяц? – ответствуй: месяц. Ибо солнце светит днем, когда и без того светло; а месяц – ночью»
(Козьма Петрович Прутков, «Мысли и афоризмы», афоризм №51)