0

我想在触发中断时每秒增加一个变量。esp32、esp-idf 上的代码。我已经连接了一个按钮,当按下按钮时我想计算秒数。

我使用轮询功能做到了这一点,但我想学习如何使用中断来做到这一点,因此仅在按下按钮时计数和轮询,而不是每秒检查是否有按下按钮。

#include <stdio.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#define ESP_INTR_FLAG_DEFAULT 0

#define BLINK_LED 13
#define GPIO_INPUT_IO_0 33
int buttonCount = 0;
int i = 0;

SemaphoreHandle_t xSemaphore = NULL;

TaskHandle_t printVariableTask = NULL;

void printVariable(void *pvParameter) {

    int a = (int) pvParameter;
    while (1) {

        printf("A is a: %d \n", a++);
        vTaskDelay(1000 / portTICK_RATE_MS);
    }
}
// interrupt service routine, called when the button is pressed
void IRAM_ATTR button_isr_handler(void* arg) {

    // notify the button task
    xSemaphoreGiveFromISR(xSemaphore, NULL);

}
// task that will react to button clicks
void button_task(void* arg) {

    // infinite loop
    for(;;) {

        // wait for the notification from the ISR
        if(xSemaphoreTake(xSemaphore,portMAX_DELAY) == pdTRUE) {
            int buttonState = gpio_get_level(GPIO_INPUT_IO_0);

            while(buttonState == 1){ //code stucks here!!!!
                buttonCount++;
                printf("GPIO_INPUT_IO_0 %d\n", buttonState);
                printf("Button pressed! %d \n", i++);
                gpio_set_level(BLINK_LED, buttonState);
                vTaskDelay(1000 / portTICK_RATE_MS);
                }
        }
    }
}

void app_main()
{
    // create the binary semaphore
    xSemaphore = xSemaphoreCreateBinary();

    // configure button and led pins as GPIO pins
    gpio_pad_select_gpio(GPIO_INPUT_IO_0);
    gpio_pad_select_gpio(BLINK_LED);

    // set the correct direction
    gpio_set_direction(GPIO_INPUT_IO_0, GPIO_MODE_INPUT);
    gpio_set_direction(BLINK_LED, GPIO_MODE_OUTPUT);

    // enable interrupt on falling (1->0) edge for button pin
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_POSEDGE);

    // start the task that will handle the button
    xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL);

    // install ISR service with default configuration
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);

    // attach the interrupt service routine
    gpio_isr_handler_add(GPIO_INPUT_IO_0, button_isr_handler, NULL);

    int pass = 25;
    xTaskCreate(&printVariable, "printVariable", 2048, (void*) pass, 5, &printVariableTask);

}

它可以工作,但是当代码进入 while(buttonState == 1) 时,循环永远不会结束。

我究竟做错了什么?

4

1 回答 1

0

不确定这是否仍然是您的问题,但尝试将一个新的全局变量作为标志,并在您想开始计数时在中断例程中将其设置为 1。在您的循环中查找该标志设置为 1 并开始递增。当您检测到按钮不再被按下时,将标志设置为 0。

此外,您永远不会在按钮任务 while 循环中重置按钮状态。这就是为什么您的按钮状态总是返回为 1。

实际上,进一步研究它,我认为您可能只需要在 for(;;) 循环中的 if 语句之外对输入级别级别进行采样。我认为这是因为(我相信)您在按钮任务中的 if 不会在下降沿被调用?

于 2021-02-12T17:39:17.710 回答