Простой вопрос, а ставит меня в тупик :)

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

https://www.youtube.com/watch?v=AT0CXtchKoA

Суть такая, есть устройство которое рапортует о своем состоянии логическими уровнями на выходах, всего выводов 6, мне надо в зависимости от состояний этих уровней выводить на индикацию (lcd1602) определенный текст. Я для этой цели заказал MH-Tiny, думаю справится. С самим индикатором проблем нет, разобрался как работает.  Как мне правильно организовать считывание кодов? Хочу чтобы как-то по прерываниям, чтобы атинька засыпала когда нет изменений на входах. Дайте направление куда копать? 

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

PCINT

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

ua6em, спасибо!

А есть ли в природе симулятор ардуино? Ну вот как в протеусе можно скомпилировать проект и не загружая его посмотреть как логика работает. У меня еще ардуинка не доехала, хочется проверить как будет скетч работать, виртуально.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Proteus

wokwi.com

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016
b707
Offline
Зарегистрирован: 26.05.2017

Delta213 пишет:

ua6em, спасибо!

А есть ли в природе симулятор ардуино? Ну вот как в протеусе можно скомпилировать проект и не загружая его посмотреть как логика работает. У меня еще ардуинка не доехала, хочется проверить как будет скетч работать, виртуально.

так в том же протеусе и ардуину можно

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

До чего дошел прогресс :) Парни, всем спасибо, изучаю и пробую, пока больше нет вопросов.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Delta213 пишет:

До чего дошел прогресс :) Парни, всем спасибо, изучаю и пробую, пока больше нет вопросов.

ты обращайся ежели что )))

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

Обращаюсь! Пытаюсь освоить прерывания, нашел в сети этот скетч:


#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);
}

В протеусе собрал и не работает, не пойму в чем причина, то-ли в протеусе (хотя другие скетчи работают), то-ли в коде, помогите разобраться.

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

В шестой строке:

volatile uint8_t oldPINB = 0xFF;

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Не вижу разрешение прерываний sei().

Green
Offline
Зарегистрирован: 01.10.2015

У Ардуино они уже разрешены. 

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

BOOM пишет:

В шестой строке:

volatile uint8_t oldPINB = 0xFF;

Это насколько я понял маска с которой сравнивается состояние пинов, вернее их изменение. Как это может влиять?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Delta213 пишет:

BOOM пишет:

В шестой строке:

volatile uint8_t oldPINB = 0xFF;

Как это может влиять?

Значение этой переменной меняется в прерывании.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

наш коллега Владимир неплохо все озвучил )))

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

ua6em пишет:

наш коллега Владимир неплохо все озвучил )))

Так я от туда и взял скетч, но не работает :(

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

[/quote]

Значение этой переменной меняется в прерывании.

[/quote]

Ну да, но начальное значение FF, оно и так FF пины ведь подтянуты.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Delta213 пишет:

ua6em пишет:

наш коллега Владимир неплохо все озвучил )))

Так я от туда и взял скетч, но не работает :(

так я к тому и сказал, его детище, должен и ответ держать )))

b707
Offline
Зарегистрирован: 26.05.2017

Delta213 пишет:

Ну да, но начальное значение FF, оно и так FF пины ведь подтянуты.

начальное возможно, но потом-то оно меняется

У меня сомнение - вы понимаете, зачем вообще пишут "volatile" в таких случаях?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Проверил.

Код из #8 работает без нареканий и без изменений !!!

У ТС видимо картинка c UNO для рисования схем, а не модель для Proteus !

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Komandir пишет:

Код из #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);
}


 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016
BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А я тоже заметил, что иногда работает и без volatile. Но бывает и не работает без этого параметра. Не знаю почему, что-то на что-то влияет в реальных «камнях». Поэтому в прерываниях глобальные всегда так «обзываю».

b707
Offline
Зарегистрирован: 26.05.2017

Так в том то и дело, что совершенно валидный в других ситуациях код без волатиля в прерывании может(может!) работать неверно. А может верно.

Если я не прав, придет Влад и обзовет меня дураком. Но пока его нет, я на коне.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

