今回はUSBのVPCを使ってパソコンと通信してみました。
投稿時の開発環境を記しておきます。
( IDE & MX バージョンアップしました )
PC:Windows10 OS
IDE: STM32CubeIDE Version1.6.0
Configurator: STM32CubeMX Version6.2.0
Board: STM32Nucleo-F401RE
VCPとは
VCPとは Virtual COM Port (仮想COMポート)の略です。
マイコンボード等のUSBコネクタからUSBケーブルでパソコンとつなぎ、パソコンはCOMポートを選択して仮想的にRS232C等のシリアル通信を行う場合のCOMポートだと私は理解しています。
下図はマイコンペリフェラルのUARTを使い、USB-シリアル変換して VCP通信するブロック図です。
今回はマイコンペリフェラルにUSB-DEVICEを使うことで、USB-シリアル変換を省略してVCP通信を行います。
ブロック図は以下の通りです。
ハードウェア的なコストが下がるので魅力的ですね。
USBのコネクタ
上記NucleoボードにはUSBコネクタがないので、以下のものを準備してNucleoボードと接続しました。
接続を確認する
USBコネクタとNucleoボードは以下のとおりに接続します。
プロジェクトを作成する
IDEを起動し、File- New – STM32 Project を選択し、Target Selection ウィンドウが出たら Board Selector タブを選択し Boards List から NUCLEO-F401RE を選択し Next ボタンを押します。
Project 名に F401UsbVcp と入力し、Finishボタンを押します。
Initialize all peripherals with their default Mode ? と聞いてくるので Yesを押します。
This kind of project is associated with the STM32CubeMx perspective. Do you want to open this perspective now ? と聞いてくるので Yesを押します。
USBの設定を行う
Pinout & Configuration – Categories – Connectivity から USB OTG FS を選択し Mode で Device_Only を選択します。
GPIO Settings では PA11, PA12 が選択されていることを確認しておきます。
次に Categories – Middleware から USB DEVICE を選択し Mode – Class for FS IP で Communication Device Class (Virtual Port Com) を選択します。
VPC になっていますね 笑
クロックの設定
USBは48MHzのそこそこ精度の良いクロックを必要とするようです。
Clock Configuration でクロックを下図のとおりに設定します。
この設定を行わないと警告が出ます。
よく見えないので、2つに分割してみます。
左半分
右半分
この後ビルドしてエラーがないことを確認しておきます。
コーディングする
Project EXplorer – F401UsbVcp の下に USB_DEVICE フォルダが追加されています。
App の下の usbd_cdc_if.c をダブルクリックして開きます。
262行目あたりに CDC_Receive_RS()という関数があるので以下のようにコード( if()の近辺 )を追加します。
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
uint8_t sendBuf[64];
if (*Len && *Len < 64)
{
for (int i = 0; i < *Len; i++)
{
sendBuf[i] = Buf[i];
}
CDC_Transmit_FS(sendBuf, *Len);
}
return (USBD_OK);
/* USER CODE END 6 */
}
ビルドしてエラーがないことを確認し
Run - Debug - Resume でプログラムを動作させておきます。
環境をつくる
増設したUSBコネクタにUSBケーブルを挿し、パソコンとつなぎます。
パソコン側はいつものように Tera Term を起動します。
新しい接続 ウィンドウでシリアルを選択すると STLink Virtual COM Port以外にもうひとつUSBシリアルデバイスが見つかるので、そちらを選択します。
設定 - 端末 でローカルエコーにチェックを入れます。
通信パラメーターの設定は不要です。
相手のマイコン側がUARTではないので、なんとなくうなずけますね。
何かキーを押して、ボードからそのままその値が返ってくれば成功です。
コードの概要説明
説明というほどのものではありませんけれど、
たどっていくと CDC_Receive_FS() は割り込みサービスルーチンから呼ばれていることがわかります。
ですから、この中の処理は簡潔にかかなければなりません。
*Lenに値が入っていれば、*Bufからデータを取り出せばよいことになります。
CDC_Transmit_FS() で受信した電文をそのまま返しています。
いかがでしたか?
あのUSB通信が、ほとんど設定だけで動いてしまったので楽チンできました。