|
Редактирование строки на ЖКИ., Ввод времени в RTC |
|
|
|
Dec 14 2007, 16:53
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Простая, казалось бы на первый взгляд задача... Но вот уже вторые сутки ломаю голову. Не могу придумать как это лучше сделать. Хочу, как в мобильном телефоне настраивать время. Вот мой кусок кода: Код void EditTime_Func(void) { unsigned char temp; rtc_get_time(0x99); //значение времени в yr, mn, dt, dy, hr, min, sec ClearScreen(); // display clear GotoXY(0,0); sprintf_P(lcd_buf,"%d/%d/%d %d %02d:%02d:%02d", yr, mn, dt, dy, hr, min, sec); PutStr(lcd_buf); w=CharWidth(*plcd_buf)-2; start_Timer(TIMER_0, 500, blink, TIMER_CYCLE);
for(;;) { temp=key_get(); switch(temp) //key_code.scan { case LEFT: //k_esc {......} break; case RIGHT: //k_enter {......} break; case DOWN: //k_left {......} break; case UP: //k_right {......} break; default: // 0...9 {......} break; } if(key_code.scan == LEFT) //выход из функции { stop_Timer(TIMER_0); break; } } }
//------------------------------------------------------------------------------ void blink(void) { InvertRect(x, y, w, 9); } Идея такая. Вывожу на экран значение времени в виде строки: "2007/12/24 1 12:32:00" Ф-ция start_Timer() запускает каждые 0,5 сек ф-цию blink(), которая в свою очередь инвертирует заданный прямоугольник. Т.е. должно мигать текущее знакоместо. Кнопками UP, DOWN выбираю следующее, предыдущее знакоместо. Ввод числа осуществляется с клавиатуры 4х4. Это все у меня работает. Проблема еще в том, что символы имеют переменную ширину. Поэтому после каждого ввода символа необходимо ,наверное, перерисовывать всю строку. После нажатия ENTER новые значения переменных необходимо записать в RTC. Как сделать ввод чисел только в заданные места, т.е. пропускать '/' , ' ' , ':' ? Меня не покидает чувство, что изобретаю велосипед.
|
|
|
|
|
 |
Ответов
|
Dec 14 2007, 20:32
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(rezident @ Dec 14 2007, 20:16)  Разделите логически в программе ввод, вывод и редактирование, а потом совместите их. Т.е. с помощью клавиатуры вы будете редактировать какую-то переменную время/дата. И эту же переменную выводить на экран после каждой модификации полностью. Не нужно будет ломать голову как совместить видимую позицию курсора и редактируемый символ. rezident дело говорит. "В одну корзину класть не можно на яйца сверху серп и молот" Всегда делаю различные процедуры для индикации и обработки клавиатуры. Логически эти процедуры связаны только через переменную MenuNumber, которая указывает на номер текущего меню (на тип информации, выводимой на дисплей). Обработчик клавиатуры верхнего уровня ServiceKeys в зависимости от значения MenuNumber и нажатых кнопок производит нужные действия, напр.: -выбор параметра для редактирования - перемещает мигающее поле на дисплее; -вход в режим изменения параметра - копирует выделенную переменную в буфер редактора; -изменение параметра - меняет переменную в буфере редактора; -выход из режима изменения параметра - сохраняет переменную; Процедура вывода на дисплей RedrawLCD вызывается раз в 1 сек и после обработки клавиатуры. Эта процедура по значению MenuNumber выводит на дисплей нужные параметры, беря их или напрямую, или из буфера редактора. Эта процедура и занимается преобразованием бинарных переменных в ASCII коды.
|
|
|
|
|
Dec 15 2007, 16:15
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(alux @ Dec 15 2007, 11:57)  Можете привести для наглядности свой код? Какой то конкретный код привести вряд ли смогу, это все ненаглядно и громоздко. Еще некоторые соображения по поводу вашего примера кода. Если вы не применяете RTOS и не запускаете эту процедуру как отдельную задачу, то у вас во время редактирования часов прибор ничего больше не делает (только прерывания). Я применяю несколько другой метод организации обработки клавиатуры и дисплея, который без RTOS обеспечивает выполнение алгоритмов кусками, отдельными состояниями конечного автомата (по сути это работа по флагам). Общая структура следующая: - Один таймер выделяется под системный, который обеспечивает регулярное прерывание, в котором выставляется флаг f10ms_Past. - Этот флаг обрабатывается в основном цикле main, где формируются места, которые выполняются через равные промежутки: 10 мс, 1 сек, другие необходимые. Код //--------------------------------------------------------------// // 10 milliseconds, One and Ten seconds Procedures // //--------------------------------------------------------------// if (f10ms_Past) // 10 ms past { f10ms_Past = 0; ReadKeys(); RunADC(); Task1_Service(); Task2_Service(); ................... if (++TenMilliSecCnt >= 100) // 1 second past { TenMilliSecCnt = 0; poGreenLED ^= 1; // Toggle green LED RedrawLCD(); // Redraw LCD module .................... if (++SecCnt >= 10) // 10 seconds past { SecCnt = 0; ................. } } } //--------------------------------------------------------------// // Keys service Conditions Determination // //--------------------------------------------------------------// if (fShortKey || fLongKey) { ServiceKey(); RedrawLCD(); } ..................... - Каждые 10 мс выполняется процедура ReadKeys(); которая является драйвером клавиатуры нижнего уровня и занимается сканированием кнопок, обработкой дребезга, распознает длительность нажатия, автоповтор и т.д. Результат ее работы - значения регистров статуса и флаги нажатия. - Обработчик клавиатуры верхнего уровня ServiceKeys(); вызывается по наличию флагов. Его работу я уже описал. - Про функцию вывода на дисплей я уже тоже писал. Важное замечание: вся эта структура будет хорошо работать только в том случае, если обеспечивается, что время работы любой функции не превышает 10 мс и хотя бы раз за 10 мс выполняется главный цикл. Но я обычно пишу так, что это условие всегда выполняется.
|
|
|
|
|
Dec 15 2007, 20:28
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Baser @ Dec 15 2007, 21:15)  - Один таймер выделяется под системный, который обеспечивает регулярное прерывание, в котором выставляется флаг f10ms_Past. А я делаю более логично. В "тиковом" прерывании инкрементирую переменную на величину периода "тика". Получается, что ее значение является временной меткой, выраженной в миллисекундах. 16-и битной переменной хватает для отсчета интервала времени больше минуты, а 32-х битная переменная переполняется только через почти полтора месяца. Цитата(Baser @ Dec 15 2007, 21:15)  Важное замечание: вся эта структура будет хорошо работать только в том случае, если обеспечивается, что время работы любой функции не превышает 10 мс и хотя бы раз за 10 мс выполняется главный цикл. Но я обычно пишу так, что это условие всегда выполняется. Если имеется упомянутая мной выше переменная "миллисекундных тиков", то нет необходимости так строго выдерживать период "суперцикла". Ограничивать период выполнения суперцикла приходится лишь в том, случае в его теле вычисляется, например, управляющее воздействие, которое должно быть обязательно выдано за определенный промежуток времени. Если же вернуться к теме топика, то при наличии ресурсов в ОЗУ формируется буфер экрана и все изменения, определяемые функциями меню, делаются в нем. Затем весь буфер одной функцией выводится на экран. При необходимости для ускорения вывода можно пропускать элементы изображения, которые не изменились за текущий цикл, а выводить на экран только изменения. Клавиатура у меня обычно тоже имеет свой буфер в который помещаются заранее определенные коды клавиш. Обрабатываются кнопки, устраняется дребезг, формируются коды клавиш и заполняется буфер в том же самом "тиковом"прерывании.
|
|
|
|
|
Dec 15 2007, 21:49
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(rezident @ Dec 15 2007, 22:28)  А я делаю более логично. В "тиковом" прерывании инкрементирую переменную на величину периода "тика". Получается, что ее значение является временной меткой, выраженной в миллисекундах. 16-и битной переменной хватает для отсчета интервала времени больше минуты, а 32-х битная переменная переполняется только через почти полтора месяца. При таком решении мне немного не понятно, как можно без дополнительных флагов обеспечивать выполнение периодических процедур главного цикла ОДИН раз за их номинальный период. МК в моменты простоя может все время крутиться в main и пролетать через них сотни раз за время одного "тика" прерывания. Цитата(rezident @ Dec 15 2007, 22:28)  Если имеется упомянутая мной выше переменная "миллисекундных тиков", то нет необходимости так строго выдерживать период "суперцикла". Ограничивать период выполнения суперцикла приходится лишь в том, случае в его теле вычисляется, например, управляющее воздействие, которое должно быть обязательно выдано за определенный промежуток времени. Ну, как показывает практика, даже пропадание 1-2-х 10 мс процедур никак не сказывается на нормальной обработке клавиатуры и дисплея. Дребезг то на уровне 50-70 мс, сами понимаете. Цитата(rezident @ Dec 15 2007, 22:28)  Клавиатура у меня обычно тоже имеет свой буфер в который помещаются заранее определенные коды клавиш. Обрабатываются кнопки, устраняется дребезг, формируются коды клавиш и заполняется буфер в том же самом "тиковом" прерывании. В первых своих работах я тоже делал обработку клавиатуры в прерывании, а потом перестал, потому что нету смысла: обработка неспешная и нечего ей занимать драгоценное время прерываний.
|
|
|
|
|
Dec 15 2007, 22:21
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Baser @ Dec 16 2007, 02:49)  При таком решении мне немного не понятно, как можно без дополнительных флагов обеспечивать выполнение периодических процедур главного цикла ОДИН раз за их номинальный период. МК в моменты простоя может все время крутиться в main и пролетать через них сотни раз за время одного "тика" прерывания. Дык у каждого процесса своя переменная заданного периода. Простым вычитанием двух беззнаковых переменных определяется закончился требуемый процессу интервал времени или еще нет. Код switch (mnuFlag) { case MNU_LEVEL1: mnu_time=tickTime; //фиксируем отметку времени mnuFlag=MNU_LEVEL2; break; case MNU_LEVEL2: if ((tickTime-mnu_time)<5000) break; //ждем окончания интервала времени 5сек else { ... mnuFlag=MNU_LEVEL3; } break; case MNU_LEVEL3: ... .... } Цитата(Baser @ Dec 16 2007, 02:49)  Ну, как показывает практика, даже пропадание 1-2-х 10 мс процедур никак не сказывается на нормальной обработке клавиатуры и дисплея. Ну да, со скоростью 100 раз в секунду ни одна супер-пупер-машинистка долбить по клаве не сможет. Цитата(Baser @ Dec 16 2007, 02:49)  Дребезг то на уровне 50-70 мс, сами понимаете. Это довольно плохие контакты. Я не припомню, чтобы мы применяли кнопки у которых дребезг превышал 10мс. Обычно не более единиц мс. Цитата(Baser @ Dec 16 2007, 02:49)  В первых своих работах я тоже делал обработку клавиатуры в прерывании, а потом перестал, потому что нету смысла: обработка неспешная и нечего ей занимать драгоценное время прерываний. Хозяин-барин. Все от задачи зависит. Некоторые задачи вообще полностью в "тиковом" прерывании выполняются (исключая конечно же начальную инициализацию).
|
|
|
|
Сообщений в этой теме
alux Редактирование строки на ЖКИ. Dec 14 2007, 16:53 SasaVitebsk Я реализовывал такую задачу. Правда на ассемблере ... Dec 14 2007, 17:27 Сергей Борщ Цитата(alux @ Dec 14 2007, 18:53) Проблем... Dec 16 2007, 10:01 alux Цитата(Сергей Борщ @ Dec 16 2007, 14:01) ... Dec 16 2007, 11:47  SasaVitebsk Цитата(alux @ Dec 16 2007, 15:47) В каких... Dec 16 2007, 15:23   alux Цитата(SasaVitebsk @ Dec 16 2007, 19:23) ... Dec 16 2007, 15:51 zltigo Цитата(Сергей Борщ @ Dec 16 2007, 12:01) ... Dec 16 2007, 11:55  alux Цитата(zltigo @ Dec 16 2007, 15:55) Все э... Dec 16 2007, 13:09 SasaVitebsk Тоже делаю временные метки.
Сейчас сделаю отдельну... Dec 16 2007, 10:50 rezident Дык алгоритм-то редактирования простейший.
1 урове... Dec 16 2007, 12:16 alux Цитата(rezident @ Dec 14 2007, 22:16) Раз... Dec 16 2007, 12:47  rezident Цитата(alux @ Dec 16 2007, 17:39) Не вижу... Dec 16 2007, 12:52  zltigo Цитата(alux @ Dec 16 2007, 14:47) А можно... Dec 16 2007, 13:13   alux Если не жалко, выложите код. Dec 16 2007, 13:26    zltigo Цитата(alux @ Dec 16 2007, 15:26) Если не... Dec 16 2007, 13:41 Baser Цитата(rezident @ Dec 16 2007, 00:21) Дык... Dec 16 2007, 18:03 alux Цитата(Baser @ Dec 16 2007, 22:03) Может ... Dec 16 2007, 18:24  SasaVitebsk Цитата(alux @ Dec 16 2007, 22:24) В начал... Dec 16 2007, 19:40   alux Цитата(SasaVitebsk @ Dec 16 2007, 23:40) ... Dec 17 2007, 08:07  Baser Цитата(alux @ Dec 16 2007, 20:24) В начал... Dec 16 2007, 19:48 SasaVitebsk Вы можете добавить ещё один фонт состоящий только ... Dec 17 2007, 16:50 alux При выводе на экран строки, например шрифтом 7х10,... Dec 18 2007, 19:41 SasaVitebsk А какой у вас дисплей/контроллер? Dec 18 2007, 20:20 alux MT12864J ks0108
Добавлено
Простите за тупой воп... Dec 18 2007, 21:26 Сергей Борщ Цитата(alux @ Dec 18 2007, 23:26) А если ... Dec 19 2007, 19:21 SasaVitebsk Примерный смысл дойдёт из конструкции.
Код maska =... Dec 19 2007, 15:50
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|