b707 пишет:
Так в том то и дело, что совершенно валидный в других ситуациях код без волатиля в прерывании может(может!) работать неверно. А может верно.

 До сих пор я думал, что если в "простом" коде, без прикреплённых файлов (до них пока не дошёл) переменная объявлена как глобальная, то этого достаточно, её везде будет видно. Всегда так делал и проблем не было, но, видимо всё ещё впереди))

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Если нет volatile, то компилятор упрощает проверки в основном цикле скетча, если там нет явного изменения этой переменной. Что бы дать ему понять, что переменная может измениться где то ещё и при каждой проверке надо заново считывать значение - ставиться volatile.

rkit
Offline
Зарегистрирован: 23.11.2016
bool x = true;

ISR{
  x = false
}

void loop() {
  while(x) {
    // этот цикл может не завершиться после отработки ISR, потому что оптимизатор не знает, что переменная может измениться вне текущего потока выполнения, 
    // а значит будет читать значение из регистра процессора, а не из основной оперативки
    // volatile сигнализурует, что это может произойти, так что компилятор каждый раз будет запрашивать переменную из оперативки
  }
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Волатиль запрещает компилятору слишком увлекаться оптимизацией переменных. А паттерны оптимизаций предугадать простому хоббисту не дано. Поэтому на каком-то -O все ок, а на другом - переменная меняется на константу и рантайм идёт по... Чтобы баги были везде и всегда одинаковые - ставь волатиль.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Спасибо #26 #27 #28 за разъяснения век живи, век учись.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

BOOM пишет:

А я тоже заметил, что иногда работает и без volatile. Но бывает и не работает без этого параметра. Не знаю почему, что-то на что-то влияет в реальных «камнях». Поэтому в прерываниях глобальные всегда так «обзываю».

волатильная в озу, неволатильная в регистрах

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

ua6em пишет:

волатильная в озу, неволатильная в регистрах

так не катит

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

BOOM пишет:

А я тоже заметил, что иногда работает и без volatile. Но бывает и не работает без этого параметра. Не знаю почему, что-то на что-то влияет в реальных «камнях». Поэтому в прерываниях глобальные всегда так «обзываю».

Это определяется не "камнем", а компилятором, точнее, его оптимизатором. 

Если между двумя обращениями к указанной переменной ее значение может сохраниться в регистре, могут быть и проблемы. Если же такое невозможно, проблем не будет.

В любом случае, можно дизассемблировать сгенеренный код, и понять, возможны ли проблемы в данном конкретном случае.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Дим-мычъ пишет:

 До сих пор я думал, что если в "простом" коде, без прикреплённых файлов (до них пока не дошёл) переменная объявлена как глобальная, то этого достаточно, её везде будет видно. Всегда так делал и проблем не было, но, видимо всё ещё впереди))

Видимость и волатильность - понятия ортогональные.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

andriano пишет:

 Видимость и волатильность - понятия ортогональные.

Даже и представить себе не мог, что, как объясняет rkit, оптимизатор, "подлым образом", вместо обращения к  глобальной переменной по адресу в памяти, может воспользоваться её копией ,сохранённой ранее в регистре.

Надеюсь, если присвоить переменной квалификатор volatile, уже всё будет как задумано, без подводных камней, т.к. неопределённость как-то не очень нравится

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Дим-мычъ пишет:

 т.к. неопределённость как-то не очень нравится

что называется флаг в руки - пиши на ассемблере )))

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Дим-мычъ пишет:

andriano пишет:

 Видимость и волатильность - понятия ортогональные.

Даже и представить себе не мог, что, как объясняет rkit, оптимизатор, "подлым образом", вместо обращения к  глобальной переменной по адресу в памяти, может воспользоваться её копией ,сохранённой ранее в регистре.

Надеюсь, если присвоить переменной квалификатор volatile, уже всё будет как задумано, без подводных камней, т.к. неопределённость как-то не очень нравится

1. Оптимизатор не допускает никакой неопределенности, гарантируя, что код после оптимизации будет приводить в точности к тем же результатам, что и без оптимизации. Естественно, это "в точности" имеет некоторые ограничения. Например то, что код после оптимизации будет выполняться быстрее (а разве не это цель оптимизации?), т.е. уже не совсем "в точности". Другое ограничение - используемые переменные в момент исполнения кода не должны меняться нигде за пределами этого кода. Именно для такого контроля и служит volatile. Но и ее во многих случаях оказывается недостаточно, например, в случае многобайтовых переменных.

