Easyelectronics.ru

Электроника для всех
Текущее время: 22 апр 2019, 03:35

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 42 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 13 июл 2017, 23:13 
Старожил
Аватара пользователя

Зарегистрирован: 23 янв 2012, 00:31
Сообщения: 1797
Откуда: Новокузнецк
TSV писал(а):
Это счётчик тиков в обработчике прерывания по переполнению аппаратного счётчика.
Красиво, кратко, компилятор молчит, но что-то не работает, Мега вообще не запускается после прошивки.
По-простому конечно нужно так if (i < 100) {i++;},
но в этом ли косяк пока не могу проверить, идея только сейчас пришла, до проверки смогу добраться только через 2-3 дня.

Самый главный вопрос: зачем вообще так делать? Неочевидные конструкции только вред приносят

_________________
elisey.su


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 11:16 
Заглядывает иногда

Зарегистрирован: 16 сен 2016, 11:21
Сообщения: 198
elisey писал(а):
Самый главный вопрос: зачем вообще так делать? Неочевидные конструкции только вред приносят
Да просто хотелось выпендриться самому перед собой. Типа - так круче.
Всё, вопрос снят и вообще основная проблема была не в этом – оперативку пытался использовать на 330% по недомыслию. Но хорошо, что эта мелочь отловилась до устранения главной причины, а то ищи потом этот косяк, когда в принципе работает, но как-то не так.

P.S. У меня такая штука в другом месте в принципе работала, как ни странно, в таком же счётчике и тоже в прерывании – серийная могралка светодиодом была сделана, длина серии считалась в таком счётчике. Теперь понимаю, почему там небольшой непринципиальный косячок был.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 11:39 
Старожил
Аватара пользователя

Зарегистрирован: 14 июн 2015, 17:41
Сообщения: 2411
Откуда: Русь, Новороссийск
В прерывании лучше не считать, а флаг ставить.
А уж в главном цикле всегда есть время флаги посчитать.

(это я теперь такой умный стал :) )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 12:17 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2767
У себя в прерывании подсчет шагов ШД вполне себе живет следующая конструкция:
Код:
   if (StepMotorData[Motor].StepLeft)
   {
      if(!(--StepMotorData[Motor].StepLeft))
      {
                      // все досчитали
      }
   }

Никакого криминала не вижу.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 12:55 
Старожил
Аватара пользователя

Зарегистрирован: 18 апр 2017, 03:01
Сообщения: 916
Если по каким-то причинам важно не пропускать счёт (особенно если период между прерываниями маленький), то лучше считать в прерывании и там же ставить флаг при досчёте до нужного значения. Тоже не вижу криминала, главное при этом не делать в прерывании каких-нибудь глупостей...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 14:22 
Заглядывает иногда

Зарегистрирован: 16 сен 2016, 11:21
Сообщения: 198
h4lf писал(а):
Если по каким-то причинам важно не пропускать счёт (особенно если период между прерываниями маленький), то лучше считать в прерывании и там же ставить флаг при досчёте до нужного значения. Тоже не вижу криминала, главное при этом не делать в прерывании каких-нибудь глупостей...
Именно тот случай, только не флаг ставится, а бит порта инвертируется прямо в прерывании.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 17:13 
Старожил
Аватара пользователя

Зарегистрирован: 18 апр 2017, 03:01
Сообщения: 916
Тогда тем более в прерывании это делать лучше и правильнее(если, конечно, нельзя аппаратно). Но нужно чтобы во всей остальной программе работа с этим портом была атомарной (например через BSRR или бит-как-там-его в STM32 или запрещать прерывания на время RMW).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 17:42 
Заглядывает иногда

Зарегистрирован: 16 сен 2016, 11:21
Сообщения: 198
h4lf писал(а):
Тогда тем более в прерывании это делать лучше и правильнее(если, конечно, нельзя аппаратно). Но нужно чтобы во всей остальной программе работа с этим портом была атомарной (например через BSRR или бит-как-там-его в STM32 или запрещать прерывания на время RMW).
Не понял, почему? Я же только один бит в порту меняю PORTB ^= _BV(LED_PIN_NUM). Что эквивалентно PORTB ^= (1<< LED_PIN_NUM). Зачем атомарность?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 18:28 
Старожил
Аватара пользователя

