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

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

Пн апр 01, 2019 20:31:33

Dimon456 писал(а):если программа завершилась корректно, то должно быть возвращено значение 1
если вы сумеете объяснить, куда именно должно быть возвращено значение в микроконтроллере, то я съем свою собственную шляпу :)

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

Пн апр 01, 2019 21:26:03

Вот фрагмент кода, отвечающий за редактирование текущего времени
Спойлер//Редактирование текущего значения часов
if (menu == 100 && fConf) {
hour = EditHour(hour, button); //сохраняем значение часов
// Преобразуем из двоичной системы в BCD и записываем в DS1307
temp = ((hour / 10) << 4) | (hour % 10);
DS1307Write(0x02, temp);
_delay_ms(1);
}
//Редактирование текущего значения минут
if (menu == 101 && fConf) {
minute = EditMinute(minute, button); //сохраняем значение минут
// Преобразуем из двоичной системы в BCD и записываем в DS1307
temp = ((minute / 10) << 4) | (minute % 10);
DS1307Write(0x01, temp);
_delay_ms(1);
}

А вот фрагмент кода, отвечающий за редактирование параметров таймеров, относящийся к таймеру 1
Спойлерif (fConf) {
//Настройка таймера t1
if (menu == 11000) {
time[0].on_hour = EditHour(time[0].on_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_hour, time[0].on_hour);
}
if (menu == 11001) {
time[0].on_min = EditMinute(time[0].on_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_min, time[0].on_min);
}
if (menu == 11010) {
time[0].off_hour = EditHour(time[0].off_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_hour, time[0].off_hour);
}
if (menu == 11011) {
time[0].off_min = EditMinute(time[0].off_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_min, time[0].off_min);
}
if (menu == 1102) {
if (button == BTN_SHRT_RIGHT) {
if (time[0].work == 0) time[0].work = 1;
}

if (button == BTN_SHRT_LEFT) {
if (time[0].work == 1) time[0].work = 0;
}
if (eeprom_is_ready())
eeprom_update_byte(&t[0].work, time[0].work);
}

Этот код повторяется 4 раза. Логичней было бы сделать его функцией или циклом. Но из-за того что разные значения пунктов меню, приходится для каждого таймера повторять кусок кода
кстати, что-то ваш проект в протеусе ничего не высвечивает на индикаторе...

В протеус в настройках микроконтроллера указан файл прошивки? А то у меня после перезапуска протеус приходится ручками указывать путь к файлу timer.elf

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

Вт апр 02, 2019 06:54:32

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

логика меню должна быть какой-то такой
Код:
МЕНЮ
   1. ПУНКТ1 - ФУНКЦИЯ1
   2. ПУНТК2 - ФУНКЦИЯ2
   3. ПУНТК3 - ФУНКЦИЯ3
то есть когда выбран нужный пункт сразу вызывается нужная функция и внутри этой функции уже ничего проверять не надо.

возможен и чуть другой подход
Код:
МЕНЮ
   1. ПУНКТ1 - КОД1
   2. ПУНТК2 - КОД2
   3. ПУНТК3 - КОД3

//обработка меню
char get_menu(menu M);

switch (get_menu(МЕНЮ)){
   case КОД1: func1(); break;
   case КОД2: func2(); break;
   case КОД3: func3(); break;
}
то есть функция "навигации по меню" возвращает код выбранного пункта, и по этому коду вызывается нужная функция. можно впридачу этой функции передавать в виде параметра номер пункта меню, если уж так хочется...

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

Добавлено after 8 minutes 58 seconds:
что касается редактирования времени, то я понимаю так, что у вас должна быть функция "редактирование числа", которая в параметрах получает указатель на байт и байт-ограничитель значения, а возвращает true, если число изменено или false, если была "отмена ввода". пусть эта функция называется bool edit_int(char *data; char max);
время у вас хранится в структуре time { char hour; char minute;}
значит, чтобы отредактировать эту структуру (пусть на неё указывает указатель T), вы всего-навсего должны вызвать два раза функцию edit_int:
Код:
if(edit_int(&T.hour, 24) && edit_int(&T.minute, 60)){
...
}
настройки таймера у вас фактически состоят из двух времен - времени включения и времени выключения, значит, чтобы отредактировать настройки таймера, надо вызвать edit_int 4 раза...

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

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

Вт апр 02, 2019 08:15:29

ARV писал(а):
Dimon456 писал(а):если программа завершилась корректно, то должно быть возвращено значение 1
если вы сумеете объяснить, куда именно должно быть возвращено значение в микроконтроллере, то я съем свою собственную шляпу :)
А я не утверждаю что должно быть что то возвращено.
Изначально вопрос был
Dimon456 писал(а):А за чем в конце основного кода
Код:
return 0;
Анализируя asm-файл
Спойлер
Код:
 while (1)
  {

   Read_DS1307(temp);
     938:   89 81          ldd   r24, Y+1   ; 0x01
     93a:   e8 dc          rcall   .-1584      ; 0x30c <Read_DS1307>
.
.
.
.
    //Вызываем функцию мигания секундной точкой
    IND_BlinkSecond();
    117a:   93 d1          rcall   .+806       ; 0x14a2 <IND_BlinkSecond>

  }
    117c:   dd cb          rjmp   .-2118      ; 0x938 <main+0x1d4>
