- Лоботрясы

Поиск
Перейти к контенту

Главное меню:

Статьи по AVR

Читать в Яндекс.Подписках



     Имитация аналоговых часов на дисплее
Просмотров: 1861
     И снова Бонжорно! На этот раз приведу очередной пример на LCD дисплее от одного из телефонов Siemens (ну что поделать! удалось когда-то достать их дофига и больше, так что не обессудьте :-) 
     С момента моего увлечения микроконтроллерами у меня уже накопилась тысяча и одна коробочка проектов, в которых я пытаюсь не забыть, что я там делал вообще, попеременно прыгая с одного на другой, при этом пытаясь по силе возможности (времени, настроения, котировок доллара, положения планет и т.д. и т.п.) продвигать их далее. Одним из таких старых проектов являлся проект аналоговых часов (точнее - псевдоаналоговых на жидкокристаллическом дисплее), идея о котором появилась у меня ещё полтора-два года назад, и, к настоящему времени, потихоньку сошла на нет ;-) Но это не касается программных наработок, которые в дальнейшем я планирую применить в каком-нибудь очередном цифровом устройстве в режиме меню или в качестве красивой заставки.
     Принцип построения часовых и минутных аналоговых стрелок я приводить не буду, т.к. об этом хорошо написано в одной их моих предыдущих статей - Формирование стрелки на дисплее. Поэтому для начала (и для интриги) приведу фото - подтверждение работоспособности программного кода, а потом займусь подробным описанием китайской письменности на языке С.
     Если ещё интересно, тогда продолжаю делиться информацией. Пример кода, представленный ниже, заточен под компилятор CodeVisionAVR  а с другими под микроконтроллеры AVR я и не работаю. Так вот... В качестве подопытного кролика опять был применён дисплей LPH9135, но нам ведь главное - принцип, правда?
     Говорю сразу - задача ставилась только в получении на LCD (TFT, OLED) дисплее от мобильного телефона часовой и минутной стрелок, имитирующих поведение аналоговых часов. Изображение аналоговых часов было скачано где-то в мусорных просторах интернета, преобразовано в 8-ми битную палитру через программу Image2Lcd и записано во flash-память микроконтроллера, а потом, естественно, оттуда выведено на дисплей (каким образом - опять отсылаю к одной из своих статей по дисплеям - LPH9135, поищите :-) Но даже если у вас на руках дисплей от иного безвременно ушедшего карманного друга, поняв принцип построения аналоговых стрелок, его легко можно реализовать и на другом дисплее с иной библиотекой функций. Но применение своей библиотеки, рассчитанной на микроконтроллеры AVR, внесло свои нюансы по поводу реализации процедуры обновления стрелок - из-за малой тактовой частоты микроконтроллера (ну, не STM32, увы!) и небольшой скорости ввода данных по интерфейсу SPI в дисплей, пришлось отказаться от полной очистки дисплея и новой прорисовки стрелок (т.к. это происходило ну оччень медленно!). Очистка происходит таким образом: при изображении очередных значений часов и минут в виде стрелок, эти значения запоминаются, и при последующем обращении к функции рисования стрелок эти предыдущие значения (положения) стрелок окрашиваются в цвет фона, после чего происходит построение стрелок на новом месте. Как возьмусь за дисплей с 8-ми (или 16-ти) битным интерфейсом, обязательно (в сочетании с STM32) изменю данный метод в построении стрелок в сторону большей скорости и практичности. А пока представлю получившиеся функции в их нынешнем виде (функции обеспечивают только вывод часовой и минутной стрелок, а секундную вы можете добавить сами по аналогии!).

Для работы этих функций нужно обязательно добавить в начале проекта библиотеку:

#include <math.h> //Подключаем стандартную библиотеку математических функций CVAVR
//**********************************************************
//                   Функция для отрисовки стрелки
//**********************************************************
// x1,y1 - центр (ось вращения) стрелки; value - числовое значение от 0 до 59; len - длина стрелки (в пикселях);
// width - ширина стрелки (в пикселях); color - цвет стрелки
void hand_clock (char x1, char y1, char value, char len, char width, int color)
     unsigned char x2, y2, shift_x, shift_y;
     unsigned int a; // Угол

     a = (int)((360/60)*value); //Определяем угол, соответствующий значению value
     //Смещение по оси х и y относительно начала стрелки (центра циферблата), т.е. определяем проекцию стрелки на ось х и y
     shift_x = len * sin(a * 3.14 / 180.0); //Предварительно переводим угол из градусов в радианы
     shift_y = len * cos(a * 3.14 / 180.0);
     //Определяем координату конца стрелки
     x2=x1+shift_x;
     y2=y1-shift_y;
     LCD_FillLine (x1, y1, x2, y2, width, color); //Рисуем линию от начала до конца стрелки
}

//**********************************************************
//           Функция для вывода часовой и минутной стрелки
//**********************************************************
// x1,y1 - центр (ось вращения) стрелки; hour - число от 0 до 23; minute - число от 0 до 59; LenHourHand, LenMinHand - соответственно длина часовой и 
// минутной стрелки; WidthHourHand и WidthMinHand - соответственно ширина часовой и минутной стрелки; ColHourHand и ColMinHand -
// соответственно цвет часовой и минутной стрелки; b_color - цвет фона
void display_hand_clock (char x1, char y1, char hour, char minute, char LenHourHand, char LenMinHand, char WidthHourHand, char WidthMinHand, int ColHourHand, int ColMinHand, int b_color)
{
     static bit flag=0; //Флаг, разрешающий после первого вывода стрелки стирать её предыдущее положение
     static unsigned char last_hour=0, last_minute=0;
     hour%=12; //Получаем число от 0 до 11
     hour*=5; //Между отметками часов на циферблате - 5 делений
     if(minute>=12&&minute<24)   hour+=1;
     if(minute>=24&&minute<36)   hour+=2;
     if(minute>=36&&minute<48)   hour+=3;
     if(minute>=48&&minute<60)   hour+=4;
     if(flag)
     { //Окрашиваем предыдущее положение стрелки под цвет фона
          hand_clock (x1, y1, last_hour, LenHourHand, WidthHourHand, b_color);
          hand_clock (x1, y1, last_minute, LenMinHand, WidthMinHand, b_color);
     }
     last_hour=hour; last_minute=minute; //Запоминаем новое положение конца стрелки
     flag=1;
     hand_clock (x1, y1, hour, LenHourHand, WidthHourHand, ColHourHand); // Рисуем часовую стрелку
     hand_clock (x1, y1, minute, LenMinHand, WidthMinHand, ColMinHand); // Рисуем минутную стрелку
}
//**********************************************************
     При изображении часовой стрелки учитывалось её положение относительно минутной стрелки, видео работы показывать не вижу смысла (вы чего, часов не видели?), поэтому поверьте на слово - работа псевдоаналоговых часов практически идентична живым. 

Опубликовано 10.01.2015
©Igoryosha, 2015
 
 
Назад к содержимому | Назад к главному меню