GPIOの入力割り込み、キューでの割り込みデータの受け渡し。
開発環境
vsCode+PlatformIO
プラットフォーム:ESP-IDF
<プログラムの動作内容>
・GP4を押すと、"立上がり"と"立下り"で、割り込み。
・GP5を押すと、"立上がり"のみで、割り込み。
・GP4,5ともに、同一の割り込み関数。その中で、ピン番号をキューに格納。
・タスクを一つ作り、その中で、キューデータを受信。ピン番号と、GPIOのレベルをシリアル出力。
ESP32のAPIを使って、GPIO割り込みの基本を学びます。
APIなので、レジスタを直接叩くことはありません。
このひな形を基本に、自分のアプリケーションを作っていくことになると思われます。
<参考>
コード
platformio.ini
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = espidf
Kconfig.projbuild
menu "GPIO Configuration"
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
config GPIO_OUTPUT_0
int "GPIO output pin 0"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 8 if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2
default 18
help
GPIO pin number to be used as GPIO_OUTPUT_IO_0.
config GPIO_OUTPUT_1
int "GPIO output pin 1"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 9 if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2
default 19
help
GPIO pin number to be used as GPIO_OUTPUT_IO_1.
config GPIO_INPUT_0
int "GPIO input pin 0"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 4
help
GPIO pin number to be used as GPIO_INPUT_IO_0.
config GPIO_INPUT_1
int "GPIO input pin 1"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 5
help
GPIO pin number to be used as GPIO_INPUT_IO_1.
endmenu
LS1_GPIO_main.c
/* GPIO Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
/**
* Brief:
* This test code shows how to configure gpio and how to use gpio interrupt.
*
* GPIO status:
* GPIO18: output (ESP32C2/ESP32H2 uses GPIO8 as the second output pin)
* GPIO19: output (ESP32C2/ESP32H2 uses GPIO9 as the second output pin)
* GPIO4: input, pulled up, interrupt from rising edge and falling edge
* GPIO5: input, pulled up, interrupt from rising edge.
*
* Note. These are the default GPIO pins to be used in the example. You can
* change IO pins in menuconfig.
*
* Test:
* Connect GPIO18(8) with GPIO4
* Connect GPIO19(9) with GPIO5
* Generate pulses on GPIO18(8)/19(9), that triggers interrupt on GPIO4/5
*
*/
#define GPIO_OUTPUT_IO_0 CONFIG_GPIO_OUTPUT_0
#define GPIO_OUTPUT_IO_1 CONFIG_GPIO_OUTPUT_1
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
/*
* Let's say, GPIO_OUTPUT_IO_0=18, GPIO_OUTPUT_IO_1=19
* In binary representation,
* 1ULL<<GPIO_OUTPUT_IO_0 is equal to 0000000000000000000001000000000000000000 and
* 1ULL<<GPIO_OUTPUT_IO_1 is equal to 0000000000000000000010000000000000000000
* GPIO_OUTPUT_PIN_SEL 0000000000000000000011000000000000000000
* */
#define GPIO_INPUT_IO_0 CONFIG_GPIO_INPUT_0
#define GPIO_INPUT_IO_1 CONFIG_GPIO_INPUT_1
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
/*
* Let's say, GPIO_INPUT_IO_0=4, GPIO_INPUT_IO_1=5
* In binary representation,
* 1ULL<<GPIO_INPUT_IO_0 is equal to 0000000000000000000000000000000000010000 and
* 1ULL<<GPIO_INPUT_IO_1 is equal to 0000000000000000000000000000000000100000
* GPIO_INPUT_PIN_SEL 0000000000000000000000000000000000110000
* */
#define ESP_INTR_FLAG_DEFAULT 0
static QueueHandle_t gpio_evt_queue = NULL;
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void gpio_task(void* arg)
{
uint32_t io_num;
for (;;) {
if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
}
}
}
void app_main(void)
{
//GPIO出力ピン設定---------------------------------------------------------------------
//zero-initialize the config structure.
gpio_config_t io_conf = {};
//disable interrupt
io_conf.intr_type = GPIO_INTR_DISABLE;
//set as output mode
io_conf.mode = GPIO_MODE_OUTPUT;
//bit mask of the pins that you want to set,e.g.GPIO18/19
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
//disable pull-down mode
io_conf.pull_down_en = 0;
//disable pull-up mode
io_conf.pull_up_en = 0;
//configure GPIO with the given settings
gpio_config(&io_conf);
//GPIO入力ピン設定-------------------------------------------------------------------
//interrupt of rising edge
io_conf.intr_type = GPIO_INTR_POSEDGE;
//bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
//set as input mode
io_conf.mode = GPIO_MODE_INPUT;
//enable pull-up mode
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
//change gpio interrupt type for one pin
gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
//create a queue to handle gpio event from isr
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
//start gpio task
xTaskCreate(gpio_task, "gpio_task_example", 2048, NULL, 10, NULL);
//割り込み関数------------------------------------------------------------------------
//install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
//remove isr handler for gpio number.
gpio_isr_handler_remove(GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin again
gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
printf("Minimum free heap size: %"PRIu32" bytes\n", esp_get_minimum_free_heap_size());
int cnt = 0;
while (1) {
printf("cnt: %d\n", cnt++);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
}
}