Easyelectronics.ru

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

Часовой пояс: 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
Сообщения: 2599
Откуда: Русь, Новороссийск
В прерывании лучше не считать, а флаг ставить.
А уж в главном цикле всегда есть время флаги посчитать.

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


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

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

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


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

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: 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
Сообщения: 1128
Тогда тем более в прерывании это делать лучше и правильнее(если, конечно, нельзя аппаратно). Но нужно чтобы во всей остальной программе работа с этим портом была атомарной (например через 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
Сообщения: 1128
В обработчике не нужна, но если его не сможет перебить другой обработчик который тоже будет работать с 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
Сообщения: 1128
У Вас будут вложенные прерывания? И если будут - то там будет изменение состояния 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
Сообщения: 1128
Инструкции CBI/SBI до PORTB в Атмега328 дотягиваются, значит всё нормально, должно быть атомарно, т.е. без RMW всего PORTB. Но я бы посмотрел листинг в финальной версии и убедился что там везде CBI/SBI при работе с PORTB. Так, на всякий случай.
Кстати, для Меги328 инвертировать состояние выхода можно просто записью в PINB.


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

Зарегистрирован: 25 фев 2011, 18:45
Сообщения: 3534
Откуда: Новосибирск
Код:
   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
Сообщения: 1128
Нет, 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 часов


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

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

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

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