Меню на ATmega8

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 3
Зарегистрирован: Сб мар 23, 2013 09:47:06

Сообщение imusg »

Здравствуйте! Вот уже пару дней бъюсь над меню! Вот код:

Код: Выделить всё

#include <mega8.h>
#include <delay.h>
// I2C Bus functions
#include <i2c.h>

// Alphanumeric LCD functions
#include <alcd.h>

// Declare your global variables here
void menu1 (void) //Пункт вкл\выкл LED
{
int led=0;    // Переменная для определения состояния диода
lcd_clear();
lcd_gotoxy(2,0);
lcd_putsf("LED");
while(1)     // Проверка состояния диода 
{
if (led==0)
{
lcd_gotoxy(4,1);
lcd_putsf("OFF");
}
if (led==1)
{
lcd_gotoxy(4,1);
lcd_putsf("ON");
}
while(1)
{
if (PINC.5==0)
{
if (led==1)   // Если диод включон
{
PORTC.2=0;   // Выключаем
led=0;
lcd_clear();
lcd_gotoxy(2,0);
lcd_putsf("LED");
lcd_gotoxy(4,1);
lcd_putsf("OFF");
delay_ms(50);
break;      // Прерываем цикл
}
if (led==0)  // Если выключен
{
 PORTC.2=1;  // Включаем
led=1;
lcd_clear();
lcd_gotoxy(2,0);
lcd_putsf("LED");
lcd_gotoxy(4,1);
lcd_putsf("ON");
delay_ms(50);
break;         // Прерывание
}
}
}
if (PINC.3==0)break;  // Этим я хотеля вывести из функции в меню
 

}

}
void menu2 (void)  // Демо пункт
{
lcd_clear();
lcd_gotoxy(5,0);
lcd_putsf("PIN5");
}
void menu3 (void) // Дело пункт
{
lcd_clear();
lcd_gotoxy(5,0);
lcd_putsf("PIN3");

}

void main(void)
{
 int mn=1;    // переменная счёта меню

PORTB=0x00;
DDRB=0x00;

PORTC=0x38;
DDRC=0x07;

PORTD=0x00;
DDRD=0x00;

TCCR0=0x00;
TCNT0=0x00;

TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

MCUCR=0x00;

TIMSK=0x00;

UCSRB=0x00;

ACSR=0x80;
SFIOR=0x00;

ADCSRA=0x00;

SPCR=0x00;

TWCR=0x00;

i2c_init();

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 0
// RD - PORTB Bit 1
// EN - PORTB Bit 2
// D4 - PORTD Bit 4
// D5 - PORTD Bit 5
// D6 - PORTD Bit 6
// D7 - PORTD Bit 7
// Characters/line: 16
lcd_init(16);

lcd_gotoxy(0,0);
lcd_putsf("Welcome to");
delay_ms(700);
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("I'm Ready!!!");

 while (1)
      {
       if (PINC.4==0)  // Щелкаем вверх минусуем mn
       {
       mn--; 
       }    
       
       if (PINC.3==0) // Щелкаем вниз плюсуем mn
       {
       mn++;
       } 
       
       if (mn==2)  // Пункт диода
       { 
       lcd_clear();          //
       lcd_gotoxy(2,0);      //
        lcd_putsf("LED");    // Здесь отображаю Название пункта
        lcd_gotoxy(4,1);     //
        lcd_putsf("ON/OFF"); //
        while (1)        // Здесь если нужно войти ждем PC5, если нет, то вниз вверх
        {
       if (PINC.5==0)menu1();        
       if (PINC.4==0)mn--; 
       if (PINC.3==0)mn++;
       
        }
       }  
       
       if (mn==3)     // Демо пункт
       {
       lcd_clear();          //
       lcd_gotoxy(2,0);      // Отображаю название
        lcd_putsf("menu2") ; //
       if (PINC.5==0)  // Ждем 0 на PC5 если нужно войти
       {
        menu2();
        }
       }
       
       if (mn==0)
       {
       mn=1;
       }

      }


}