ни какого там ret нету, в общем команду return 0; я не нашел, и если это причуда компилятора....
melandr писал(а):В протеус в настройках микроконтроллера указан файл прошивки? А то у меня после перезапуска протеус приходится ручками указывать путь к файлу timer.elf
Вы нам другой протеус дали, возможно и другой проект.

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

Вт апр 02, 2019 09:49:16

Роман, у меня так и реализовано. Как во втором, указанном Вами подходе. функция "навигации по меню" возвращает код выбранного пункта, и по этому коду происходит отображение названия пункта меню или параметра. Но дальше интересней. Для того, чтобы отредактировать какой-либо параметр, я отметил пункты меню, имеющие возможность редактирования и дальше через if изменяю уже в другом месте
Спойлерif (fConf) {
//Настройка таймера t1
if (menu == 11000) {
time[0].on_hour = EditHour(time[0].on_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_hour, time[0].on_hour);
}
if (menu == 11001) {
time[0].on_min = EditMinute(time[0].on_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].on_min, time[0].on_min);
}
if (menu == 11010) {
time[0].off_hour = EditHour(time[0].off_hour, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_hour, time[0].off_hour);
}
if (menu == 11011) {
time[0].off_min = EditMinute(time[0].off_min, button);
if (eeprom_is_ready())
eeprom_update_byte(&t[0].off_min, time[0].off_min);
}
if (menu == 1102) {
if (button == BTN_SHRT_RIGHT) {
if (time[0].work == 0) time[0].work = 1;
}

if (button == BTN_SHRT_LEFT) {
if (time[0].work == 1) time[0].work = 0;
}
if (eeprom_is_ready())
eeprom_update_byte(&t[0].work, time[0].work);

Возможно код, который я выше привел необходимо поместить в конструкцию switch/case которая выводит на индикатор в функции fDisplaybutton(menu);
Просто делал все по примеру, но видать пример не слишком удачный. Либо я что-то не понял.

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

Вт апр 02, 2019 09:54:09

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

не знаю, где пошло все наперекосяк

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

Вт апр 02, 2019 10:38:24

Завтык происходит в коде, где происходит редактирование параметров. то есть по предложенному Вами принципу реализации меню Вывод пунктов меню так и происходит. Возможно стоит в функцию вывода на экран добавить и функции редактирования параметров, там где это необходимо. Так как я в конструкции switch_case только делаю вывод на индикатор требуемой строки или переменной. А все действия, осуществляемые в меню (как то редактирование) делаются в в основном цикле ниже. Как-то так.

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

Вт апр 02, 2019 11:01:49

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

я бы делал так.

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

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

сделал бы функции вывода "текста" и "времени", которые просто выводили в экранную оласть соответствующие "символы".

систему меню сделал бы так. в массиве хранил бы "текст", отображаемый на индикаторе.

логика функции навигации по меню заключалась бы в том, что брался бы очередной элемент массива "имен" пунктов, и выводился при помощи той функции, о которой писал ранее, затем ожидался бы ввод кнопки. свитчем по коду кнопки менял бы либо номер пункта меню (индкс массива), либо вызывал бы функцию "редактирования" времени.

все время (включая текущее), хранил бы в массиве. поэтому при нажатии Enter номер текущего индекса меню сразу бы соответствовал номеру структуры в массиве времен, что позволло бы его редактировать путем передачи в функцию единственного "индекса".

редактирование делал бы в цикле: сначала вывод времени, затем установка мерцающих разрядов, затем опрос кнопки и изменение.

как-то так... мне кажется, при реализации описанного алгоритма просто не должно возникать ваших проблем с кодом...

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

Вт апр 02, 2019 13:15:46

Роман, доходчиво объяснили. Извините, что я Вас так дотошно достаю. Но хотелось бы этот вопрос довести до логического завершения.
Теперь по Вашим пунктам. Сам понимаю, что у меня быдлокод. Потому и хочу его причесать да и для себя разобраться.
ARV писал(а):индикацию сделал бы, как я делал её всегда: массив байт по числу индикаторов - экранная область. по прерыванию идет вывод этой экранной области на реальные индикаторы.

Библиотека по такому принципу и работает. Правда я в нее подописывал функции вывода времени, часов и минут. Возможно вывод можно было сделать одной функцией, добавив в нее какой-нибудь параметр, который указывал бы на принадлежность выводимых значений. Но я не допер как так красиво сделать, потому сделал как смог. но оно работает.
ARV писал(а):дополнительно к экранной обалсти массив признаков мерцания - если в этом массиве индикатор помечен, то он мерцает. мерцание в том делается в том же прерывании путем пропуска "отмеченного" индикатора втечение определенного количества циклов обновления.

в библиотеке семисегментного индикатора эта опция есть, работает нормально
ARV писал(а):таким образом, процесс вывода заключается в обновлении сордержимого экранной области и пометки мигающих позиций, если надо.

в моем коде так и реализовано
ARV писал(а):сделал бы функции вывода "текста" и "времени", которые просто выводили в экранную оласть соответствующие "символы".

выше уже написал, что в библиотеке есть функции вывода числовых значений и строк.
ARV писал(а):систему меню сделал бы так. в массиве хранил бы "текст", отображаемый на индикаторе.

Вот здесь хотелось бы поподробней. У меня есть переменная - указатель на массив строк.
Спойлерchar* str[] = { "coLc", "Fnoc", "ruoh", "ninn", // cloc conF hour min
"1t", "2t", "3t", "4t", // t1 t2 t3 t4
"no1t", "Fo1t", "no2t", "Fo2t", // t1on t1of t2on t2of
"no3t", "Fo3t", "no4t", "Fo4t", // t3on t3of t4on t4of
"FFo", "no" // off on
};

Так как вывод осуществляется справа налево в индикатор, все названия меню развернуты. Вы подразумеваете под системой меню именно логическую последовательность, или просто все используемые надписи к меню. Потому как у меня самих используемых строк 18, но некоторые строки используются по несколько раз в разных разделах меню.
ARV писал(а):логика функции навигации по меню заключалась бы в том, что брался бы очередной элемент массива "имен" пунктов, и выводился при помощи той функции, о которой писал ранее, затем ожидался бы ввод кнопки. свитчем по коду кнопки менял бы либо номер пункта меню (индкс массива), либо вызывал бы функцию "редактирования" времени.

Вот сделал функцию
Спойлер//Функция получения кода меню в зависимости от кода нажатой кнопки
unsigned int MenuGet(char btn)
{
unsigned int keyMenu;
//если нажата кнопка OK
if (btn == BTN_SHRT_OK)
{
if (!buttonEdit)
keyMenu *= 10;
}
//если нажата кнопка LEFT
if (btn == BTN_SHRT_LEFT)
{
if (!fConf) keyMenu--;
//сбрасываю бит 6 - значит последняя операция была -
MDCR &= 0b10111111;
}
//если нажата кнопка RIGHT
if (btn == BTN_SHRT_RIGHT)
{
if (!fConf) keyMenu++;
//выставляю бит 6 в единицу, - значит последняя операция была +
MDCR |= 0b01000000;
}
//если нажата кнопка ESC
if (btn == BTN_SHRT_ESC)
{
if (keyMenu >= 10 && !fConf)
{
keyMenu /= 10;
}
}
return keyMenu;
}

Считаете, лучше сделать через switch? В данном случае эта функция просто указывает какой пункт меню нужно вывести. но для того, чтобы получить по коду меню какой текст или данные следует вывести необходимо иметь массив, который бы четко сделал привязку кода меню к пунктам меню. плюс туда же можно добавить дополнительным признаком возможность редактирования
ARV писал(а):все время (включая текущее), хранил бы в массиве. поэтому при нажатии Enter номер текущего индекса меню сразу бы соответствовал номеру структуры в массиве времен, что позволло бы его редактировать путем передачи в функцию единственного "индекса".

то есть параметры таймеров хранить в одномерном массиве с шагом 5 (так как параметров по каждому таймеру 5) и обращаться к ним по индексу, не заморачиваясь со структурой

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

Вт апр 02, 2019 13:31:54

после того, как на все мои предложения вы отвечаете "это так и есть", я остаюсь в полных непонятках, откуда у вас возникает тупик :) если все так и есть, все должно быть просто и красиво... где-то есть нюансик, который я пока не вижу
melandr писал(а):не заморачиваясь со структурой
почему? массив структур тоже хорошо. это не принципиально, имхо. но я бы делал структурами, так понятнее по коду.
melandr писал(а):Вы подразумеваете под системой меню именно логическую последовательность, или просто все используемые надписи к меню. Потому как у меня самих используемых строк 18, но некоторые строки используются по несколько раз в разных разделах меню.
меню для вот подобных систем с ограниченными возможностями ввода-вывода не так просто сделать хорошо... я обычно всегда жертвую памятью и кодом ради удобства восприятия написанного.

