今回はUARTのサンプル events を動かしてみます。
この記事は JTAG でデバッグすることを前提にして書いています。
環境構築については こちら をご覧になってください。
投稿時の開発環境を記しておきます。
PC:
Windows10 OS
開発ボード :
ESP32-DevKitCーVE
(Soc : ESP32-D0WD-V3)
デバッガー(H/W):
FT2232D
デバッガー (S/W) :
Visual Studio Code + PlatformIO + ESP-IDF Framework
概要
ブロック図を載せておきます。

デバッガー FT2232D は USBシリアルポートを2つ持っていて、JTAGデバッッグの他にシリアル通信を行うことができます。
これによりMonitorとは別に、PCとESP32間でUARTを使うことができます。
今回は Tera Term で COM n2 の通信ポートを使って ESP32 とつないで events プログラムを動かしてみます。
PCから送信したものを ESP32で受け取って、それをそのまま返信するという簡単なものです。
イベントの要因を区別して検出することができます。
プロジェクトをつくる
使っていたプロジェクトを開いていたら、File – Close Folder して閉じておきます。
その後にVSCodeからPlatformIOをOpenします。
以下の内容でプロジェクトを新規に作成します。
Name : ESP32E-UART-events
Board : Espressif ESP32 Dev Module
Framework : Espressif IoT Development Framework
Name : ESP32E の “E” は Framework (Espressif IoT Development Framework)の頭文字を示しています。
(後から見てわかるように、ESP-IDFを使うことを明示しています)

次にplatformio.ini に以下の3行を追加して、 Ctrl + s で保存しておきます。
COM[4]の4の部分はデバイスマネージャーのポート(COMとLPT)で Silicon Labs CP210x から始まるCOMの番号を記述します。
debug_tool = minimodule
upload_port = COM[4]
monitor_speed = 115200
UARTのAPIリファレンスとサンプル
UARTのAPIは こちら を参照してください。
サンプルプログラムは こちら を参考にしました。
PlatformIOで Eresspsif IoT Development Framework を選択したことにより、以下のローカルフォルダからも参照可能なはずです。
C:\Users\xxxxx\.platformio\packages\framework-espidf\examples\peripherals\uart\uart_events
(xxxxxは皆さまのユーザー名)
コーディングする
main.c を以下のようにコーディングしてビルドしておきます。
//以降にコメント文をつけてみました。
UARTのAPIについては こちら をご覧ください。
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"
static const char *TAG = "uart_events";
// (1)Tera Termで送受信するUARTのピン番号を指定する
#define CONFIG_EXAMPLE_UART_TXD 23 // (1)
#define CONFIG_EXAMPLE_UART_RXD 22 // (1)
// (2)UART1を指定
#define EX_UART_NUM UART_NUM_1 // (2)
// (3)バッファのバイト数
#define BUF_SIZE (1024) // (3)
#define RD_BUF_SIZE (BUF_SIZE)
// (4)キューのハンドル
static QueueHandle_t uart0_queue;
static void uart_event_task(void *pvParameters)
{
// (5)イベント構造体
uart_event_t event;
// (6)通信用バッファの確保
uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
for(;;) {
// (7)イベントの待機
// (7)第3引数はタイムアウト時間の指定で、portMAX_DELAYは無制限の待ち
if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
switch(event.type) {
// (8)受信イベント
case UART_DATA:
ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
ESP_LOGI(TAG, "[DATA EVT]:");
uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size);
break;
// (9)FiFoのオーバーフロー
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow");
uart_flush_input(EX_UART_NUM);
xQueueReset(uart0_queue);
break;
// (10)バッファが一杯
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full");
uart_flush_input(EX_UART_NUM);
xQueueReset(uart0_queue);
break;
// (11)受信のブレーク信号
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break");
break;
// (12)パリティエラー
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error");
break;
// (13)フレーミングエラー
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error");
break;
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
vTaskDelete(NULL);
}
void app_main(void)
{
esp_log_level_set(TAG, ESP_LOG_INFO);
// (14)設定用の構造体
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_EVEN,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
// (15)ドライバーのインストール
uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
// (16)パラメーターの設定
uart_param_config(EX_UART_NUM, &uart_config);
// (17)UART1として使うピンの指定
uart_set_pin(EX_UART_NUM, CONFIG_EXAMPLE_UART_TXD, CONFIG_EXAMPLE_UART_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
// (18)イベント用スレッドの生成
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);
}
ビルドして実行してみる
ビルドエラーがないことを確認したら F5キーを押してデバッグモードに入ります。
タスクバーが青からオレンジ色にかわったら、もう一度F5キーを押してプログラムを動作させます。
PCで Tera Term を起動して(14) に合わせて通信パラメーターを設定します。
Tera Term から文字を送ると、それがそのまま返ってきます。
送った文字が2つ表示されれば成功です。
例えばバリティの設定を異なる値(evenからodd)に変更してみると、(12)のパリティエラーイベントを拾ってくれます。
コメント
通信速度やパリティの設定が合わないとエラーのイベントを受け取ります。
気をつけたいのは、エラーのイベントを受信したすぐ後に(8)受信イベント(UART_DATA)も受け取ることがあります。
一般的には、その際のデータは破棄するなどの処理が必要になります。
github esp32e-uart-events にプロジェクトをアップしましたので、よろしければご覧になってください。
( 環境: Visual Studio Code + PlatformIO + ESP-IDF Framework )