Проблемка что я не могу сообразить как сделать выход из функции menu1() и дальше щелкать меню! PC3 вниз, PC4 вверх, PC5 ОК, PC2 диод. Да и вообще комменты о софтинке послушать хочется! Может как то проще и сжатей можно сделать!
Вложения
lcd_menu.zip
(13.47 КБ) 223 скачивания
Последний раз редактировалось imusg Пт май 10, 2013 15:45:35, всего редактировалось 1 раз.
Реклама
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Сообщение Vov123 »

Ну если бы к проекту был присоединён файл протеуса,да и свою программу снабдили комментариями,людей участвующих в обсуждении будет немало.
Реклама
Прорезались зубы
Сообщения: 208
Зарегистрирован: Вс дек 10, 2006 19:26:13

Сообщение dm211 »

Кто-то где-то на этом форуме посоветовал вот такой принцип меню- http://avrproject.ru/publ/menu_on_a_mic ... r/1-1-0-33 ,с легкостью на си переделал, только такое меню использую теперь, очень удобно.
Потрогал лапой паяльник
Сообщения: 310
Зарегистрирован: Пт дек 17, 2010 14:41:25

Сообщение phenomen »

Вот: многоуровневое меню с обработчиком. Может понравиться...
Думаю доделать его не составит особого труда.
Критика приветствуется.
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 3
Зарегистрирован: Сб мар 23, 2013 09:47:06

Сообщение imusg »

dm211 писал(а):Кто-то где-то на этом форуме посоветовал вот такой принцип меню- http://avrproject.ru/publ/menu_on_a_mic ... r/1-1-0-33 ,с легкостью на си переделал, только такое меню использую теперь, очень удобно.

Спасибо за совет, но я в ассемблере зеро!
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

ТС, скорее всего все это уже видел (тема с меню неубиваемая) - и он просто не знает, с чего начать.
Начать, имхо, нужно с определения базового меню, например, в вашем случае оно мне видится таким

typedef struct
{
const char *txt; // текст текущего положения меню
struct menu *Up;// указатель на структуру меню при нажатии кнопки Up
struct menu *Down;// указатель на структуру меню при нажатии кнопки Down
void (*Func)(void); // функция, которая выполняется в текущем положении меню при нажатии кнопки ок
}menu;// определение структуры