в вашем случае не вижу причин не повторить несколько раз в массиве строк одно и то же, если это существенно упрощает остальной код, делая его прозрачнее.

еще, чистая вкусовщина: на 4 разрядах сообщение t1on воспринимается хуже, чем 1-on, имхо. t - выглядит уродливо на семи сегментах... а цифра однозначно ассоциируется с номером. уж всяко пользователь догадается, что речь о таймере, если хоть раз с "инструкцией" ознакомился :)

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

Вт апр 02, 2019 13:43:40

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

94НН03 С006Щ3НN3 П0К4ЗЫ8437, К4КN3 У9N8N73ЛЬНЫ3 83ЩN М0Ж37 93Л47Ь Н4Ш Р4ЗУМ!
8П3Ч47ЛЯЮЩN3 83ЩN! СН4Ч4Л4 Э70 6ЫЛ0 7РУ9Н0, Н0 С3ЙЧ4С Н4 Э70Й С7Р0К3 84Ш Р4ЗУМ ЧN7437 Э70 4870М47NЧ3СКN, Н3 З49УМЫ84ЯСЬ 06 Э70М. Г0Р9NСЬ.
ЛNШЬ 0ПР393Л3ННЫ3 ЛЮ9N М0ГУ7 ПР0ЧN747Ь Э70.

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

