Обработчик нажатий клавиатуры по Serial (UART)

буду благодарен за примеры

Примеры к абстрактным данным не пишутся.

мне казалось данные вполне неабстрактные

пример:

  1. Читаете первый принятый байт. Если он 0x5F или 0x6F - переходите к п 2, если нет - остаетесь на п.1
  2. Читаете следующий байт. Если он один из 33х команд - отмечаете кнопку как нажатую или отжатую в массиве. Если нет - ничего не делаете. В любом случае переход на п1

Вот и все. В коде это должно занять строчек 10, не более.

Читаешь сериал, пока не попадется 0x5F или 0x6F. Попалось - сохранил в переменную action, читаешь сериал дальше. Следующим байтом пойдёт сканкод. Т.е. если считал байт не равный 0x5F или 0x6F, но action уже 0x5F или 0x6F, то этот байт сохраняешь в keycode и начинаешь искать в массиве связные данные. Массив не 2x33, а 33x2.
Т.е. элемент 0 - это сканкод, элемент 1 - данные.
Итого имеешь action, keycode и данные. Сделал с ними что нужно, action занулил. Начинаешь все сначала.

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

unsigned char rx_bayt  = 0;
unsigned char rx_count = 0;
unsigned char action = 0;
unsigned char keycode = 0;

byte buttons[33][2] = {{0x07,0x00},   
                       {0x06,0x00},
                       {0x05,0x00},
                       {0x0F,0x00},
                       {0x0E,0x00},
                       {0x0D,0x00},
                       {0x17,0x00},
                       {0x16,0x00},
                       {0x15,0x00},
                       {0x1E,0x00},
                       {0x1F,0x00},
                       {0x1D,0x00},
                       {0x27,0x00},
                       {0x26,0x00},
                       {0x25,0x00},
                       {0x04,0x00},
                       {0x03,0x00},
                       {0x1C,0x00},
                       {0x24,0x00},
                       {0x23,0x00},
                       {0x0C,0x00},
                       {0x0B,0x00},
                       {0x14,0x00},
                       {0x13,0x00},
                       {0x1B,0x00},
                       {0x2F,0x00},
                       {0x2D,0x00},
                       {0x2E,0x00},
                       {0x36,0x00},
                       {0x2C,0x00},
                       {0x37,0x00},
                       {0x35,0x00},
                       {0x34,0x00}};
//---------------------------------------------------------------------------
void Rx_Decode()
{
  rx_bayt = Serial1.read();

  if(((rx_bayt == 0x5F) || (rx_bayt == 0x6F)) && rx_count == 0)//принимаем 1й байт
  {
    action = rx_bayt;
    rx_count++;
  }
  else if(((rx_bayt != 0x5F) || (rx_bayt != 0x6F)) && rx_count == 1)//принимаем 2й байт
  {
    keycode = rx_bayt;
    pars();
    rx_count = 0;
  }
}
//---------------------------------------------------------------------------
void pars()
{
      switch(keycode)
      {
         //buttons[0][0] проверка нажатия 1й кнопки
         case :
                           //действие 1
                           Serial.println("1 button ON");
         break; 

         //buttons[1][0] проверка нажатия 2й кнопки         
         case : 
                           //действие 2
                           Serial.println("2 button ON");
         break;  

         //buttons[2][0] проверка нажатия 3й кнопки 
         case : 
                           //действие 3
                           Serial.println("3 button ON");
         break; 

         //buttons[3][0] проверка нажатия 4й кнопки       
         case : 
                           //действие 4
                           Serial.println("4 button ON");
         break;
      }  
}
//---------------------------------------------------------------------------
void setup() 
{
   Serial1.begin(9600);
   Serial.begin(9600);
}
//---------------------------------------------------------------------------
void loop() 
{
  if (Serial1.available() > 0) Rx_Decode();
}
//---------------------------------------------------------------------------

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

что то не до конца понял вашу мысль в том виде в каком он был он явно неподходит массив изменился. Вот но не пойму как правильно.

void Rx_Decode()
{
  rx_bayt = Serial1.read();

  if(((rx_bayt == 0x5F) || (rx_bayt == 0x6F)) && rx_count == 0)//принимаем 1й байт
  {
    action = rx_bayt;
    rx_count++;
  }
  else if(((rx_bayt != 0x5F) || (rx_bayt != 0x6F)) && rx_count == 1)//принимаем 2й байт
  {
    keycode = rx_bayt;
    
    for(byte i=0; i<33; i++)
    {
      if(buttons[i][0] == keycode)
      {
        if (action == 0x5F)//нажатие
        {
          buttons[i][1] = 1;
          Serial.println("button ON ");
          i = 33;
        }
    
        if (action == 0x6F)//отпускание
        {
          buttons[i][1] = 0;
          Serial.println("button OFF ");
          i = 33;
        }
      }//конец if(buttons[0][i] == data[1])
    }//конец for(byte i=0; i<33; i++)
    //pars();
    rx_count = 0;
  }
}

