реклама на сайте
подробности

 
 
> Отслеживание нескольких событий по времени
SZ0
сообщение Mar 11 2009, 19:40
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 14-02-06
Пользователь №: 14 331



Не могу сообразить, как правильнее распределить программные ресурсы
(структурировать программу) при следующей задаче:

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

В прерывания хочу вынести отчёт времени, периодическое чтение RTC и естественно
опрос клавиш.

А как правильнее проводить сравение выставленных будильников с RTC? В основной
части программы или по периодическим прерываниям (например раз в 1 сек) и
выставляя флаги сработки реагировать в основной части программы?

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

Как можно обеспечить нахождение в режиме программирования устройства
(выставление) пользователем условий сработки для одного выхода и при этом
чтобы одновременно продолжалась работа и управление другими выходами?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
rezident
сообщение Mar 11 2009, 20:19
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Если не предполагается восстановление всех параметров работы после пропадания/появления питания и максимальный период отсчета времени не нужен более 1,5 месяцев, то для данной задачи RTC вообще не нужен. А нужен всего один таймер, работающий от кварцованной частоты и настроенный так, чтобы генерировать прерывания с периодом, с минимально требуемым разрешением. В АСУ и ТП редко когда требуются воздействия с длительностью менее 100мс. Но можно сделать период генерации прерываний даже 10мс или 1 мс. В прерывании от таймера нужно какую-то глобальную беззнаковую 32-х битную переменную целого типа инкрементировать на число равное периоду в единицах мс. Т.е. если период прерываний будет 100мс, то в каждом прерывании от таймера увеличиваем переменную счетчика тиков на число 100, при периоде 10мс - на число 10 и т.п. Таким образом в этой переменной будет храниться относительное время в единицах мс с периодом переполнения примерно 0xFFFFFFFF/(1000мс*60с*60мин*24ч*30дн)=1,65 месяца.
В main-е в "вечном цикле" пускай "крутится" две основные задачи, которые выполняются поочередно.
1. HUI (интерфейс пользователя)
2. управление выходами.
Первая задача обеспечивает взаимодействие с клавиатурой и дисплеем, а также редактирование значений переменных, определяющих параметры управления выходами (описание функций выходов). Клавиатуры и дисплея может и не быть, а все параметры могут загружаться через какой-либо интерфейс. Это не суть важно.
Вторая задача, в соответствии с описанием функций каждого выхода (нормально замкнут, нормально разомкнут, время на которое выход должен быть включен и т.п.) управляет ими. Для отсчета интервалов времени должна иметься для каждого выхода своя переменная "временнОй засечки" той же рамерности, что и переменная "миллисекундных тиков". Берем беззнаковую разность между значением глобальной переменной миллисекундных тиков и временной засечки и сравниваем с переменной из описания конкретного выхода. Если разность меньше, то переходим к следующему выходу. Если же разность "больше или равно", то выполняем действие с выходом в соответствии с его описанием (включить/выключить) и запоминаем новое значение "временнОй засечки" для данного выхода.
Это все, что требуется для данной задачи. Описание функций выходов нужно хранить в энергонезависимой памяти (EEPROM внутренней или внешней или во Flash). Если же нужно, чтобы прибор продолжал функционировать с отсчетом всех временных интервалов даже и при пропадании питания, либо нужны временные интервалы более 1,5 месяцев, только тогда нужна м/с RTC с резервным питанием.
Забыл еще уточнить, что обе основные задачи "общаются" через область глобальных переменных, в которые загружаются из энергонезависимой памяти при включении прибора описания функций выходов.
И второй момент. При считывании значения переменной миллисекундных тиков нужно специальными методами обеспечить атомарность доступа к ней, если архитектура МК не обеспечивает этого условия (разрядность МК меньше 32-х бит).
Go to the top of the page
 
+Quote Post
SZ0
сообщение Mar 11 2009, 21:02
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 14-02-06
Пользователь №: 14 331