Вт апр 02, 2019 13:46:06

Starichok51 писал(а):с уродливостью буквы t я не соглашусь - она читается без проблем.
я и написал - чистая вкусовщина. мне не нравится...

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

Вт апр 02, 2019 14:36:10

и тем не менее, есть ситуации, когда приходится мириться с этой уродливостью. и не только для буквы t...

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

Вт апр 02, 2019 14:53:30

точно :(
гораздо хуже выглядят буквы, которые из-за их размеров/написания на 2 разряда размещать приходится...

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

Вт апр 02, 2019 15:24:14

Роман, а та ссылка, на Ваш проект таймера, выше по теме. Там меню реализовано по такому же принципу, как Вы указали
ARV писал(а):логика функции навигации по меню заключалась бы в том, что брался бы очередной элемент массива "имен" пунктов, и выводился при помощи той функции, о которой писал ранее, затем ожидался бы ввод кнопки. свитчем по коду кнопки менял бы либо номер пункта меню (индкс массива), либо вызывал бы функцию "редактирования" времени.

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

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

Вт апр 02, 2019 15:27:22

да я этих меню понаделал столько всяких, на разных принципах, что совершенно не помню, где какое...

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

Вт апр 02, 2019 15:33:28

Если не трудно какой-нибудь исходник на Си, не очень сложный со светодиодным индикатором, кнопками и немного периферии. Посмотреть реализацию. А то уже голова пухнет. получается общение на разных языках :) Вы рассказываете алгоритм, как правильней было бы сделать, а я не могу объяснить что меня не устраивает в моем коде и как это хотелось бы исправить. Если не жалко исходник, так сказать в образовательных целях :)

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

Вт апр 02, 2019 17:24:24

Сначала бы сыхемку....
А ужшш под оную и прожку продумать можно...
8)

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

Вт апр 02, 2019 18:30:25

светодиодный индикатор, кнопки и периферия не имеют никакого отношения к структуре и реализации меню.
обработка индикатора, кнопок и периферии - это отдельные программные блоки, в которые мы попадаем при выборе соответствующего пункта меню.

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

Вт апр 02, 2019 18:41:44

Сначала бы сыхемку....
А ужшш под оную и прожку продумать можно...
8)

Вот схема устройства.
Изображение
Starichok51 писал(а):светодиодный индикатор, кнопки и периферия не имеют никакого отношения к структуре и реализации меню.
обработка индикатора, кнопок и периферии - это отдельные программные блоки, в которые мы попадаем при выборе соответствующего пункта меню.

Как отвязать структуру и реализацию меню от используемых индикаторов, кнопок и периферии
ЗЫ: во вложении источник, по которому пытался сделать меню. Может нерпавильно сделал.
Вложения
Организация простого меню для МК.doc
(371.5 KiB) Скачиваний: 137
Ответить