Обсуждаем контроллеры компании Atmel.
Ответить

Re: AVR и светодиодный индикатор

Вт апр 02, 2019 19:46:39

вы знаете... я вас почти подвел. оказалось, все свои старые проекты с 7-сегментными индикаторами я делал тяп-ляп, стыдно показать... что поделать - 10 лет назад сам от вашего уровня не сильно отличался...


но я набросал код, который ДОЛЖЕН работать (хоть я его и не проверял). во всяком случае можете взять его в качестве идеи для развития или самостоятельной доводки до совершенства
Код:
/// структура элемента меню
typedef struct{
   uint8_t      data_id; // номер данных
   char      name[4]; // текст пункта меню
} menu_item_t;

/// массив пунктов меню
static menu_item_t menu[] = {
      {0, "CLOC"}, // настройка часов
      {1, "t1on"}, // далее настройки моментов времени 4-х таймеров
      {2, "t1of"},
      {3, "t2on"},
      {4, "t2of"},
      {5, "t3on"},
      {6, "t3of"},
      {7, "t4on"},
      {8, "t4of"}
};

/// структура записи времени
typedef struct{
   uint8_t hour;
   uint8_t min;
} time_t;

/// количество пунктов меню
#define MENU_CNT   (sizeof(menu) / sizeof(menu_item_t))

/// внешний массив с данными о времени
extern time_t time_array[];
/// внешняя функция вывода строки из 4 символов на экран
extern void str_to_screen(char str[4]);
/// внешняя функция вывода времени на экран
extern void time_to_scren(time_t *t);
/// внешняя функция включения мигания позиций на экране
/// позиции задается единичками в 4-х младших битах
extern void blink_scren(uint8_t pos);

/// прототип функции редактирования времени
bool edit_time(uint8_t id);

/// навигация по меню
bool menu_navigate(void){
   uint8_t item = 0;   // текущий пункт меню на экране
   uint8_t btn;      // код нажатой кнопки
   
   while(1){
      // выводим на экран название текущего пункта
      str_to_screen(menu[item].name);
      // ждем нажатия кнопки
      btn = get_button();
      // обработка кнопки
      switch(btn){
      case BTN_ENTER:
         // включаем редактирование времени
         if(edit_time(menu[item].data_id)) break;
         else return false;
      case BTN_ESCAPE:
         // выход (отмена меню)
         return false;
      case BTN_LEFT:
         // предыдущий пункт меню по кругу
         if(--item >= MENU_CNT) item = MENU_CNT-1;
         break;
      case BTN_RIGHT:
         // следующий пункт меню по кругу
         if(++item >= MENU_CNT) item = 0;
         break;
      }
   }
}

/// тип результата редактирования числа
typedef enum{
   EDIT_OK,   // редактирование закончено успешно
   EDIT_ESC,   // редактирование отменяется
   EDIT_CONT   // редактирование продолжается
} edit_result_t;

/**
 * редактирование числа с ограничением максимального значения
 * @param btn код нажатой кнопки
 * @param data указатель на однобайтное число
 * @param max верхняя граница допустимого значения (не пересекаемая)
 * @return результат редактирования
 */
edit_result_t edit_int(uint8_t btn, uint8_t *data, uint8_t max){
   switch(btn){
   case BTN_ENTER:
      // закончили редактиование
      return EDIT_OK;
   case BTN_ESCAPE:
      // отменили редактирование
      return EDIT_ESC;
   case BTN_LEFT:
      // уменьшаем число по кругу
      if(--(*data) >= max) *data = max-1;
      break;
   case BTN_RIGHT:
      // увеличиваем число по кругу
      if(++(*data) >= max) *data = 0;
      break;
   }
   // редактирование продожается
   return EDIT_CONT;
}

/**
 * редактирование времени из массива
 * @param id номер записи времени в массиве
 * @return если время отредактировано полностью - true
 */
bool edit_time(uint8_t id){
   edit_result_t cont = EDIT_CONT;   // флаг продолжения редактирования

   uint8_t tmp; // временное хранилище редактируемого числа
   
   // редактирование ЧАСОВ:
   // запоминаем текущее значение часов из указанного элемента массива
   // включаем мигание перых 2 позиций
   // цикл продолжается, пока результат равен EDIT_CONT
   for(tmp  = time_array[id].hour, blink_screen(0b00001100); cont == EDIT_CONT; cont = edit_int(get_button(), &time_array[id].hour, 24));
   // если вышли из цикла по отмене редактирования
   if(cont == EDIT_ESC){
      // восстановим прежнее значение часов
      time_array[id].hour = tmp;
      // выключаем мигание
      blink_screen(0);
      // вернем результат отмены
      return false;
   }
   
   // редактирвоание МИНУТ
   cont = EDIT_CONT;
   for(tmp  = time_array[id].min, blink_screen(0b00000011); cont == EDIT_CONT; cont = edit_int(get_button(), &time_array[id].min, 60));
   if(cont == EDIT_ESC){
      time_array[id].min = tmp;
      blink_screen(0);
      return false;
   }
   // если добарись до этого места - время отредактировано полностью
   // выключаем мигание
   blink_screen(0);
   // возвращаем результат успеха
   return true;
}


