執筆者: 瀕死
最終更新: 2024/06/25
はじめまして、瀕死(ひんし)と申します。
現在私は部内のポップンコントローラーを修理しているのですが、その過程でつまずいた点などをしばらくの間は記事にしていこうと思っています。
初めての記事作成で至らぬ点などあるかもしれませんが、よろしくお願いいたします。
Mbed LPC1768においてWindows11とUSB経由でシリアル通信する方法について解説する。
MbedがWindows10以降においてシリアルポートとして認識されない問題は、公式サイトやフォーラム等に様々な情報が存在する。
情報源 | | 内容 | |
---|---|---|
| ドライバはWindows7のみ必要である | ||
| Windows7以外でもドライバが必要である | | これが当たり | |
| ST-LINKのドライバが必要である | ||
| ファームウェアアップデートが必要である |
他にも、Windows11のとあるサービスが原因であるという主張があったり、Windows11のレガシーデバイスとしてドライバを割り当てたりした。
そのため、かなりの時間と労力がかかった。本稿の読者がこのような苦労をしないことを願って執筆した。
printf
を用いる。公式サイトのドライバをインストールすると私の環境ではうまくいった。
以上の操作でシリアル通信できるようになっているはずである。
適切に認識された場合、デバイスマネージャーのポート(COMとLPT)の中にmbed serial portができる。
MbedのOSによってシリアル通信のためのクラスが異なる。
これからMbedでの開発を行う場合OS2は標準では使えないため、OS5かOS6を採用する必要がある。今回はOS6のBufferedSerialクラスを用いた。UnbufferedSerialは一般的な用途向きではないので注意しよう。
実は、Mbedはシリアル通信のクラスを使っていない場合はprintf
がUSBシリアルにリダイレクトされるので、これを使うと機能は少ないが簡単に実装できる。
UART(Universal Asynchronous Receiver/Transmitter, ユーアート)とは非同期にシリアル通信する方法の1つである。シリアル通信でほかに有名な方式としては、I2C(アイ・スクエアド・シー)やSPIなどがあるがどちらも同期式シリアル通信の方式である。
といった特徴がある。
ケーブルが2本で済むことは重要である。USB2.0TypeAにおけるピンは4つしかなく、2つはVBUS(+5V)とGNDで使用済みであるため、残りの2つで通信する必要があるからである。
シリアル通信の方式の比較として、以下の表を作成した。
通信方式 | | 同期/非同期 | | 全二重通信*-半二重通信 | | 構成 | | 相対的な通信速度 |
---|---|---|---|---|
SPI | | 同期 | | 全二重通信 | | 1マスタ-多スレーブ | | 速い |
I2C | | 同期 | | 半二重通信 | | 多マスタ-多スレーブ | | 中間 |
UART | | 非同期 | | 全二重通信 | | 1-1(方式上は対等) | | 遅い |
(*電子回路部分の構成等で半二重通信にもできる)
同期であればクロック用の信号線が必要であり、全二重通信であればデータ線は2本必要である。
通信の波形は以下のようになる。
上の表の何ビット目か | | 名前 | | 説明 |
---|---|---|
1 | | スタートビット | | 1bit の長さのLOWの信号を送信する |
2-9 | | データビット | | 指定された長さのbit列を送信する |
無し | | パリティビット | | 誤り訂正のためのbitで設定によってはないこともある |
10-11 | | ストップビット | | 1, 1.5, 2bitの指定されたいずれかの長さのHIGH信号を送信する |
I2CやSPIと違い同期式シリアル通信ではないので、データ線にも通信開始等の制御用データが入っていることがわかる。
#include "mbed.h"
// バッファサイズの設定
const size_t BUF_SIZE = 32;
// LEDのピン設定
static DigitalOut led(LED1);
// UARTのピンを設定 USBの場合は以下の定数を使う
static BufferedSerial serial_port(USBTX, USBRX);
int main(void)
{
serial_port.set_baud(9600); // 通信速度の設定
// 前の引数から、1回の通信のサイズ 単位:bit, パリティの有無, ストップビットの長さ
serial_port.set_format(8, BufferedSerial::None, 1);
// 入力用のバッファを宣言+初期化
char buf[BUF_SIZE] = {0};
// int write(char[] data, size_t data_size);で送信
serial_port.write("start\n", sizeof("start\n"));
while (true) {
// int read(char[] rx_buf, size_t buf_size);で受信
if (uint32_t read_size = serial_port.read(buf, sizeof(buf))) {
led = !led; // ledの状態を変更
serial_port.write("led: ", sizeof("led"));
if (led) serial_port.write("ON\n", sizeof("ON\n"));
else serial_port.write("OFF\n", sizeof("OFF\n"));
}
}
}
以上のコードをビルドして、LPC1768上で実行する。シリアルモニターでキーを打つたびに、LEDの発光状態が切り替わり、シリアルモニターにLEDの状態が表示される。
"A"をUARTで送信したときの波形を観察する。
#include "mbed.h"
// UARTのピンを設定
static BufferedSerial serial_port(p9, p10);
int main(void)
{
serial_port.set_baud(9600);
serial_port.set_format(8, BufferedSerial::None, 2);
while (true) {
serial_port.write("A", sizeof("A"));
}
}
目視で確認しやすいようにストップビットの長さを2bitに設定した。
Aだけを送信しているように見えて、Aと文字列終端として\0
を送信していることに注意する。
波形は以下のとおりである。
0x00はASCIIコードにおいて\0
であるから、正しく送信できていることがわかる。
読んでいただきありがとうございました。
次回はESP32 WROOM-32開発ボードをSPI Slaveとして用いる方法になる予定です。
この人が書いた記事