Простой вопрос, а ставит меня в тупик :)
- Войдите на сайт для отправки комментариев
Пнд, 29/08/2022 - 11:20
https://www.youtube.com/watch?v=AT0CXtchKoA
Суть такая, есть устройство которое рапортует о своем состоянии логическими уровнями на выходах, всего выводов 6, мне надо в зависимости от состояний этих уровней выводить на индикацию (lcd1602) определенный текст. Я для этой цели заказал MH-Tiny, думаю справится. С самим индикатором проблем нет, разобрался как работает. Как мне правильно организовать считывание кодов? Хочу чтобы как-то по прерываниям, чтобы атинька засыпала когда нет изменений на входах. Дайте направление куда копать?
PCINT
ua6em, спасибо!
А есть ли в природе симулятор ардуино? Ну вот как в протеусе можно скомпилировать проект и не загружая его посмотреть как логика работает. У меня еще ардуинка не доехала, хочется проверить как будет скетч работать, виртуально.
Proteus
wokwi.com
Да вот к примеру:
ua6em, спасибо!
А есть ли в природе симулятор ардуино? Ну вот как в протеусе можно скомпилировать проект и не загружая его посмотреть как логика работает. У меня еще ардуинка не доехала, хочется проверить как будет скетч работать, виртуально.
так в том же протеусе и ардуину можно
До чего дошел прогресс :) Парни, всем спасибо, изучаю и пробую, пока больше нет вопросов.
До чего дошел прогресс :) Парни, всем спасибо, изучаю и пробую, пока больше нет вопросов.
ты обращайся ежели что )))
Обращаюсь! Пытаюсь освоить прерывания, нашел в сети этот скетч:
#define ledPin 13 // Пин для светодиода #define setLedOnPin 8 // Пин кнопки включения светодиода #define setLedOffPin 9 // Пин кнопки выключения светодиода volatile uint8_t state = 0; uint8_t oldPINB = 0xFF; void pciSetup(byte pin) { *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // Разрешаем PCINT для указанного пина PCIFR |= bit (digitalPinToPCICRbit(pin)); // Очищаем признак запроса прерывания для соответствующей группы пинов PCICR |= bit (digitalPinToPCICRbit(pin)); // Разрешаем PCINT для соответствующей группы пинов } ISR (PCINT0_vect) { // Обработчик запросов прерывания от пинов D8..D13 uint8_t changedbits = PINB ^ oldPINB; oldPINB = PINB; if (changedbits & (1 << PB0)) { // Изменился D8 state = 1; // Зажигаем светодиод } if (changedbits & (1 << PB1)) { // Изменился D9 state = 0; // Гасим светодиод } } void setup() { pinMode(ledPin, OUTPUT); pinMode(setLedOnPin, INPUT_PULLUP); // Подтянем пины-источники PCINT к питанию pinMode(setLedOffPin, INPUT_PULLUP); pciSetup(setLedOnPin); // И разрешим на них прерывания pciSetup(setLedOffPin); } void loop() { digitalWrite(ledPin, state); }В протеусе собрал и не работает, не пойму в чем причина, то-ли в протеусе (хотя другие скетчи работают), то-ли в коде, помогите разобраться.
В шестой строке:
Не вижу разрешение прерываний sei().
У Ардуино они уже разрешены.
В шестой строке:
Это насколько я понял маска с которой сравнивается состояние пинов, вернее их изменение. Как это может влиять?
В шестой строке:
Как это может влиять?
Значение этой переменной меняется в прерывании.
наш коллега Владимир неплохо все озвучил )))
наш коллега Владимир неплохо все озвучил )))
Так я от туда и взял скетч, но не работает :(
[/quote]
Значение этой переменной меняется в прерывании.
[/quote]
Ну да, но начальное значение FF, оно и так FF пины ведь подтянуты.
наш коллега Владимир неплохо все озвучил )))
Так я от туда и взял скетч, но не работает :(
так я к тому и сказал, его детище, должен и ответ держать )))
Ну да, но начальное значение FF, оно и так FF пины ведь подтянуты.
начальное возможно, но потом-то оно меняется
У меня сомнение - вы понимаете, зачем вообще пишут "volatile" в таких случаях?
Проверил.
Код из #8 работает без нареканий и без изменений !!!
У ТС видимо картинка c UNO для рисования схем, а не модель для Proteus !
Код из #8 работает без нареканий и без изменений !!!
Да, я тоже проверял. volatile не нужен, работает на голом камне и без него. В Протеусе Ардуино у меня тоже плохо работает, может комп слабый...
P.S. Вот,даже код набросал для проверки
#define ledPin 13 // Пин для светодиода #define setLedOnPin PB0 // Пин кнопки включения светодиода #define setLedOffPin PB1 // Пин кнопки выключения светодиода byte state = 0; byte stateON = 0; byte stateOFF = 0; void setup() { pinMode(ledPin, OUTPUT); PCICR |= (1 << PCIE0); PCMSK0 |= (1 << PCINT0) | (1 << PCINT1); } ISR(PCINT0_vect) { if (~PINB & (1 << PB0) && stateON == 0) { //если кн.ON нажата state = 1; stateON = 1; } if (PINB & (1 << PB0) && stateON == 1) { //если кн.ON отпущена state = 1; stateON = 0; } if (~PINB & (1 << PB1) && stateOFF == 0) { //если кн.OFF нажата state = 0; stateOFF = 1; } if (PINB & (1 << PB1) && stateOFF == 1) { //если кн.OFF отпущена state = 0; stateOFF = 0; } } void loop() { digitalWrite(ledPin, state); }https://wokwi.com/projects/341701690170278484
https://wokwi.com/projects/341701690170278484
так наглядней
А я тоже заметил, что иногда работает и без volatile. Но бывает и не работает без этого параметра. Не знаю почему, что-то на что-то влияет в реальных «камнях». Поэтому в прерываниях глобальные всегда так «обзываю».
Так в том то и дело, что совершенно валидный в других ситуациях код без волатиля в прерывании может(может!) работать неверно. А может верно.
Если я не прав, придет Влад и обзовет меня дураком. Но пока его нет, я на коне.
До сих пор я думал, что если в "простом" коде, без прикреплённых файлов (до них пока не дошёл) переменная объявлена как глобальная, то этого достаточно, её везде будет видно. Всегда так делал и проблем не было, но, видимо всё ещё впереди))
Если нет volatile, то компилятор упрощает проверки в основном цикле скетча, если там нет явного изменения этой переменной. Что бы дать ему понять, что переменная может измениться где то ещё и при каждой проверке надо заново считывать значение - ставиться volatile.
bool x = true; ISR{ x = false } void loop() { while(x) { // этот цикл может не завершиться после отработки ISR, потому что оптимизатор не знает, что переменная может измениться вне текущего потока выполнения, // а значит будет читать значение из регистра процессора, а не из основной оперативки // volatile сигнализурует, что это может произойти, так что компилятор каждый раз будет запрашивать переменную из оперативки } }Волатиль запрещает компилятору слишком увлекаться оптимизацией переменных. А паттерны оптимизаций предугадать простому хоббисту не дано. Поэтому на каком-то -O все ок, а на другом - переменная меняется на константу и рантайм идёт по... Чтобы баги были везде и всегда одинаковые - ставь волатиль.
Спасибо #26 #27 #28 за разъяснения век живи, век учись.
А я тоже заметил, что иногда работает и без volatile. Но бывает и не работает без этого параметра. Не знаю почему, что-то на что-то влияет в реальных «камнях». Поэтому в прерываниях глобальные всегда так «обзываю».
волатильная в озу, неволатильная в регистрах
волатильная в озу, неволатильная в регистрах
так не катит
А я тоже заметил, что иногда работает и без volatile. Но бывает и не работает без этого параметра. Не знаю почему, что-то на что-то влияет в реальных «камнях». Поэтому в прерываниях глобальные всегда так «обзываю».
Если между двумя обращениями к указанной переменной ее значение может сохраниться в регистре, могут быть и проблемы. Если же такое невозможно, проблем не будет.
В любом случае, можно дизассемблировать сгенеренный код, и понять, возможны ли проблемы в данном конкретном случае.
До сих пор я думал, что если в "простом" коде, без прикреплённых файлов (до них пока не дошёл) переменная объявлена как глобальная, то этого достаточно, её везде будет видно. Всегда так делал и проблем не было, но, видимо всё ещё впереди))
Видимость и волатильность - понятия ортогональные.
Даже и представить себе не мог, что, как объясняет rkit, оптимизатор, "подлым образом", вместо обращения к глобальной переменной по адресу в памяти, может воспользоваться её копией ,сохранённой ранее в регистре.
Надеюсь, если присвоить переменной квалификатор volatile, уже всё будет как задумано, без подводных камней, т.к. неопределённость как-то не очень нравится
т.к. неопределённость как-то не очень нравится
что называется флаг в руки - пиши на ассемблере )))
Видимость и волатильность - понятия ортогональные.
Даже и представить себе не мог, что, как объясняет rkit, оптимизатор, "подлым образом", вместо обращения к глобальной переменной по адресу в памяти, может воспользоваться её копией ,сохранённой ранее в регистре.
Надеюсь, если присвоить переменной квалификатор volatile, уже всё будет как задумано, без подводных камней, т.к. неопределённость как-то не очень нравится
2. volatile лишь ограничивает оптимизацию, не решая других проблем. Для остального, как правило, вводят понятие атомарно исполняемых блоков.
Другими словами, все средства языка следует применять осознанно, а не надеяться, что утановивив квалификаторы "по максимуму", мы сразу избавимся от всех проблем.
Надеюсь, если присвоить переменной квалификатор volatile, уже всё будет как задумано, без подводных камней, т.к. неопределённость как-то не очень нравится
Во-вторых, останется немало других подводных камней и неопределённостей.
Во-вторых, останется немало других подводных камней и неопределённостей.
"нет ребята, всё не так, всё не так ребята" )))
Во-вторых, останется немало других подводных камней и неопределённостей.
"нет ребята, всё не так, всё не так ребята" )))
»Миша все х#йня, давай по новой.»?)))
все средства языка следует применять осознанно, а не надеяться, что утановивив квалификаторы "по максимуму", мы сразу избавимся от всех проблем.
Спасибо за разъяснения,, буду разбираться
Проверил.
Код из #8 работает без нареканий и без изменений !!!
У ТС видимо картинка c UNO для рисования схем, а не модель для Proteus !
Подтверждаю, так работает, а почему-же с нано не идет? Другие скетчи работают на этой модели. Я может не на те ноги завел?
зы
Похоже в модели косяк, сейчас переделал на уно и тоже самое, не работает. Я уже не помню где модели нано и уно брал, поделитесь плиз рабочими.
Подтверждаю. Не работает на этой модели Протеуса! Это случается.( "Никому нельзя верить!"
Я беру встроенные модели AVR/328P. Ничего не добавлял отдельно.
Иногда приходится людям показывать красивую картинку.) Но даже "чистые" модели МК (тини13, 85) работают отлично от железа на режимах со sleep-ом, WDT...
Как специально, в подтверждение вышесказанных слов.
Только что, написал программку для работы с АЦП. Скомпилил на Ардуино IDE - не пашет, хотя смотрю, там нечему "не пахать". Перекинул в Протеус, скомпилировал в ARDUINO AVR - работает, но при этом выдаёт :
# warning "Compiler optimizations disabled;"
Добавил в счётчик volatile - и заработало и в Ардуино IDE!
Так что удобно уметь временно отключать оптимизацию для проверки(пока не знаю как) или использовать два компилятора с разными установками
Так что удобно уметь временно отключать оптимизацию для проверки(пока не знаю как) или использовать два компилятора с разными установками
наш коллега Владимир неплохо все озвучил )))
А ник какой? Как то всё накручено. Тут тебе и пины, и тут же PB, и state, и oldPINB... Ужос. И заради чего?
Так что удобно уметь временно отключать оптимизацию для проверки(пока не знаю как) или использовать два компилятора с разными установками
Зачем всюду совать RP2040, если речь совсем не о нем?
Спасибо, но у меня так))
Варианты отключения оптимизатора нагуглил,(напр. редактировать файл platform.txt) но мне проще в Протеусе посмотреть, т.к. на постоянно отключать не планирую, только для проверки
Можно создать файл(ы) plaform.local.txt (и boards.local.txt) и перекрыть опции оригинальных файлов.