Silicon Laboratoriesのデバイスは、アマチュアサークルでは広く使用されておらず、Atmelなどの旗艦とはほど遠いものです。 ただし、TQFPパッケージには、単なる人間にとって非常にアクセスしやすいメインラインのマイクロコントローラーと、USB ToolStickスターターキット(最近
ハブで
言及されました )の両方があります。 私自身、マイクロプロセッサ技術に精通し、Silabsと協力して、非常に成功しました。
この記事では、USBインターフェースを使用してコンピューターとMKの接続を整理する方法と、Silabsが開発者にとってシンプルにする方法を説明します。
テストとして、USBハードウェアをサポートするF32xシリーズマイクロコントローラーを備えたC8051F320DKボードと、KeilのuVision4開発環境をそれぞれ使用します。
USB通信の実装に向けて掘り始める前に、プロトコルのいくつかの基本的な側面を決定する必要があります:デバイスがトポロジ内で占める位置(ホストまたはスレーブデバイス)と、インターフェイスを介して送信される情報の特性を決定します。
USBアーキテクチャでは、4つの基本的なデータ転送が可能です。
- コントロール転送 -接続中にデバイスを構成し、操作中にデバイスを制御するために使用されます。 このプロトコルは、保証されたデータ配信を提供します。
- 大量データ転送とは、配信および転送レートを遅らせる義務のない転送です。 アレイ転送は、他のタイプの伝送から解放されて、バス帯域幅全体を占有できます。 これらの送信の優先順位は最も低く、バスに大きな負荷がかかると一時停止します。 保証された配信-偶発的なエラーが発生した場合、繰り返しが実行されます。 配列転送は、プリンター、スキャナー、ストレージデバイスなどとのデータ交換に適しています。
- 割り込み転送 -本質的に自発的な短い転送であり、デバイスが必要とするよりもゆっくりとサービスを提供する必要があります。
サービス時間制限は、10〜255ミリ秒の範囲で設定されます。
低、フルスピードでは1〜255ミリ秒、ハイスピードでは125μsも注文可能です。 ランダム交換エラーの場合、再試行が実行されます。 割り込みは、たとえば、キーボードから文字を入力するとき、またはマウスの動きに関するメッセージを送信するときに使用されます。 - アイソクロナス転送-リアルタイムの連続送信、保証された配信遅延時間でバス帯域幅の事前に合意された部分を占有します。 これらを使用すると、1.023 MB / s(または0.5 MB / sで2つ)の帯域を持つチャネルをフルスピードで編成でき、利用可能な帯域の70%を占有します(残りは容量の少ないチャネルで埋めることができます)。 高速で、エンドポイントは最大24 MB / s(192 Mb / s)のチャネルを受信できます。 エラーが検出された場合、アイソクロナスデータは繰り返されません-無効なパケットは無視されます。 ビデオカメラ、デジタルオーディオデバイス(USBスピーカー、マイク)、オーディオおよびビデオデータを再生および記録するデバイス(CDおよびDVD)のストリーミングデバイスには、アイソクロナス転送が必要です。
MKをコンピューターに接続する場合、コントローラーは明らかにスレーブになります。
ジョイスティックのようなUSB互換HIDデバイスの作成
最も一般的で簡単に実装できるUSBデバイスのタイプは、HID(Human Interface Devices)です。 そのようなデバイスの標準である、使用される伝送のタイプは中断です。 このクラスの典型的な代表者は、USBキーボード、マウス、ジョイスティック、モニター設定パネル、バーコードリーダー、カードリーダーなどです。
HIDデバイスの利点は次のとおりです。
- 実装の容易さ。
- コンパクトなコード;
- Windowsサポート(追加のドライバーは不要)。
そのため、最も単純な
ジョイスティックマニピュレーターを実装します。 たとえば、ガレージで収集する戦闘ファー(!)用に2つ(またはそれ以上)のボタンが付いたスロットルスティックが必要です。 C8051F320DKデモボードには、1つの可変抵抗器と2つのボタンがあります-最低でも十分です。
Silabovtsyは、HIDインターフェースを備えたUSBマウスがエミュレートされるマイクロコントローラーファームウェアの例を提供します。 この例は、ほとんどのヒューマンインタラクションインターフェースを迅速かつ簡単に実装するのに十分です。 結果として、基礎となる例では、以下を処理する必要があります。
- HIDデバイス記述子の構成
- データ転送手順;
- HIDデバイス名記述子。
デバイス記述子で始まる
記述子は次の形式で必要です。
code const hid_report_descriptor HIDREPORTDESC =
{
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x02, // USAGE_PAGE (Simulation Controls)
0x09, 0xbb, // USAGE (Throttle)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x02, // USAGE_MAXIMUM (Button 2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
}
次に、何が起こっているのかを詳細に分析します。 将来のデバイスを説明する上で最も重要な部分は、データ型です。
シミュレーションコントロール (
コントロールのシミュレーション)セクションを記述する必要があります。このセクションでは、
スロットル (スロットルスティック)のみがあります。
- スロットルが機能する値の範囲はLOGICAL_MINIMUM(0)およびLOGICAL_MAXIMUM(255)です。
- この範囲のサイズ(1バイト)を設定します-REPORT_SIZE(8)および
- このタイプのコントロールの数はREPORT_COUNT(1)です。
ボタンの場合、同様のストーリー(USAGE_PAGE(
Button )):
- 値の範囲はLOGICAL_MINIMUM(0)およびLOGICAL_MAXIMUM(1)です。
- 範囲サイズ(1ビット)-REPORT_SIZE(1);
- ボタンの数は複数あるため、ここではバイト長フィールドを使用する必要があります。これはREPORT_COUNT(8)を意味します。
これはすべてオペレーティングシステムに必要です。これで、記述子を復号化キーとして使用して、コントローラーから受信する2バイトを処理する方法がわかります。
はい。また、.hには、hid_report_descriptor宣言の直前に次のような行があります。
#define HID_REPORT_DESCRIPTOR_SIZE 0x002C
#define HID_REPORT_DESCRIPTOR_SIZE_LE 0x2C00 //LITTLE ENDIAN
ここで重要なのは、記述子自体のコンパイル後に記述子のサイズを設定することであり、コントローラーがコンピューターによって認識されるように指定する必要があります。
記述子をコンパイルするタスクを簡素化するために、
www.usb.org (
HID Descriptor Tool )にあるプログラムを使用できます。 プログラムには、タスクに合わせて調整したり、独自のHIDデバイスを作成したりできるHIDデバイスの構成例が含まれています。
これでジョイスティックの説明は終了です。PCに転送するデータを準備する必要があります。
データ転送手順
例には次のコードがあります。
void IN_Report(void){
IN_PACKET[0] = VECTOR;
IN_PACKET[1] = BUTTONS;
// point IN_BUFFER pointer to data packet and set
// IN_BUFFER length to transmit correct report size
IN_BUFFER.Ptr = IN_PACKET;
IN_BUFFER.Length = 2;
}
この手順では、送信するパケットをコンパイルし、トリッキーポインターを介して送信します(実際は、ポインターの構造とその長さです)。 主なことは、コメントを暗示するように、パッケージを慎重に構成することです。そうすれば、参加せずにすべてがパッケージで行われます。
次に、VECTOR変数とBUTTONS変数を取得する方法と場所について説明します(両方とも、サイズがバイト単位のunsigned char型です)。
グローバル変数VECTORは、ADCからの割り込みの発生中にADCから値を割り当てられます。
void ADC_Conver_ISR(void) interrupt 10
{
AD0INT = 0;
//
if( VECTOR != ADC0H)
LED = 1;
else
LED = 0;
VECTOR = ADC0H;
}
同様に、グローバル変数BUTTONSは、ボタンの押下に応じて値を変更します。 ボタンはタイマーからの割り込みによってポーリングされます。 個人の好みに応じてタイマーを設定します。
void Timer2_ISR (void) interrupt 5
{
P2 &= ~Led_2;
if ((P2 & Sw1)==0) // #1
{
// pressed
BUTTONS = BUTTONS | (1<<0);
LED2 = 1;
}
else
{
// not pressed
BUTTONS = BUTTONS & 0xFE;
}
if ((P2 & Sw2)==0) // #2
{
// pressed
BUTTONS = BUTTONS | (1<<1);
LED2 = 1;
}
else
{
// not pressed
BUTTONS = BUTTONS & 0xFD;
}
TF2H = 0; // Timer2
}
HIDデバイス記述子
最後に、文字列データを調整して、デバイスに希望の名前を付けます(この例では、「JOYSTICK-HABR」)。
文字列記述子
String2Descを探しています。書き換えます
#define STR2LEN sizeof ("JOYSTICK-HABR") * 2
code const unsigned char String2Desc [STR2LEN] =
{
STR2LEN, 0x03,
'J', 0,
'O', 0,
'Y', 0,
'S', 0,
'T', 0,
'I', 0,
'C', 0,
'K', 0,
'-', 0,
'H', 0,
'A', 0,
'B', 0,
'R', 0,
};
HIDデバイスの識別
プロジェクトをコンパイルし、マイクロコントローラーをプログラミングしたら、デバイスをUSBポートに接続できます。 ホストは、デバイスがHIDクラスに属していると判断し、デバイスの制御を適切なドライバーに転送します。
Windowsで、[コントロールパネル]-> [ゲームデバイス]に移動し、乗客を確認します。 プロパティを見て、機能を確認します。
低速伝送速度は、デバイスのHIDバージョンの主な制限です。 このような交換の組織で可能な最大データ転送速度は64 Kbpsです。 このようなインジケータは、USBバスの最大速度の12 Mbpsと比較して、特定のUSB実装の選択に関してはHIDテクノロジーのマイナスのように見えます。 ただし、多くの通信タスクでは、指定された速度で十分であり、特殊なツールとしてのHIDアーキテクチャは、データ交換を整理する方法の中で正当な位置を占めています。
一般的に、HIDデバイスは、ほぼすべてのUSB対応MKに簡単に実装できます。 原則として、開発者の1つの実例で十分であり、必要な機能を取得できるものを調整します。
Silabs USBXpressツールを使用して本格的なUSBデバイスを作成する
しかし、MKでデバイスを操作するためにプロトコルを使用する必要があるときがきました。 同時に、大量のデータを高速で転送し、ラップトップですべてを実行したいと思います。そこでは多くのUSBがあり、単一のCOMではなく、あなたのデバイスでさえマッチボックスより大きくなく、チップ上のUSB-UARTボードに彫刻する必要がありますFT232RLは方法がありません。
その時、Silabsのスタッフは、誰もが生活を楽にし、「未来への道」を示すことを決めました。独自のfireとファームウェアを書くことについては歯を折ることはありません。
USBXpress開発キットは、MKおよびホスト(PC)向けの完全なソリューションであり、両方の高レベルAPIを使用してUSBプロトコルで簡単に操作できます。 USBプロトコル自体またはドライバー作成に関する特別な知識は必要ありません。 そのため、ガイドにシラビア人を書いてください。
Programmer's Guidといえば、占有するページはわずか30ページで、非常にシンプルで理解しやすいです。 私は個人的にこの例が好きではありません。非常に曲がった場所がよく見られます。PCのプログラムは一般に見ない方がいいです。
USBXpress DKは、C8051F32x、C8051F34xラインマイクロコントローラー、およびCP210x(USB-to-UARTブリッジコントローラー)用に提供されています。 USBXpressライブラリには、下位レベルのライブラリ、PC用のUSBドライバ、および上位レベルでアプリケーションを開発するためのDLLライブラリが含まれています。 そして、もちろん、ドキュメントと例のセット。
ライブラリは、BULKモードでのみデータ転送を実装します。 ライブラリのすべての機能を使用すると、それらの実装に必要なのは、マイクロコントローラの3 Kバイトのフラッシュメモリのみです。
ファームウェア
HIDの前の例と機能が似ている、多かれ少なかれ単純で理解可能な例を調べてみましょう。 PCアプリケーションには入りません。MKのファームウェアを完成させた後、すべてが明確になります。
したがって、TestPanelの例の本質は、マイクロコントローラーからADC(ポテンショメーター)と組み込みの温度計(
Temperature )の読み取り値を受け取り、ボタン(
Switch1Stateおよび
Switch2State )を押すことで、LED(
Led1および
Led2 )を
自分で点滅できる
ことです。
次に、必要な段階と考慮すべきデリケートな場所:
- USB記述子の作成。
- デバイスとUSBオンボードの初期化。
- 着信データの処理と発信パケットの生成。
- 割り込み処理。
ただし、最初に、プロジェクトを作成するときに、USB_API.h
ヘッダーファイルと
USBX_F320_1.libライブラリ自体を含めることを忘れないでください。
USB記述子の作成
巧妙に形式化された構造を持つHIDとは異なり、すべてがシンプルです
code const UINT USB_VID = 0x10C4;
code const UINT USB_PID = 0xEA61;
code const BYTE USB_MfrStr[] = {0x1A,0x03,'S',0,'i',0,'l',0,'a,0,'b,0,'s,0};
code const BYTE USB_ProductStr[] = {0x10,0x03,'U',0,'S',0,'B',0,'X',0,'_',0,'A',0,'P',0};
code const BYTE USB_SerialStr[] = {0x0A,0x03,'H',0,'A',0,'B',0,'R',0};
code const BYTE USB_MaxPower = 15;
code const BYTE USB_PwAttributes = 0x80;
code const UINT USB_bcdDevice = 0x0100;
VID、PID、および名前を使用すると、すべてが明確であることに加えて、MaxPowerパラメーター(最大電流= _MaxPower * 2)、PwAttributes-ホストのリモートウェイクアップに関与するパラメーター、およびbcdDevice-デバイスのリリース番号で最大電流を設定できます。
デバイスとUSBオンボードの初期化のニュアンス
ここで、MKが疲れることなくデータを送受信するメイン関数自体を開始します。
void main(void)
{
PCA0MD &= ~0x40; // Disable Watchdog timer
USB_Clock_Start(); // Init USB clock *before* calling USB_Init
USB_Init(USB_VID,USB_PID,USB_MfrStr,USB_ProductStr,USB_SerialStr,USB_MaxPower,USB_PwAttributes,USB_bcdDevice);
Initialize();
USB_Int_Enable();
...
ここで、解説が必要とするように、まず、初期化の前にUSBのクロックを初期化してから、MKの残りの開始操作を実行する必要があります-Initialize(); -ポート、タイマー、ADCを構成します。 次に、USB割り込みを有効にします。
着信データの処理と発信パケットの生成
ここで最も重要なことに行きます
//... main
while (1)
{
if (Out_Packet[0] == 1) Led1 = 1;
else Led1 = 0;
if (Out_Packet[1] == 1) Led2 = 1;
else Led2 = 0;
In_Packet[0] = Switch1State;
In_Packet[1] = Switch2State;
In_Packet[2] = Potentiometer;
In_Packet[3] = Temperature;
}
// main
}
Out_Packet-ホストから受信したパケット。
In_Packet-ホストに送信されたパケット。
本質は明確で、MKは送信されたパケットを常に更新し、受信したパケットのステータスを読み取ります。
割り込み処理
送信されたパケットから値を取得する場所について2ワードで説明します。 HIDの例のように、ボタンの状態はタイマーからの割り込みによって取得され、ADCと温度計の値はADCからの割り込みによって取得されます。
ここに微妙なポイントがあります-ADCの初期化中に、タイマーをオーバーフローさせることで値が変換されるように設定し(ボタンに使用するものと同じ)、変換が完了するとADC自体からの割り込みが発生します。 そして、ここでは、プロシージャの最後でコンバータ値を取得することに加えて、API関数を呼び出します
Block_Write(In_Packet、8)
収集されたデータをコンピューターに送信します。
コンピューターからのコマンドの受信は、USBからの割り込みを処理する手順で発生します。
void USB_API_TEST_ISR(void) interrupt 16
{
BYTE INTVAL = Get_Interrupt_Source();
if (INTVAL & RX_COMPLETE)
{
Block_Read(Out_Packet, 8);
}
if (INTVAL & DEV_SUSPEND)
{
Suspend_Device();
}
if (INTVAL & DEV_CONFIGURED)
{
Initialize();
}
}
この瞬間については、Programmer's Guidで詳しく説明しています。 一番下の行は、Get_Interrupt_Source()API関数が呼び出され、割り込みAPIの原因のコードを返すということです。 次に、コードが分析され、必要なアクションが実行されます。
PCプログラム
コンピューター用のプログラムを分解しません。 SilabovitesはVisual BasicおよびCの例を提供しましたが、ソースを見ることなく、開発環境でライブラリを接続し、複雑な機能に関するページを2、3回読むべきではありません。
したがって、例から既にコンパイルされたプログラムを使用します。
そのため、MK用にプロジェクトをコンパイルし、USBXpress用のユニバーサルドライバーを縫製してインストールし、デバッグボードを接続します。 システムは新しいデバイスを検出し、そのドライバーをインストールします。
インストール後に、Windowsデバイスマネージャーで何が行われているかを見てみましょう。
次に、プログラムを実行します。
彼女はデバイスを正しく見つけたことがわかります。
これで、ボタンを突く、ダイオードを点滅させる、MKの手を暖める、温度がどのように上昇するかを確認できるようになりました。
おわりに
一般に、USBXpressライブラリを使用してUSBデバイスを作成することは、HIDアーキテクチャを使用するよりも高速で透過的なプロセスであることが判明しました。 そして、速度は間違いなく高くなります。 最も薄い点は、ライブラリが閉じられていることであり、BULKデータ転送モードのみが利用可能であることに加えて、このソリューションがどれほど信頼できるかを知ることは不可能です。
使用されている有用なソース:
- Guk M.、PCハードウェアインターフェイス。 百科事典 -サンクトペテルブルク:ピーター、2002年-528秒
- クリリンA.I. USBインターフェイスを備えたSilicon Labsマイクロコントローラー。 電子部品マガジンNo. 5、2007
- PICコントローラーでのUSBインターフェイスの実用化
- SiUSBXpress Linuxドライバー