128x64 и кнопки

Может ли кто-нибудь дать мне совет по созданию меню для ЖК-дисплея 128x64 с использованием 5 кнопок? у меня 5 экранов. btn1 для отображения MainMenu и Selection. btn2 и btn3 для прокрутки вверх и вниз btn 4 и btn4 предназначены для включения/выключения и увеличения/уменьшения значений.

Проблема, с которой я столкнулся, связана с btn2 и btn3. я не знаю, как использовать их для прокрутки на другом экране, кроме screen1 (MainMenu).


#include "U8glib.h"
U8GLIB_ST7920_128X64_1X u8g(13,12,11); //Enable, RW, RS, RESET

int selectionButton = A1, selectionButtonState, selectionButtonLastState = 0, cntSelectionButtonPressed = 0, cntSelectionButtonPressed2ForMenu2 = 0;
int menuButton = A0, menuButtonState, menuButtonLastState = 0;
int scrollDownButton = A3, scrollDownButtonState, scrollDownButtonLastState = 0;
  boolean mainMenu = false;


void setup()
{
    Serial.begin(9600);
    if ( u8g.getMode() == U8G_MODE_R3G3B2 ) 
    u8g.setColorIndex(255);     // white
    else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )
    u8g.setColorIndex(3);         // max intensity
    else if ( u8g.getMode() == U8G_MODE_BW )
    pinMode(selectionButton,INPUT);
    pinMode(menuButton,INPUT);
    pinMode(scrollDownButton,INPUT);

}

void loop()
{

 scrollDownButtonState = digitalRead(A3);
 selectionButton = digitalRead(A1);
 menuButton = digitalRead(A0);



//pin A1 = RiGHT
 if(selectionButton != selectionButtonLastState)
 {
  if(digitalRead(A1) == HIGH)
  {
    cntSelectionButtonPressed += 1;
    if(cntSelectionButtonPressed == 4)
    {
      cntSelectionButtonPressed = 0;
    }
  }
  selectionButtonLastState = selectionButton;
 }


////////////////////////
 if(menuButton != menuButtonLastState)
  {
    if(cntSelectionButtonPressed == 1 && digitalRead(A0) == HIGH)
    {
         cntSelectionButtonPressed2ForMenu2 += 1; 
    }
      if(cntSelectionButtonPressed2ForMenu2 == 4)
      {
        cntSelectionButtonPressed2ForMenu2 = 0;
      }
       u8g.firstPage();
       do{
           Menu2();
         }while(u8g.nextPage());


       menuButtonLastState = menuButton; 
  }
 else
 {
 u8g.firstPage();
  do{
    MainMenu();
  }while(u8g.nextPage());
 }

}


void MainMenu(){
switch(cntSelectionButtonPressed)
{

  case 1:
           u8g.setFont(u8g_font_6x13); 
           u8g.setPrintPos(15,15);
           u8g.print("> Ceas");
           u8g.setPrintPos(15,25);
           u8g.print("  Interior casa");
           u8g.setPrintPos(15,35);
           u8g.print("  Exterior casa");  
           break;
  case 2:     
           u8g.setFont(u8g_font_6x13); 
           u8g.setPrintPos(15,15);
           u8g.print("  Ceas");
           u8g.setPrintPos(15,25);
           u8g.print("> Interior casa");
           u8g.setPrintPos(15,35);
           u8g.print("  Exterior casa");  
           break;
           break;
  case 3:
           u8g.setFont(u8g_font_6x13); 
           u8g.setPrintPos(15,15);
           u8g.print("  Ceas");
           u8g.setPrintPos(15,25);
           u8g.print("  Interior casa");
           u8g.setPrintPos(15,35);
           u8g.print("> Exterior casa");  
           break;   
}
}



void Menu2()
{

  switch(cntSelectionButtonPressed2ForMenu2)
{
  case 1:
           u8g.setFont(u8g_font_6x13); 
           u8g.setPrintPos(15,15);
           u8g.print("> Stil1");
           u8g.setPrintPos(15,25);
           u8g.print("  Stil2");
           u8g.setPrintPos(15,35);
           u8g.print("  Stil3");  
           break;
  case 2:     
           u8g.setFont(u8g_font_6x13); 
           u8g.setPrintPos(15,15);
           u8g.print("  Stil1");
           u8g.setPrintPos(15,25);
           u8g.print("> Stil2");
           u8g.setPrintPos(15,35);
           u8g.print("  Stil3");  
           break;
           break;
  case 3:
           u8g.setFont(u8g_font_6x13); 
           u8g.setPrintPos(15,15);
           u8g.print("  Stil1");
           u8g.setPrintPos(15,25);
           u8g.print("  Stil2");
           u8g.setPrintPos(15,35);
           u8g.print("> Stil3");  
           break;   
}
}

, 👍0


1 ответ


1

Во-первых, я немного удивлен, что вы используете аналоговые контакты для проверки кнопок, а не цифровые.

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

Например, вы хотите иметь следующие экраны (название/содержание экрана показано в [], переход кнопки с помощью ---(key)-->

InitScreen--- (right)--> MenuOption1Highlight---(right)-->MenuOption1Items
                              |       ^     \---(left)----+
                           (down)    (up)
                              v       |
                           MenuOption2Highlight---(right)-->MenuOption2Items
                                              \---(left)----+

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

enum EMenuPage
{
        None,
    InitScreen,
    MenuOption1Highlight,
    MenuOption1Items,
    MenuOption2Highlight,
    MenuOption2Items
};

Затем создайте для него текущее состояние как глобальную переменную:

EMenuPage _eMenuPage;

И инициализируйте его в программе установки:

_eMenuPage = None;

Создайте перечисление для ключей:

enum EKey
{
    None,
    Up,
    Down,
    Right,
    Left
};

Легче создать функцию, которая считывает ключи и возвращает один ключ, возможно, один ключ имеет приоритет над другим, или вы можете комбинировать ключи (в этом случае добавьте в EKey, например, UpAndDown). Если ни одна клавиша не была нажата, выбирается «Нет».

В цикле используйте диаграмму перехода состояний для программирования параметров:

EKey pressedKey = GetPressedKey(); // Это нужно реализовать самому, он обновляет _pressedKey;

switch (_eMenuPage)
{
case None:
    InitScreen();
    break;

case InitScreen:
    ProcessInitScreenKeys();
    break;

case MenuOptions1HighLighted:
    ProcessMenuOptions1HighLightedKeys();
    break;

...
default:
    // Недопустимый ключ
    break;
}

Для каждой страницы вы создаете функцию (например, InitScreen), которая обновляет состояние и показывает содержимое на дисплее:

void InitScreen()
{
    _eMenuPage = InitScreen;

    // Показать содержимое на дисплее.
}

Кроме того, вы создаете функцию Process...Keys для обработки ключей. Нравится:

void InitScreen()
{
    EKey pressedKey = GetPressedKey();
    switch (pressedKey)
    {
    case Right:
        MenuOptions1HighLighted();
        break;

    default:
        // Игнорировать другие ключи
        break;
    }
}

Для другой функции это будет выглядеть так:

void ProcessMenuOptions1HighLightedKeys()
{
    EKey pressedKey = GetPressedKey();
    switch (pressedKey)
    {
    case Down:
        MenuOptions1HighLighted();
        break;

    case Right:
        MenuOption1Items();
        break;

    default:
        // Игнорировать другие ключи
        break;
    }
}

(Кстати, я не проверял и не компилировал код).

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

,