Зарегистрирован: 18 апр 2017, 03:01
Сообщения: 916
В обработчике не нужна, но если его не сможет перебить другой обработчик который тоже будет работать с PORTB.
А вот в остальной программе при работе с PORTB нужна. Попробую объяснить на примере. Допустим основная программа работает с другим пином PORTB через RMW вот так:
Код:
PORTB |= _BW(PIN2);
что на ассемблере будет как минимум три команды (при RMW):
1. прочитать PORTB
2. изменить бит PIN2
3. записать обратно в PORTB
А вот теперь представьте, что ваше прерывание, которое тоже работает с PORTB, произойдёт между инструкциями 1 и 3. В этом случае Ваш бит LED_PIN_NUM который в PORTB в прерывании инвертируется (примет новое значение), но по возвращению из прерывания в PORTB запишется старое значение бита LED_PIN_NUM, которое было до прерывания. Это потому, что в инструкциях 1 и 3 читается и записывается состояние всего порта, а не отдельного бита и между ними может произойти прерывание. Примерно то же может быть и с глобальными переменными, которые используются в прерываниях. Да, это будет редкая и трудноуловимая ошибка (гейзенбаг).

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 19:13 
Заглядывает иногда

Зарегистрирован: 16 сен 2016, 11:21
Сообщения: 198
h4lf писал(а):
В обработчике не нужна, но если его не сможет перебить другой обработчик который тоже будет работать с PORTB.
А вот в остальной программе при работе с PORTB нужна.
Существенно. В данном случае неактуально, но для спокойствия рекомендуете сделать так?
Код:
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ PORTB ^= _BV(LED_PIN_NUM)}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 14 июл 2017, 20:55 
Старожил
Аватара пользователя

Зарегистрирован: 18 апр 2017, 03:01
Сообщения: 916
У Вас будут вложенные прерывания? И если будут - то там будет изменение состояния PORTB? если нет, то в обработчике прерывания это не имеет смысла и не нужно. Лучше смотрите всю остальную программу, где может быть изменение состояния порта через RMW. И глобальные переменные, задействованные в прерываниях, особенно те, что больше 8 бит, если на 8 битном МК. Какой хоть МК используется?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 15 июл 2017, 00:47 
Заглядывает иногда

Зарегистрирован: 16 сен 2016, 11:21
Сообщения: 198
h4lf писал(а):
У Вас будут вложенные прерывания? И если будут - то там будет изменение состояния PORTB? если нет, то в обработчике прерывания это не имеет смысла и не нужно. Лучше смотрите всю остальную программу, где может быть изменение состояния порта через RMW. И глобальные переменные, задействованные в прерываниях, особенно те, что больше 8 бит, если на 8 битном МК. Какой хоть МК используется?
Вложенных не будет. Пока. А вообще на этом же порту ещё кнопка меню и 1-Wire линия с программным интерфейсом. Мега 328.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 15 июл 2017, 01:33 
Старожил
Аватара пользователя

Зарегистрирован: 18 апр 2017, 03:01
Сообщения: 916
Инструкции CBI/SBI до PORTB в Атмега328 дотягиваются, значит всё нормально, должно быть атомарно, т.е. без RMW всего PORTB. Но я бы посмотрел листинг в финальной версии и убедился что там везде CBI/SBI при работе с PORTB. Так, на всякий случай.
Кстати, для Меги328 инвертировать состояние выхода можно просто записью в PINB.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 15 июл 2017, 12:14 
Старожил

Зарегистрирован: 25 фев 2011, 18:45
Сообщения: 3488
Откуда: Новосибирск
Код:
   if (++sample >= SAMPLES)
   {
      meter_off ();
      measure_complete = true;
   }


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 16 июл 2017, 01:55 
Заглядывает иногда

Зарегистрирован: 16 сен 2016, 11:21
Сообщения: 198
h4lf писал(а):
Кстати, для Меги328 инвертировать состояние выхода можно просто записью в PINB.
Т.е. PINB |= _BV(MY_PIN_NUM) даст 1 на MY_PIN_NUM в PORTB?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 16 июл 2017, 02:05 
Старожил
Аватара пользователя

Зарегистрирован: 18 апр 2017, 03:01
Сообщения: 916
Нет, PINB = _BV(MY_PIN_NUM) инвертирует MY_PIN_NUM если он настроен как выход.
из DS:
Цитата:
14.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the
SBI instruction can be used to toggle one single bit in a port.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Можно ли делать так if (i++ < 100) {;} ?
СообщениеДобавлено: 17 июл 2017, 13:49 
Заглядывает иногда

Зарегистрирован: 16 сен 2016, 11:21
Сообщения: 198
h4lf писал(а):
Нет, PINB = _BV(MY_PIN_NUM) инвертирует MY_PIN_NUM если он настроен как выход.
Упссс, вот это номер!!! Учту, спасибо. Я пока только познаю этот мир, поэтому иду стандартными привычными способами, описанными в книжках.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 42 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot]


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB