Если у меня в программе по какой-то причине главный цикл будет зависать, я смогу дописать вывод вспомогательной инфы на индикатор, и так отловить проблему. В вашем варианте всегда будет светиться один из сегментов, и то, если повезет, отладочный вывод в вашем варианте уже невозможен. Но, повторяю: каждый имеет право на веревку достаточной длины, чтобы выстрелить себе в ногу... Я не посягаю на это священное право!
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Ну это же ваши проблемы.) А у меня свои. И не надо про верёвку, вроде как вы учитель.) Я, конечно, прислушиваюсь, но каждый сам находит что для себя оптимально.
Добавлено after 5 hours 14 minutes 43 seconds: Вспомнил, однако, когда мне пришлось делать динамическую индикацию в основном цикле... Когда я делал собственную реализацию ScopeClock... из-за очень больших задержек на вход-выход от прерываний для этого пришлось отказаться, и весь векторный кадр пришлось рисовать в главном цикле при запрещенных прерываниях...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Ну если уже подходить к вопросу принципиально, то главный цикл может быть привязан к какому то "системному таймеру" и молотить строго через определенные интервалы времени. Тогда динамическую индикацию можно дергать и в основном цикле (при условии, что все подзадачи укладываются в период цикла) Я встречала и противоположный подход - в основной программе только инициализация периферии. И все. А вся логика - в прерывании таймера. В принципе, оба подхода имеют право на жизнь. Но программа может стать сложночитаемой, когда одна большая простыня кода.
ARV, Если все задачи главного цикла выполняются заведомо быстрее периода систика, то джиттер будет в несколько тактов. Просто обновление дисплея нужно поставить в самом начале суперцикла. При частоте систика в 1-2-4 кГц - эти несколько тактов заметны не будут. Но тогда нужно думать и дробить задачи. Так как даже запись в ЕЕПРОМ с блокирующим ожиданием флага готовности может все поломать. Поэтому мой подход обычно - все тайминго-критичное ( динамическая индикация, отслеживание каких то периферийных процессов, критичных ко времени и т.д.; туда же обычно и кнопки уходят) - оно живет отдельно, в прерывании систика, со своими конечными автоматами, невидимыми из суперцикла. А в самом суперцикле - отслеживание флагов от периферии, а для вывода - заполнение видеопамяти. Тогда можно себя не ограничивать в редких "долгоиграющих" задачах типа записи в ЕЕПРОМ. Где то кто то писал (может даже и вы) - все медленное, отвечающее за работу с внешним миром - в основной программе, все критичное ко времени - на прерываниях. И взаимодействие с основным миром - через флаги.
OKF писал(а):
Именно так. Никаких простыней.)
У меня так не получается ))) Поскольку любое состояние устройства - это как отдельный режим/подрежим. И вся логика тут же дробится на кучку switch(mode) {}.... внутри суперцикла Часть этих свичей уходят в функции.... Но в суперцикле у меня остается минимум два свича по режимам - один - это таймаут текущего режима и переход к следующему, второй - это загрузка/перезагрузка таймаута для текущего режима. Спойлер
while (1) {// super loop uint8_t ticks; do ticks = getSysClockInterval(); while(!ticks);
//---------- переменные на один раз modeType newMode = mode; uint8_t reloadTimeOut = 0;
//---------- exec peripherial
//---------- Timeout if ( mode == newMode && modeTimeOut ) { modeTimeOut--; if ( !modeTimeOut) { switch (newMode) { case mtInit: //newMode = mtShowTime; break; } // switch newmode } // if ( !modeTimeOut) } // if modeTimeOut
//---------- New or Reload timeout if (mode != newMode) reloadTimeOut = 1;
if (reloadTimeOut) { switch (newMode) { case mtInit: modeTimeOut = 1; break; } // switch newmode } // if reloadTimeOut
//---------- Mode change if (mode != newMode) { mode = newMode; } // if (mode != newMode)
} // while (1) - super loop
}
Зачастую еще в суперцикле живет обработчик нажатий на кнопки. Мне так удобнее.
Хотя в последнее время мне больше нравится концепция событий от периферии и от программных таймеров. Тогда программа дробится на вагон мелких обработчиков событий.
Всё так, пока в главном цикле код линейный, либо пока из-за прерываний джиттер systick не станет неприемлемым
Код заведомо короче системного периода. Джиттера нет, потому что нет прерываний. И я не агитирую за индикацию в основном цикле, но зачастую так проще. Там же и кнопки и всё остальное. Конечно это для простых конструкций. Да, и отладочный вывод на тот же индикатор почему не возможен? Это же быстро всё.
Кто-нибудь может сказать. avr-gcc при работе с eeprom библиотечными функциями из eeprom.h (типа eeprom_update_byte() и т.п.) сам запрещает прерывания на время обновления? Что-то я задумался, посмотрел ассемблерный код и не могу сообразить, давно асмом не пользовался, а там все понамешано.... Вроде cli есть, а восстановление предыдущего состояния не вижу. Хотя программы всегда работали без вопросов.
ks0, обычно сначала куда то сохраняется SREG, потом CLI, потом защищенный блок и потом восстановление SREG - тогда вернется состояние запрета прерываний как было до входа в защищенный блок. И вроде как eeprom_update_byte() не запрещает прерывания, там тупой блокирующий цикл ожидания готовности...
Сейчас этот форум просматривают: Google [Bot] и гости: 10
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения