为什么我需要将 millis() 函数放在主循环中来触发 ISR?

问题描述 投票:0回答:1

我正在尝试复制包含多功能按钮的耳塞功能。如果您按此按钮 x 次,在一段时间内,耳塞将根据您按按钮的次数执行某些操作。问题是我需要将 millis() 放在主循环内以触发 ISR增加 millis 变量:ISR (TIMER0_COMPA_vect),我不明白为什么

这些是我的主要代码和库。

#include <mcu_init.h>
#include <millis.h>
#include <button.h>

int main() {

    GPIO_init();

    cli();

    INT0_init();
    TMR0_init();

    sei();

    while (1) {
        
        handleButton();
        
    }

    return 0;

}
#include <millis.h>

static volatile uint32_t miliseconds = 0;

ISR (TIMER0_COMPA_vect) {
    miliseconds++;
    PORTA |= (1 << 1);

}

uint32_t millis() {

    uint32_t time;
    uint8_t oldSREG = SREG;

    cli();

    time = miliseconds;
    SREG = oldSREG;

    return time;

}

这是按钮的逻辑,以防万一。

#include <button.h>

volatile uint8_t count = 0;
volatile uint32_t lastPressTime = 0;

ISR (INT0_vect) {

    if (millis() - lastPressTime >= 200) {
        count++;
      lastPressTime = millis();

    }

}

void handleButton() {
  
  if (millis() - lastPressTime >= 1500) {
    lastPressTime = millis();

    switch (count) {

      case 2:
        PORTA ^= (1 << 1);
        count = 0;
        break;

      case 3:
        PORTA ^= (1 << 3);
        count = 0;
        break;

      default:
        count = 0;

    }

    }

    return;

}

这些是头文件

#ifndef MILLIS_H_
#define MILLIS_H_

#include <avr/interrupt.h>

uint32_t millis();

#endif
#ifndef BUTTON_H_
#define BUTTON_H_

#include <millis.h>

void handleButton();

#endif
c arduino embedded avr
1个回答
0
投票

在你的handleButton函数中,每次进入if()块时都会重置count变量。

如果您不使用 millis() 函数,即在每个主循环中执行 switch(),一旦中断例程将其从零递增并返回,计数变量可能会再次重置为零。

如果你想在超时发生后重置变量计数并且不再按第一次发生,你需要处理一些状态,如下面的代码:

// as in your code, the minimum acceptable time between press events
#define def_click_debounce_ms 200
// after a press event occurs, if no more press events occur after this time, we assume that the user press sequence has completed
#define def_pause_validate_click_ms (def_click_debounce_ms + 1000)

// your ISR for the press event, just enriched with a signal on too short press
ISR (INT0_vect) {

    if (millis() - lastPressTime >= def_click_debounce_ms) {
        // increment the number of press detected
        count++;
        lastPressTime = millis();
    }
    else
    {
        // signal to main that an invalid press happened
        reset_wait_release_request++;
    }
}

// the status of handleButton check 
typedef enum _enum_check_button_press_status
{
    enum_check_button_press_status_init = 0,
    enum_check_button_press_status_check_press_sequence,
    enum_check_button_press_status_numof
}enum_check_button_press_status;

// our check button press status variable
enum_check_button_press_status e_check_button_press_status = enum_check_button_press_status_init;
// we use this variable to keep the number of press events handleButton detects
uint8_t num_consecutive_press_detected = 0;

void handleButton() {
    // store the current time
    const uint32_t now_ms = millis();
    switch(e_check_button_press_status)
    {
    case enum_check_button_press_status_init:
    default:
    {
        // no press detected at this moment
        num_consecutive_press_detected = 0;
        // check for a press sequence
        e_check_button_press_status = enum_check_button_press_status_check_press_sequence;
        break;
    }
    case enum_check_button_press_status_check_press_sequence:
    {
        // has the interrupt routine detected a new press?
        if (count != main_count)
        {
            // align our own press counter
            main_count = count;
            // increment the number of press detected by the main
            num_consecutive_press_detected++;
            // mark the time of the last press detected by the main
            start_wait_release_ms = now_ms;
        }
        // if an invalid press happened, let's restart our release timer
        else if (reset_wait_release_request != reset_wait_release_ack)
        {
            reset_wait_release_ack = reset_wait_release_request;
            // we restart the time of the last press detected by the main
            start_wait_release_ms = now_ms;
        }
        // if a timeout happens waiting for next press, let's check if it was a valid press sequence
        else if ((num_consecutive_press_detected > 0) && (now_ms - start_wait_release_ms >= def_pause_validate_click_ms))
        {
            // do your stuff
            switch(num_consecutive_press_detected)
            {
            case 0:
            {
                // should never happen...
                break;
            }
            case 2:
            {
                // do the 2-clicks stuff
                PORTA ^= (1 << 1);
                break;
            }
            case 3:
            {
                // do the 3-clicks stuff
                PORTA ^= (1 << 3);
                break;
            }
            
            case 1:
            default:
            {
                printf("Invalid number of press detected: %u\n", (unsigned int)num_consecutive_press_detected);
                break;
            }
            }
            
            // go back to the init state
            e_check_button_press_status = enum_check_button_press_status_init;
        }
        break;
    }
    }   

}
© www.soinside.com 2019 - 2024. All rights reserved.