Благодарю за столь развёрнутый ответ!

Делал систему, когда пользователь всё программирует и только потом происходит запуск. Но здесь пока не знаю как правильно "выкрутиться" с одновременным программированием и продолжением работы. Наверное нужно запоминать номер меню/блока который обрабатывается в режиме программирования, и при каждом последовательном проходе заходить в него и выполнять соответствующие действия пользователся?
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 11 2009, 21:42
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(SZ0 @ Mar 12 2009, 02:02) *
Наверное нужно запоминать номер меню/блока который обрабатывается в режиме программирования, и при каждом последовательном проходе заходить в него и выполнять соответствующие действия пользователся?
Т.е. проблема все-таки лишь с организацией меню? Это не так сложно как кажется. Допустим нам нужно простейшее трехуровневое меню при четырехкнопочной клавиатуре (кнопки: вверх, вниз, ввод, отмена).
1-й уровень. Основной. Сюда пользователь попадает сразу после включения прибора. Ему соответствует индекс меню - 0.
2-й уровень. Выбор номера редактируемого параметра. Ему соответствует индекс меню - 1.
3-й уровень. Редактирование значение выбранного параметра. Ему соответствует индекс меню - 2.
Вызывается функция меню. По текущему индексу переходим к соответствующей ветке.
а) Вначале индекс 0 - вызываем 1-й уровень, где, например, отображаем состояния выходов и ждем нажатия кнопок. Т.е. при вызове по индексу 0 (в Си это можно оператором switch оформить) вызываем функцию отображения переменной и проверяем наличие в буфере клавиатуры скан-кодов. Если скан-код имеется, то извлекаем его из буфера, меняем индекс меню - 1 и выходим из функции меню. Проверка делается всего один раз.
б) В следующий раз при вызове функции меню по индексу 1 попадаем уже во второй уровень. Где отображаем число номера параметра и м.б. сопровождающую надпись (типа "параметр N"). Проверяем наличие в буфере клавиатуры скан-кода клавиши. Если есть скан-код, то извлекаем его из буфера и проверяем на совпадение с кодами клавиш. Если "вниз", то уменьшаем (проверяя на выход за границу допустимых значений, т.е. если уже равно нулю, то НЕ уменьшаем) значение переменной номера параметра. Если "вверх", то увеличиваем (если равно максимальному номеру, то НЕ увеличиваем) величину переменной номера параметра. Если "ввод", то увеличиваем индекс меню на число 2. Если "отмена", то уменьшаем индекс меню на число 1. Проверка делается всего один раз и после этого выходим из функции меню.
в) В следующий заход попадаем опять по индексу меню. Если в предыдущий раз клавиши не нажимались, то индекс не менялся и все то же самое, что в п.б. Если индекс изменился и стал 0, то происходит все то же, что в п.а. Если же попали в третий уровень, то отображаем локальную копию значения параметра, номер которого был выбран на предыдущем вызове функции меню. И опять проверяем буфер клавиатуры. Если имеются скан-коды "вверх" или "вниз", то соответственно увеличиваем или уменьшаем на заданный шаг (совсем не обязательно именно на 1 изменять) локальной копии значения параметра. Если код "ввод", то сохраняем значение локальной копии параметра (той, что редактировали) в переменную из которой копировали это значение, уменьшаем индекс меню на 1. Если же код клавиши "отмена", то НЕ сохраняя значения, уменьшаем индекс меню на 1. Выходим из функции меню.
В общих чертах как-то так. Основная суть в том, что НЕ нужно постоянно находится в функции меню. Вошли в нее, перешли по индексу на соответствующий уровень, если нужно, то отобразили что-то, проверили нажатие клавиши, если в буфере был код клавиши, то выполнили требуемое действие и вышли из функции меню. Все!
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th July 2025 - 01:49
Рейтинг@Mail.ru


Страница сгенерированна за 0.01396 секунд с 7
ELECTRONIX ©2004-2016