Порядок прерываний в STM32

Я хочу сделать калькулятор на STM32 с моей клавиатурой 4x4 и SSD (7-сегментный дисплей). Я буду использовать A в качестве сложения на клавиатуре и, скажем, я посчитаю это: 9 + 8 = 17. Я использую прерывания для получения чисел с клавиатуры, поэтому прерывания, которые я использовал для этих чисел, следующие:

//INTERRUPT FOR NUMBER 9

void EXTI0_1_IRQHandler(void){ // Interrupt from PB0
    GPIOB->ODR ^= (1U << 9); //PB9
    if ((GPIOB->IDR >> 0) & 1){
        //9
        setSSD(9);
    }
GPIOB->ODR ^= (1U << 9); //PB9
}

//INTERRUPT FOR NUMBER 8
void EXTI2_3_IRQHandler(void){// Interrupt from PB2

    GPIOB->ODR ^= (1U << 9); //PB9
    if ((GPIOB->IDR >> 2) & 1){
        //8
        setSSD(8);
    }
}

//INTERRUPT FOR A 
void EXTI4_15_IRQHandler(void){
        if ((GPIOA->IDR >> 9) & 1){
            //A
            addition (x,y);
        }
        GPIOB->ODR ^= (1U << 4); //PB4
}

Вот моя проблема: на обычном языке C я бы попросил пользователя дать число с помощью scanf и поместить число в переменную x, а затем взять другое число, поместить его в y. И определите A как x + y, чтобы вычисление было выполнено.

Но здесь нет такой функции, как scanf, так как я могу упорядочить прерывания? Например, первое прерывание (нажатие первого числа) должно быть x, а второе прерывание (нажатие второго числа) должно быть y.

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

SSD? Это может быть многое. Устранить неоднозначность. Хотя обработка нажатий клавиш в прерываниях возможна, у вас, вероятно, будут проблемы с отказом переключения. Вам лучше разделить процесс на обработку нажатия клавиш, числовой ввод и калькулятор, а не пытаться делать все это в прерываниях - это нецелесообразно.

Clifford 23.12.2020 21:32

7 сег. отображать. Отредактировано.

noob 23.12.2020 22:06

Сколько цифр?

Clifford 23.12.2020 22:15

Одно прерывание на клавишу кажется довольно экстравагантным (и маловероятным). Это действительно то, как работает оборудование?

Clifford 23.12.2020 22:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
129
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Пользовательский интерфейс, как вы его описываете, имеет состояние, то есть он может находиться в состоянии, когда вы вводите «X», или в состоянии, когда вы вводите «Y». Вы можете добавить «ветви» состояния в обработчики прерываний, т.е. if (state == StateX) ... else if (state == StateY) .... Но обработчики прерываний часто лучше оставить короткими и простыми.

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

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

Ответ принят как подходящий

Вам нужно пересмотреть свой дизайн, а не смешивать ввод-вывод с приложением. Сначала заставьте ваш ввод-вывод работать с устранением дребезга коммутатора и т. д. (который может использовать или не использовать прерывания); затем напишите приложение-калькулятор. Вы уже обдумали, как это сделать с помощью stdio, и точно так же, как scanf() не обновляет дисплей или не выполняет вычисления, не должен этого делать и ваш драйвер клавиатуры.

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

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

В частности, ответ на ваш вопрос заключается в использовании простого «автомата состояний», где состояние увеличивается при нажатии клавиши оператора, и использовать это «состояние», чтобы определить, какой оператор обновляется. Вам нужно только два «регистра», потому что вместо A = x + y настоящий калькулятор выполняет x = x + y, так что ответ можно использовать в качестве операнда в дальнейших операндах.

// Variables to store the operands and operator
int operand[2] = 0 ;
int operand_idx = 0 ;
typedef enum
{
    ADD,SUB,MUL,DIV
} eOperator ;

eOperator operator ;

// Call for each digit key pressed
void addDigit( int d )
{
    operand[operand_idx] *= 10 ;
    operand[operand_idx] += d ;
    display( operand[operand_idx] ) ;
}

// Call when an operator key is pressed
void setOperator( eOperator op )
{
    if ( operator == 0 )
    {
        operator = op ;
        operand_idx = 1 ;
    }
    else
    {
        calculate() ;
    }
}

// Call when " = " / answer key pressed
void calculate()
{
    switch( operator )
    {
        case ADD :  operand[0] = operand[0] + operand[1] ; break ;
        case SUB :  operand[0] = operand[0] - operand[1] ; break ;
        case MUL :  operand[0] = operand[0] * operand[1] ; break ;
        case DIV :  operand[0] = operand[0] / operand[1] ; break ;
    }

    display( operand[0] ) ;
    operand[1] = 0 ;
}

// Call to clear calculation
void clear()
{
    operand[0] = 0 ;
    operand[1] = 0 ;
    operand_idx = 0 ;
}

Затем, если вы реализуете подходящий драйвер клавиатуры с функцией getKey(), тогда сам калькулятор будет выглядеть так:

for(;;)
{
    char key = getKey() ;

    if ( isdigit( key ) )
    {
        addDigit( key - '0' ) ;
    }
    else
    {
        switch( key )
        {
             case 'A' : setOperator( ADD ) ; break ;
             case 'B' : setOperator( SUB ) ; break ;
             case 'C' : setOperator( MUL ) ; break ;
             case 'D' : setOperator( DIV ) ; break ;
             case 'E' : calculate() ; break ;
             case 'F' : clear() ; break ;
        }
    }
}

Другие вопросы по теме