Дальше - лист бумаги, который расчерчиваем на колонки и прописываем в них
номер ! Текст ! реакция на кнопку вниз ! реакция на кнопку вверх ! реакция на кнопку ок(вызов функции)
например
0 ! welcom ! pMenu[1] ! pMenu[10] ! 0
1 ! set Lamp ! pMenu[2] ! pMenu[0] |! fnSetLamp
2 ! clear Lamp!pMenu[3] ! pMenu[1] | fnClearLamp
и так далее
Если при нажатии клавиш ничего не происходит или функция выполняться не должна - ставим 0.
Когда все готово, переносим в реал
menu Menu[11]={\
{"welcom", &Menu[1],&Menu[10],0},
{"set Lamp", &Menu[2],&Menu[0],fnSetLamp},
{"clear Lamp",&Menu[3],&Menu[1],fnClearLamp},
и так далее

создаем указатель
struct menu *pMenu; // Указатель на активное меню
там же описываем функции
void fnSetLamp(void)


ну и описываем анализ кнопок
например
if(cButton == BUTTON_DOWN)
{
if(pMenu->Down)// если там стоит не 0
{
pMenu=pMenu->Down; // то спускаемся вниз
LCD_OUT(pMenu->txt); // выводим новую надпись


ну и при нажатии ОК вызываем функцию по указателю

if(cButton == BUTTON_OK)
{
if(pMenu->Func())
{
pMenu->Func(); // выполняем


Заранее предупреждаю, что сейчас могу что-то написать неверно, за чужим компом, но общее представление как бы дал.
Наверное. :)
Контактная информация:
Реклама
Потрогал лапой паяльник
Сообщения: 310
Зарегистрирован: Пт дек 17, 2010 14:41:25

Сообщение phenomen »

urry, Я похожее предложил вместе с куском кода.
Вот он с комментариями:
Спойлер

Код: Выделить всё

typedef char MENU_NAME[17];//максимум 16 символов + конец строки

typedef struct MENU_DEF
{
char* name;//указатель на имя меню
struct MENU_DEF * submenu;//подменю данного элемента
void (*handler)(void);//обработчик входа в меню (можем не иметь подменю но вызвать ф-цию)
}MENU;

//строки с названиями меню
//отступы для понимания структуры :)
MENU_NAME main1 = "One";
   MENU_NAME s1main1 = "One1";
   MENU_NAME s1main2 = "Two1";
   MENU_NAME s1main3 = "Three1";

MENU_NAME main2 = "Two";
   MENU_NAME s2main1 = "One2";
   MENU_NAME s2main2 = "Two2";
   MENU_NAME s2main3 = "Three2";

MENU_NAME main3 = "Three";
   MENU_NAME s3main1 = "One3";
   MENU_NAME s3main2 = "Two3";
      MENU_NAME s3main2_1 = "Two31";
      MENU_NAME s3main2_2 = "Two32";
   MENU_NAME s3main3 = "Three3";

//пример обработчика
void handler_sample()
{
    printf("handler_sample\n");
}

//описиваем первое подменю
MENU menu_one[] =  {
                      {s1main1, NULL, NULL},
                      {s1main2, NULL, NULL},
                      {s1main3, NULL, NULL},
                      {NULL, NULL, NULL}//конец меню
                    };
//описиваем подменю второго подменю
MENU menu_two_s[] =  {
                      {s3main2_1, NULL, NULL},
                      {s3main2_2, NULL, NULL},
                      {NULL, NULL, NULL}
                    };

//описиваем второе подменю
MENU menu_two[] =  {
                      {s2main1, NULL, NULL},
                      {s2main2, menu_two_s, NULL},
                      {s2main3, NULL, handler_sample},
                      {NULL, NULL, NULL}
                    };

//описиваем третье подменю
MENU menu_thr[] =  {
                      {s3main1, NULL, NULL},
                      {s3main2, NULL, NULL},
                      {s3main3, NULL, NULL},
                      {NULL, NULL, NULL}
                    };

//главное меню
MENU main_menu[] = {
                      {main1, menu_one, NULL},
                      {main2, menu_two, NULL},
                      {main3, menu_thr, NULL},
                      {NULL, NULL, NULL}
                    };

//запуск обработчика
void run_handler(struct MENU_DEF * parent)
{
    //есть ли он вообще
    if(parent->handler != NULL)
    {
        //запуск
        parent->handler();
    }
    else//можно удалить
        printf("No handler for %s\n", parent->name);
}

//выводим все меню на экран с отступами
//parent - указатель на текущее меню/подменю
//level - глубина меню
void test_menu(struct MENU_DEF * parent, int level)
{
    int i;
    struct MENU_DEF * curr = parent;
    //проходим по всех пунктах текущего меню пока
    //не конец меню (curr->name != NULL)
    while(curr != NULL && curr->name != NULL)
    {
        //выводим отступ (можно удалить)
        for(i=0;i<level;i++)
            printf("\t");
        printf("+:");

        //Выводим название элемента
        printf("%s: ", curr->name);
        //запускаем обработчик
        run_handler(curr);

        //идем в подменю елемента
        test_menu(curr->submenu, level+1);

        //переходим к следующему елементу текущего меню
        curr++;
        //аналогично curr--; но нужно проверять на равенство parent
    }
}

int main()

{
    test_menu(main_menu, 0);

    return 0;
}
Код не нужно переделывать. А только доделать. Написать названия/структуру своего меню,
добавить обработку нажатий кнопок вверх/вниз/ОК. Да и вроде все :)
Ответить

Вернуться в «AVR»