USB CDC (STM32)

(2017.8.4 作成)

(2017.11.11 更新)

 STM32マイコンをRS-232C接続のデバイスのように使うためのCDCクラスを公開しています。(ダウンロードはこちら。CDCについてはこちら。ライブラリの使用法についてはこちらを参照ください)

 USBを使うに際してのコネクタの接続法やUSBライブラリを使用する固有の注意点もこちらのUSB HIDクラスの説明に記載がありますので、見てやってください。

 使用するには一点だけ注意していただきたい点があります。USBのバルク転送によりCDCは実現されているのですが、バルク転送ではバッファサイズいっぱいまでデータが詰め込まれて送られてくるとマスタ側は転送の途中だと判断し待機状態になります。このため通信の最後にサイズ0の通信を行ってマスタ側に転送終了を通知する必要があります。

 実際のコーディングについては、いろいろと書くより下のサンプルコードを見ていただくのが最もわかりやすいと思います。

関数リファレンス

コンストラクタ

プロトタイプ

UsbHid(int8_t (*DataReceive)(uint8_t *Data, uint32_t *Len) = 0,

        int8_t (*Init)(void) = 0,

        int8_t (*DeInit)(void) = 0);

戻り値

なし

引数

DataReceive

データ受信時に毎回呼び出されるコールバック関数を設定します。 Lenにはデータ長が格納されます

Init

コネクタが接続されたときに呼び出される関数です

DeInit

コネクタが外されたときに呼び出される関数です

備考

 

ホストへデータを送信する(ヘッダなしバージョン)

プロトタイプ

bool SendData(const uint8_t *data,

                       const uint8_t &length)const

戻り値 接続が確立しておらず、送信に失敗するとfalseが返ります
引数

任意のデータ

備考  

マスタへ転送終了を通知する

プロトタイプ

bool Flush()const;

戻り値

送信結果

引数

任意のデータ

備考  バッファサイズ(64kBとか)と同じサイズの通信を行う際にデータ転送終了を通知します。

サンプルコード

 以下のサンプルはSTM32F103C8T6基板を用いて通信を行うサンプルです。PC側のサンプルソフトと合わせて使用してください。

 プログラムの行っていることですが、PB6端子にスイッチを接続し、スイッチが押されるたびに押された回数をPCへ転送します。一方PC側からは基板のLEDのOn/Offを制御しています。


#include "DKS_UsbCdc.h"
#include "DKS_Common_F103xB.h"
#include "DKS_GPIO_F103xB.h"
#include "DKS_F103C8T6.h"

DKS::UsbCdc *cdc;
DKS::InterupptIn *button;
DKS::STM32F103C8T6 *board;
uint8_t c;

//PC -> STM32 通信
 int8_t DataReceive(uint8_t *buff, uint32_t *Len)
{
  board->led->write(buff[0]);
  return 0;
}

// STM32 -> PC 通信
 extern "C"
 void EXTI9_5_IRQHandler(void)
{
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6);
        uint8_t SendBuffer[2];
        if (button->Debounce(100)==0)
        {
                SendBuffer[0] = 0xf;
                SendBuffer[1] = c;
                c++;
                cdc->SendData(SendBuffer,2);
                cdc->Flush();
        }
}

int main(void)
{
        DKS::InitSystem();

        board=new DKS::STM32F103C8T6(DKS::BluePill);
        button = new DKS::InterupptIn(GPIOB, GPIO_PIN_6, DKS::Pull_Up, DKS::IT_Falling);
        cdc=new DKS::UsbCdc(DataReceive);

        c=0;

        while (1)
        {
        }
}