Глюк с клавиатурой. А может просто глупость, или нет

Тема в разделе "Флудилка", создана пользователем Igor68, 15 ноя 2018.

  1. Igor68

    Igor68 Гуру

    Так опрос клавиатуры, когда процессору ну совсем нет времени на основной цикл main, всё время то в IRQ, то в FIQ. Говорю про ARM7. В моём случае на main уходит менее 1% времени.
    Код (C++):
    //========== параметры интерфейса клавиатуры =====================================
    unsigned char    Key_Old;                                        //прошлый код клавиши
    char    key;
    uint8_t    keyloop;
    uint8_t kMatrix[4];

    void    GetKey(void)
    {
        switch(keyloop)
        {
            //------ out _KEY2_2 -----
            //K_KEY1
            case 0:
                PORT_KEYBOARD_S_OUT = _KEY2_2 << 16; //установка высокого уровня
                keyloop++;
                break;
            case 1:
                if(PORT_KEYBOARD_IN & _KEY1_1)
                    kMatrix[0]    |= 0x0F;
                else
                    kMatrix[0]    &= (~(0x0F));
                if(PORT_KEYBOARD_IN & _KEY1_2)
                    kMatrix[1]    |= 0x0F;
                else
                    kMatrix[1]    &= (~(0x0F));
                PORT_KEYBOARD_C_OUT = _KEY2_2 << 16; //установка низкого уровня
                keyloop++;
                break;
            case 2:
                if(!(PORT_KEYBOARD_IN & _KEY1_1))
                    kMatrix[0]    |= 0xF0;
                else
                    kMatrix[0]    &= (~(0xF0));
                if(!(PORT_KEYBOARD_IN & _KEY1_2))
                    kMatrix[1]    |= 0xF0;
                else
                    kMatrix[1]    &= (~(0xF0));
                PORT_KEYBOARD_S_OUT = _KEY2_3 << 16; //установка высокого уровня
                keyloop++;
                break;
            case 3:
                if(PORT_KEYBOARD_IN & _KEY1_1)
                    kMatrix[2]    |= 0x0F;
                else
                    kMatrix[2]    &= (~(0x0F));
                if(PORT_KEYBOARD_IN & _KEY1_2)
                    kMatrix[3]    |= 0x0F;
                else
                    kMatrix[3]    &= (~(0x0F));
                PORT_KEYBOARD_C_OUT = _KEY2_3 << 16; //установка низкого уровня
                keyloop++;
                break;
            case 4:
                if(!(PORT_KEYBOARD_IN & _KEY1_1))
                    kMatrix[2]    |= 0xF0;
                else
                    kMatrix[2]    &= (~(0xF0));
                if(!(PORT_KEYBOARD_IN & _KEY1_2))
                    kMatrix[3]    |= 0xF0;
                else
                    kMatrix[3]    &= (~(0xF0));
                keyloop++;
                break;
            case 5:
                if(kMatrix[0] == 0xFF)
                {
                    key = K_KEY1;
                    TCK_L = 0;                            //Обнуление таймера подсветки
                }
                else if(kMatrix[1] == 0xFF)
                {
                    key = K_KEY2;
                    TCK_L = 0;                            //Обнуление таймера подсветки
                }
                else if(kMatrix[2] == 0xFF)
                {
                    key = K_KEY3;
                    TCK_L = 0;                            //Обнуление таймера подсветки
                }
                else if(kMatrix[3] == 0xFF)
                {
                    key = K_KEY4;
                    TCK_L = 0;                            //Обнуление таймера подсветки
                }
                else
                    key = NO_KEY;
                keyloop = 0;
                break;
            default:
                PORT_KEYBOARD_C_OUT = _KEY2_2 << 16; //установка низкого уровня
                PORT_KEYBOARD_C_OUT = _KEY2_3 << 16; //установка низкого уровня
                keyloop = 0;
                break;
        }
    }


    //
    // Опрос клавиатуры
    char    Inkey(void)
    {
            if((key != NO_KEY) &&
            (key != Key_Old))
            {
                Key_Old = key;
                return key;
            }
            else
            {
                Key_Old = key;
                return NO_KEY;
            }
    }
     
    Потому как реализация выходного сигнала (синтезатор на ШИМ по огибающей) на FIQ, измерения и коррекция сигнала, обслуживание периферии, пересчёт выжных параметров на IRQ. на main и времени уже нет. Так что в main только Inkey, а работа с клавой как периферия GetKey. И тормоз с вводом пропал. Кстати сканирование клавы 2х2 идёт как по высокому, так и по низкому уровню, то есть если случайные наводки и т.п. В смысле опрос:
    1 подаём низкий, при нажатии должен прочитан быть низкий
    2 подаём высокий при нажатии должен прочитан быть высокий
    3 при выполнении п 1 и 2 клавиша считается нажатой
     
    Последнее редактирование: 15 ноя 2018
  2. Igor68

    Igor68 Гуру

    А что бы не тратить память, можно обойтись и одним байтом - как метод флагов.
    вот это:
    Код (C++):
    kMatrix[2]    |= 0x0F;
    поменять на это:
    Код (C++):
    kMatrixByte    |= 0x01; //для одного опроса (по высокому)
    kMatrixByte    |= 0x02; //тогда для низкого
    //остальное аналогично

    //ну и проверка
    if((kMatrixByte & 0x03) == 0x03)
      //клавиша нажата
     
    Ну если занимать не матрицу как ранее, а один байт, то анализировать надо конкретно биты. Как раз выходит, что на переменную в 1байт определяются состояния 4-х кнопок в помехоустойчивом варианте. Процедуру GetKey повесить надо на прерывание по любому таймеру. Тогда в цикле main ну или loop просто читать код клавиши. Клавиша будет прочитана и дребезга с параметром OldKey для функции Inkey не будет - испытано.