подсветка синтаксиса отсутствует, что, конечно, сильно подгаживает восприятие... но надеюсь, разберетесь. во всяком случае можете рассчитывать на мои пояснения, если что-то не понятно.

P.S. простите меня за циклы for... обычно я так не пишу...

Re: AVR и светодиодный индикатор

Вт апр 02, 2019 20:26:42

Спасибки, буду разбираться. Кстати смотрел Ваш проект "Таймер - меньше просто не бывает" так и не понял все зависимости хидеров и исходников. Есть файл micro-timer.c и файл main.c Но нигде не нашел подключение исходного файла display-new.c

Re: AVR и светодиодный индикатор

Чт апр 04, 2019 06:45:54

Собственно, как я понял, хотелось таймер-часики соорудить?
8)
Сразу замечание по схемотехнике - на один разъем выводить все те сигналя, что на схеме НЕ РЕКОМЕНДУЕТСЯ.
Сразу разделяем позиционные ключи, сегментные ключи и кнопы.
Особое внимание к шлейфу кнопок.
:write:
Поглядю со временем... чего на том калеченом 28-лапом корпусировании соорудить можно. С моего взгляда такой вариант нагрузок на 8-ю мегу весьма избыточен - вместе с путевым/легко воспринимаемым интерфейсом пользователя может и не влезть прожка - индикатор-то ВСЕГО ЛИШЬ 4-х позиционный...
Но... продолжать буду на своей ветке (https://radiokot.ru/forum/viewtopic.php?f=62&t=156720) - отвлекаться сложно...
Да и какая-то тренировка... Я б такую постановку задачи сразу же отбросил по причине ЛЕНИ и наличия готовых и удобных в схемотехническом плане изделий. В том числе и немаловажный фактор - корпусировка/разводка выводов кристалла МК.
Да и в подобном проекте ассемблер значительно удобнее...
Ну ужжшшш... "ежли хотимсс впихерить" - то придется извратом заняться.
:beer:

Re: AVR и светодиодный индикатор

Чт апр 04, 2019 06:54:20

BOB51 писал(а):то придется извратом заняться
вы, конечно, можете заниматься извратом сколько угодно, но проект подобного уровня влезет не только в мегу8, но и в attiny2313 на Си без маленйших извратов. а уж на меге8 можно просто вот вообще не париться.

Re: AVR и светодиодный индикатор

Чт апр 04, 2019 07:29:46

Для простого варианта часейков/таймерюг места и в тиньке 13-й достаточно.
Однако...
У нас 4 позиции в дисплее и 4 кнопы, что само по себе для устройства с несколькими внутренними одновременно функционирующими подустройствами маловато.
Когда-то впихивал и 16 независимых таймерюг в одну упаковку - но там же помимо 4-х позиционки были еще 8 двухцветных светиков (по одному на каждый таймер - настройка/счет/сработка - желтый/зеленый/красный) и 16-позиционная клавиатура с пищалкой (ну и ессно под ассемблером - тогда ешшо на бумаге компилировать приходилось). А тут ДВА календарных таймера и главные часы/календарь плюс режим ввода параметров одновременно могут быть востребованы. Да в качестве показаний или цифирь или "синтез-кракозябры"...
Следовательно система индикации текущего статуса и одновременно фоновых устройств будет весьма сложной задачей.
Да еще так, чтоб пользователю удобно было все это начинко ОДНОВРЕМЕННО воспринимать.
А пользователь в нашем случае весьма вредно-придирчивый (ЖОНА к примеру).
Наибольшие возможные проблемы именно в самой менюшке и сопутствующем управлении - а они во много больше места, чем собственно сам таймер занимать могут.
То я уж в своем монологе расставить попытаюсь (ежли удастся).
8)

Re: AVR и светодиодный индикатор

Чт апр 04, 2019 07:35:02

BOB51, при всем уважении: вы рассуждаете, как теоретик, только думающий о проблеме, а я - как практик, не единожды делавший подобное. я со всеми проблемами знаком не понаслышке, и могу смело утверждать, что atmega8 для описанного топикстертером проекта - более чем просторный МК.

Re: AVR и светодиодный индикатор

Чт апр 04, 2019 14:19:57

ну, если писать на Си, то может atmega8 окажется маловата. а на ассемблере будет даже с хорошим запасом.

Re: AVR и светодиодный индикатор

Чт апр 04, 2019 14:23:21

:facepalm:

Re: AVR и светодиодный индикатор

Чт апр 04, 2019 15:34:55

Starichok51, при все уважении, "маловато" или нет зависит, в первую очередь, от программиста, а не от того, на С он пишет или на ассемблере. При правильном использовании С (не исключающем ассемблерных вставок), за одно и то же время можно написать более компактный код, чем на ассемблере. Так как бОльшую часть времени удастся уделить оптимизации алгоритма и меньшую - его реализации в коде.
С другой стороны, студент для диплома может и на ассемблере такое понаписать, что без слез не взглянешь. Реализовывал один такой CORDIC для тригонометрических функций на ассемблере i386. Так родная функция из glibc, написанная на С, оказалась и быстрее, и короче :)))

Re: AVR и светодиодный индикатор

Пт апр 05, 2019 14:17:26

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