Страница 5 из 5

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

Добавлено: Вт апр 02, 2019 19:46:39
ARV
вы знаете... я вас почти подвел. оказалось, все свои старые проекты с 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
melandr
Спасибки, буду разбираться. Кстати смотрел Ваш проект "Таймер - меньше просто не бывает" так и не понял все зависимости хидеров и исходников. Есть файл micro-timer.c и файл main.c Но нигде не нашел подключение исходного файла display-new.c

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

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

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

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

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

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

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

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

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

Добавлено: Чт апр 04, 2019 14:19:57
Starichok51
ну, если писать на Си, то может atmega8 окажется маловата. а на ассемблере будет даже с хорошим запасом.

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

Добавлено: Чт апр 04, 2019 14:23:21
ARV
:facepalm:

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

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

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

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