UARTとは
UART(Universal Asynchronous Receiver/Transmitter)は、ESP32で最も利用頻度の高い通信方式の一つです。
センサーやマイコン、PCとの通信だけでなく、RS-232やRS-485などのシリアル通信にも利用されます。
ESP32ではデバッグログの出力にもUARTが使用されており、開発では欠かせないインターフェースです。
UART通信の仕組み
UARTはクロック信号を使用しない非同期シリアル通信です。
送信側と受信側で同じ通信設定(ボーレートなど)を使用することで通信を行います。
一般的な設定は次の通りです。
- ボーレート:115200bps
- データ長:8bit
- パリティ:なし
- ストップビット:1bit
一般には 8N1 と呼ばれる設定です。
ESP32-C5で使用できるUART
ESP32-C5には複数のUARTが搭載されています。
一般的には
- UART0
- UART1
を使用します。
UART0は書き込みやログ出力にも使用されるため、
アプリケーション通信にはUART1を使用すると設計しやすい場合があります。
ただし、UART0でもGPIOを変更すればユーザー用途として利用可能です。
ESP-IDFで使用するUART API
ESP-IDFでは主に次のAPIを使用します。
| API | 内容 |
|---|---|
uart_driver_install() | UARTドライバ初期化 |
uart_param_config() | 通信条件設定 |
uart_set_pin() | GPIO設定 |
uart_write_bytes() | データ送信 |
uart_read_bytes() | データ受信 |
この5つを理解すれば、多くのUART通信は実装できます。
UART初期化
UART通信を開始する前に、
- ドライバのインストール
- 通信条件の設定
- GPIO設定
を行います。
サンプルコード
#include "driver/uart.h"
#include "esp_err.h"
#include "driver/gpio.h"
#define UART_PORT UART_NUM_1
#define TX_GPIO GPIO_NUM_4
#define RX_GPIO GPIO_NUM_5
#define RX_BUF_SIZE 1024
static void uart_init(void)
{
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT
};
ESP_ERROR_CHECK(
uart_driver_install(
UART_PORT,
RX_BUF_SIZE,
0,
0,
NULL,
0));
ESP_ERROR_CHECK(
uart_param_config(
UART_PORT,
&uart_config));
ESP_ERROR_CHECK(
uart_set_pin(
UART_PORT,
TX_GPIO,
RX_GPIO,
UART_PIN_NO_CHANGE,
UART_PIN_NO_CHANGE));
}
uart_driver_install()ではUARTドライバを有効化します。
uart_param_config()ではボーレートやデータ長など通信条件を設定します。
uart_set_pin()では送信・受信に使用するGPIOを指定します。
UART送信
UART送信はuart_write_bytes()を呼び出すだけです。
まずは送信部分だけを見てみましょう。
uart_write_bytes(
UART_PORT,
message,
strlen(message));
第1引数にはUART番号、
第2引数には送信データ、
第3引数には送信するバイト数を指定します。
const char *message = "Hello UART!\r\n";
uart_write_bytes(
UART_PORT,
message,
strlen(message));
UART受信
UART受信はuart_read_bytes()を使用します。
受信バッファを用意し、受信待ち時間(タイムアウト)を指定するだけで受信できます。
まずは受信部分だけを見てみましょう。
サンプルコード
uint8_t rx_data[128];
while (1)
{
int len = uart_read_bytes(
UART_PORT,
rx_data,
sizeof(rx_data),
pdMS_TO_TICKS(100));
if (len > 0)
{
printf("Receive %d byte(s): ", len);
for (int i = 0; i < len; i++)
{
printf("%02X ", rx_data[i]);
}
printf("\n");
}
}
uart_read_bytes第4引数には受信タイムアウト時間を指定します。
今回は100ms待機しています。
受信データがある場合は、受信バイト数が返ります。
双方向通信
送信と受信は同時に使用できます。
例えば、一定周期でデータを送信しながら、受信データを監視することも可能です。
サンプルコード
const char *tx_message = "UART TEST\r\n";
uint8_t rx_data[128];
while (1)
{
uart_write_bytes(
UART_PORT,
tx_message,
strlen(tx_message));
int len = uart_read_bytes(
UART_PORT,
rx_data,
sizeof(rx_data),
pdMS_TO_TICKS(100));
if (len > 0)
{
printf("Receive %d byte(s)\n", len);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
送信と受信は独立して動作するため、同じUARTポートでも問題なく使用できます。
UART通信でよくあるトラブル
ESP32でUART通信ができない場合は、次の項目を確認してみてください。
- TX/RXが逆になっていないか
- ボーレートが一致しているか
- GND同士が接続されているか
- GPIO設定が正しいか
- UART0をログ出力と共用していないか
UARTのトラブルは、配線ミスや通信設定の不一致が原因となることがほとんどです。
実務で使うポイント
今回のサンプルコードはUART通信の基本動作を理解するためのものです。
実際の製品開発では、さらに次のような処理を追加することが一般的です。
- リングバッファによる受信管理
- CRCチェック
- 通信タイムアウト監視
- パケット解析
- エラーリトライ
- FreeRTOSタスク分離
これらを実装することで、より安定したUART通信を実現できます。
まとめ
今回はESP32でUART通信を行う基本的な方法を紹介しました。
UART通信はESP32で最も利用頻度の高いインターフェースの一つです。
ESP-IDFでは
uart_driver_install()uart_param_config()uart_set_pin()uart_write_bytes()uart_read_bytes()
の5つのAPIを理解すれば、多くのUART通信を実装できます。
UARTを習得すると、RS-485やModbus RTUなどのシリアル通信にも応用できるため、組み込み開発の幅が大きく広がります。