2. volatile лишь ограничивает оптимизацию, не решая других проблем. Для остального, как правило, вводят понятие атомарно исполняемых блоков.

Другими словами, все средства языка следует применять осознанно, а не надеяться, что утановивив  квалификаторы "по максимуму", мы сразу избавимся от всех проблем.

SLKH
Offline
Зарегистрирован: 17.08.2015

Дим-мычъ пишет:

 

Надеюсь, если присвоить переменной квалификатор volatile, уже всё будет как задумано, без подводных камней, т.к. неопределённость как-то не очень нравится

Во-первых, в любом случае будет не "как задумано", а "как написано".

Во-вторых, останется немало других подводных камней и неопределённостей.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

SLKH пишет:

Во-вторых, останется немало других подводных камней и неопределённостей.

"нет ребята, всё не так, всё не так ребята" )))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

ua6em пишет:

SLKH пишет:

Во-вторых, останется немало других подводных камней и неопределённостей.

"нет ребята, всё не так, всё не так ребята" )))

»Миша все х#йня, давай по новой.»?)))

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

andriano пишет:

 все средства языка следует применять осознанно, а не надеяться, что утановивив  квалификаторы "по максимуму", мы сразу избавимся от всех проблем.

SLKH пишет:
Во-первых, в любом случае будет не "как задумано", а "как написано". Во-вторых, останется немало других подводных камней и неопределённостей.

 Спасибо за разъяснения,, буду разбираться

Delta213
Delta213 аватар
Offline
Зарегистрирован: 26.08.2022

Komandir пишет:

Проверил.

Код из #8 работает без нареканий и без изменений !!!

У ТС видимо картинка c UNO для рисования схем, а не модель для Proteus !

Подтверждаю, так работает, а почему-же с нано не идет? Другие скетчи работают на этой модели. Я может не на те ноги завел?

зы

Похоже в модели косяк, сейчас переделал на уно и тоже самое, не работает. Я уже не помню где модели нано и уно брал, поделитесь плиз рабочими.

Green
Offline
Зарегистрирован: 01.10.2015

Подтверждаю. Не работает на этой модели Протеуса! Это случается.( "Никому нельзя верить!"

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Я беру встроенные модели AVR/328P. Ничего не добавлял отдельно.

Green
Offline
Зарегистрирован: 01.10.2015

Иногда приходится людям показывать красивую картинку.) Но даже "чистые" модели МК (тини13, 85) работают отлично от железа на режимах со sleep-ом, WDT...

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

 Как специально, в подтверждение вышесказанных слов.

Только что, написал программку для работы с АЦП. Скомпилил на Ардуино IDE - не пашет, хотя смотрю, там нечему "не пахать". Перекинул в Протеус, скомпилировал в ARDUINO AVR - работает, но при этом выдаёт :

# warning "Compiler optimizations disabled;"

Добавил  в счётчик volatile - и заработало и в Ардуино IDE!

 Так что удобно  уметь временно отключать оптимизацию для проверки(пока не знаю как) или использовать два компилятора с разными установками

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Дим-мычъ пишет:

 Так что удобно  уметь временно отключать оптимизацию для проверки(пока не знаю как) или использовать два компилятора с разными установками

Green
Offline
Зарегистрирован: 01.10.2015

ua6em пишет:

наш коллега Владимир неплохо все озвучил )))


А ник какой? Как то всё накручено. Тут тебе и пины, и тут же PB, и state, и oldPINB... Ужос. И заради чего?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

Дим-мычъ пишет:

 Так что удобно  уметь временно отключать оптимизацию для проверки(пока не знаю как) или использовать два компилятора с разными установками

Написано же: "скомпилировал в ARDUINO AVR".

Зачем всюду совать RP2040, если речь совсем не о нем?

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

ua6em пишет:

Спасибо, но у меня так))

 Варианты отключения оптимизатора нагуглил,(напр. редактировать файл platform.txt) но  мне проще в Протеусе посмотреть, т.к. на постоянно отключать не планирую, только для проверки

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Можно создать файл(ы) plaform.local.txt (и boards.local.txt) и перекрыть опции оригинальных файлов.