Зачем вы все скопировали?
Нужно просто проверить, есть ли в массиве такое значение

void Rx_Decode()
{
  rx_bayt = Serial1.read();

  if(((rx_bayt == 0x5F) || (rx_bayt == 0x6F)) && rx_count == 0)//принимаем 1й байт
  {
    action = rx_bayt;
    rx_count++;
  }
  else if ( rx_count == 1)  //принимаем 2й байт
  { bool test = false; 
    keycode = rx_bayt;
    for(byte i=0; i<33; i++)
    { if(buttons[i][0] == keycode)  test = true; }
    if (test)  {
        // байт есть в массиве, обрабатываем команду
    }
else {  // байта в массиве нет, команда неверна, возвращаемся в начало
  rx_count =0;
}

добавил это работает спасибо. А как выглядеть должен обработчик команды?

unsigned char rx_bayt  = 0;
unsigned char rx_count = 0;
unsigned char action = 0;
unsigned char keycode = 0;

byte buttons[33][2] = {{0x07,0x00},   
                       {0x06,0x00},
                       {0x05,0x00},
                       {0x0F,0x00},
                       {0x0E,0x00},
                       {0x0D,0x00},
                       {0x17,0x00},
                       {0x16,0x00},
                       {0x15,0x00},
                       {0x1E,0x00},
                       {0x1F,0x00},
                       {0x1D,0x00},
                       {0x27,0x00},
                       {0x26,0x00},
                       {0x25,0x00},
                       {0x04,0x00},
                       {0x03,0x00},
                       {0x1C,0x00},
                       {0x24,0x00},
                       {0x23,0x00},
                       {0x0C,0x00},
                       {0x0B,0x00},
                       {0x14,0x00},
                       {0x13,0x00},
                       {0x1B,0x00},
                       {0x2F,0x00},
                       {0x2D,0x00},
                       {0x2E,0x00},
                       {0x36,0x00},
                       {0x2C,0x00},
                       {0x37,0x00},
                       {0x35,0x00},
                       {0x34,0x00}};
//---------------------------------------------------------------------------
void Rx_Decode()
{
  rx_bayt = Serial1.read();

  if(((rx_bayt == 0x5F) || (rx_bayt == 0x6F)) && rx_count == 0)//принимаем 1й байт
  {
    action = rx_bayt;
    rx_count++;
  }
  else if(((rx_bayt != 0x5F) || (rx_bayt != 0x6F)) && rx_count == 1)//принимаем 2й байт
  {
    bool test = false; 
    keycode = rx_bayt;
    
    for(byte i=0; i<33; i++)
    {
      if(buttons[i][0] == keycode) test = true;
    }

    if (test)  
    {
        // байт есть в массиве, обрабатываем команду
        Serial.println("button OK");
    }
    else // байта в массиве нет, команда неверна, возвращаемся в начало
    {
      rx_count = 0;
    }
  }
}
//---------------------------------------------------------------------------
void setup() 
{
   Serial1.begin(9600);
   Serial.begin(9600);
}
//---------------------------------------------------------------------------
void loop() 
{
  if (Serial1.available() > 0) Rx_Decode();
}
//---------------------------------------------------------------------------

Почитайте про оператор switch() - это как раз то что надо.

Вот что вышло
вывод в терминал
1 button ON
2 button ON
Мне кажется что то в кейсе я сделал неправильно. Или мне так кажется.

unsigned char rx_bayt  = 0;
unsigned char rx_count = 0;
unsigned char action = 0;
unsigned char keycode = 0;

byte buttons[33][2] = {{0x07,0x00},   
                       {0x06,0x00},
                       {0x05,0x00},
                       {0x0F,0x00},
                       {0x0E,0x00},
                       {0x0D,0x00},
                       {0x17,0x00},
                       {0x16,0x00},
                       {0x15,0x00},
                       {0x1E,0x00},
                       {0x1F,0x00},
                       {0x1D,0x00},
                       {0x27,0x00},
                       {0x26,0x00},
                       {0x25,0x00},
                       {0x04,0x00},
                       {0x03,0x00},
                       {0x1C,0x00},
                       {0x24,0x00},
                       {0x23,0x00},
                       {0x0C,0x00},
                       {0x0B,0x00},
                       {0x14,0x00},
                       {0x13,0x00},
                       {0x1B,0x00},
                       {0x2F,0x00},
                       {0x2D,0x00},
                       {0x2E,0x00},
                       {0x36,0x00},
                       {0x2C,0x00},
                       {0x37,0x00},
                       {0x35,0x00},
                       {0x34,0x00}};
//---------------------------------------------------------------------------
void Rx_Decode()
{
  rx_bayt = Serial1.read();

  if(((rx_bayt == 0x5F) || (rx_bayt == 0x6F)) && rx_count == 0)//принимаем 1й байт
  {
    action = rx_bayt;
    rx_count++;
  }
  else if(((rx_bayt != 0x5F) || (rx_bayt != 0x6F)) && rx_count == 1)//принимаем 2й байт
  {
    bool test = false; 
    keycode = rx_bayt;
    
    for(byte i=0; i<33; i++)
    {
      if(buttons[i][0] == keycode) test = true;
    }

    if (test)  
    {
        // байт есть в массиве, обрабатываем команду
        //Serial.println("button OK");
        pars();
        rx_count = 0;
    }
    else // байта в массиве нет, команда неверна, возвращаемся в начало
    {
      rx_count = 0;
    }
  }
}
//---------------------------------------------------------------------------
void pars()
{
  unsigned char temp = 0;

    for(byte i=0; i<33; i++)
    {
      if(buttons[i][0] == keycode)
      {
        if (action == 0x5F)//нажатие
        {
          buttons[i][1] = 1;
          //Serial.print(i);
          //Serial.println(" button ON ");
          i = 33;
        }
    
        if (action == 0x6F)//отпускание
        {
          buttons[i][1] = 0;
          //Serial.print(i);
          //Serial.println(" button OFF ");
          i = 33;
        }
      }//конец if(buttons[0][i] == data[1])
    }//конец for(byte i=0; i<33; i++)
    
    for(byte i=0; i<33; i++)
    {
      temp = buttons[i][1];
      switch(i)
      {
         //проверка нажатия 1й кнопки
         case 0:
                //действие 1
                //if(temp == 1){Serial.println("1 button ON");}else{Serial.println("1 button OFF");}
                if(temp == 1){Serial.println("1 button ON");}
         break; 

         //проверка нажатия 2й кнопки         
         case 1: 
                //действие 2
                //if(temp == 1){Serial.println("2 button ON");}else{Serial.println("2 button OFF");}
                if(temp == 1){Serial.println("2 button ON");}
         break;  

         //проверка нажатия 3й кнопки 
         case 2: 
                           //действие 3
                           //Serial.println("3 button ON");
         break; 

         //проверка нажатия 4й кнопки       
         case 3: 
                           //действие 4
                           //Serial.println("4 button ON");
         break;
      }  
    }//конец for(byte i=0; i<33; i++)
}
//---------------------------------------------------------------------------
void setup() 
{
   Serial1.begin(9600);
   Serial.begin(9600);
}
//---------------------------------------------------------------------------
void loop() 
{
  if (Serial1.available() > 0) Rx_Decode();
}
//---------------------------------------------------------------------------

Массив с нулевыми значениями точно нужен?

Мне кажется вот в этой строке:

  else if(((rx_bayt != 0x5F) || (rx_bayt != 0x6F)) && rx_count == 1)//принимаем 2й байт

Должно быть не логическое или, а логическое и:

  else if(((rx_bayt != 0x5F) && (rx_bayt != 0x6F)) && rx_count == 1)//принимаем 2й байт

Потому что во втором байте не может быть ни 0x5F ни 0x6F. А может быть и вообще упростить до:

  else if (rx_count == 1)//принимаем 2й байт

Но может случится такое, что вторым придёт 5F или 6F вследствие взрыва газа на Венере. Первое условие должно быть безусловно синхронизирующим.

Поскольку этих значений нет в массиве, то второе условие все равно не выполнится.
Так что явная проверка на

не нужна

Это так. Но работать будет чуть медленней.

Кстати, для “наглядности”, диапазон значений rx_count логичнее сдвинуть от 1 до 2 (а не 0…1 как сейчас) :slight_smile:

const uint8_t kaNone = 0x00;
const uint8_t kaOn   = '1';
const uint8_t kaOff  = '0';

typedef struct {
  uint8_t action;
  uint8_t code;
} panelKey_t;

panelKey_t getPanelKey() {
  static uint8_t action = kaNone;
  panelKey_t result = {.action = kaNone, .code = 0x00};

  int16_t reading = Serial.read();
  // read() returns -1 on empty Serial buffer
  if (0x00 <= reading) {
    uint8_t currentByte = (byte) reading;
    if (kaOn == currentByte || kaOff == currentByte) {
      Serial.println("Action code catched");
      action = currentByte;
    } else {
      if (kaNone != action) {
        Serial.println("Key code catched");
        result.action = action;
        result.code = currentByte;
        action = kaNone;
      }
    }
  }
  return result;
}

void setup() {
  Serial.begin(9600);
}

void loop()
{
  panelKey_t panelKey = getPanelKey();
  if (kaNone != panelKey.action) {
    Serial.print("Key data incoming: code="); Serial.print((char)panelKey.code); 
    Serial.print(", action="); Serial.println(kaOn == panelKey.action ? "ON": "OFF");
  }
}

1 лайк