プログラムと通信するための最もシンプルなUSBデバイスを作成します

独自のUSBガジェットを作成するというテーマを継続します。
シンプルなデバイスを作成します。

デバイスはPCに接続される予定であるため、デバイスとPC間のデータ転送が必要になる可能性が最も高いことを意味します。
ファームウェアとソフトウェアの接続を確立して、ファームウェアとソフトウェアの作成を始めましょう。

データを転送する最も簡単な方法は、USB通信デバイス(CDC)のクラスを使用することです。
この接続により、デバイスはシステムで通常の仮想COMポートとして表示されます。
この接続の利点は、独自のドライバーを作成する必要がないことです。
データの送受信も簡単です。Windowsのポートを操作するには、それをテキストファイルとして開き、通常の読み取り/書き込み操作を実行するだけです。


最小限のMKストラップで回路を取ります。



今回は、USBに4つの連絡先と1つのボタンのみを追加する必要があります(ボタンはブートローダーにのみ必要です:プログラマーのチップを再配置するよりも、USBを使用してデバイスのファームウェアを押して交換する方がはるかに簡単です)。



美しくしようと懸命に努力していないので、配線は次のようになります。



ただし、プラグインコンポーネントを頻繁に実験する場合は、arduinoの類似物であるJaluinoを作成して、各MKレッグをすぐに分割することをお勧めします。

ファームウェア


最小限から始めましょう:
include 18f2455 --
--
enable_digital_io () --
--
alias Button is pin_B7 -- ,
pin_B7_direction = input --
--
-- - USB CDC
include usb_serial -- usb
--
usb_serial_init () -- -- USB CDC
forever loop -- ,
usb_serial_flush () -- usb.
--
end loop


このコードをコンパイルし、結果のHEXファイルをブートローダーを使用してMKに書き込み、デバイスを起動すると、システムで新しいデバイスがどのように検出されるかを確認できます:仮想COMポート。



デバイスが既に動作しているので、通信するように教えます。

受信したバイトを読み取るusb_serial_read( byte :ブール関数があります。 バイトが受信されると、指定された変数に入力してtrueを返し、そうでない場合はfalseを返します

バイトを送信するためのusb_serial_dataプロシージャがあります。 変数として偽装されているため、バイトを送信するには、送信するバイトの値を割り当てるだけで十分です。

メインループの前にバイト変数を宣言し、メインループで受信したバイトをチェックし、もしあれば、それらを送り返します。

include 18f2455
--
enable_digital_io ()
--
alias Button is pin_B7
pin_B7_direction
= input
--
--
include usb_serial
--
usb_serial_init ()
var byte ch --
forever loop --
usb_serial_flush ()
if ( usb_serial_read ( ch ) ) then -- , ch
usb_serial_data = ch --
end if
end loop


コンパイル、ボタンを押したまま、電源を歪め、ブートローダーを起動し、ファームウェアを変更して起動します。
デバイスはシステムで再び定義されましたが、デバイスの動作をテストするためにソフトウェアが必要になりました。

私たちにはありませんが、既成の端末を使用しています。私はRealTermプログラムを使用しました。
目的の番号でポートを開き、データを送信します。


そして、私たちは送ったものを受け取ります。 したがって、すべてが正常に機能します。

ソフトウェア


したがって、マイクロコントローラーはバイトを受信し、すぐに送り返すことができます。 次に、通信するためのソフトウェアを作成します(Delphiを使用します)。

新しいプロジェクトを作成し、必要なコンポーネントをフォームに分散します:
SpinEdit1-ポート番号を指定します
Button1-接続を確立します
Button2-接続を切断します
SpinEdit2-バイトを10進数形式で入力するため
Button3-バイトを送信します
Memo1-受信した情報を表示します。

上記のように、通常のテキストファイルと同じ方法で、com-portを操作する必要があります。CreateFile、WriteFile、およびReadFile関数を使用します。

詳細を説明しないために、com-portを操作するための既製のライブラリ、ComPortを取り上げます。

各ボタンに必要なタスクを掛けて、最終的なコードを取得します。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics , Controls, Forms,
Dialogs, StdCtrls, Spin,ComPort;

type
TForm1 = class (TForm)
SpinEdit1: TSpinEdit;
Button1: TButton;
Button2: TButton;
SpinEdit2: TSpinEdit;
Button3: TButton;
Memo1: TMemo;
procedure OnRead(Sender: TObject; ReadBytes: array of Byte );
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
Port: TComPort;
public
{ Public declarations }
end;

var
Form1: TForm1;
num: integer;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
Port := TComPort.Create(SpinEdit1.Value, br115200); //
Port.OnRead := OnRead; //
Button2.Enabled := true ; //
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Port.Free; //
Button2.Enabled := false ; //
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if Button2.Enabled then Port.Write([SpinEdit2.Value]);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
if Button2.Enabled then
Port.Free;
end;

procedure TForm1.OnRead(Sender: TObject; ReadBytes: array of Byte );
var
i:integer;
begin
for i := Low(ReadBytes) to High(ReadBytes) do //
begin
Memo1.Text := Memo1.Text + '.' +InttoHex(ReadBytes[i],2); // HEX
inc(num); // -
end;
if num > 10 then begin
Memo1.Lines.Add( '' ); //
num := 0;
end;
end;

end.


開始、接続の確立、バイトの送信:



したがって、最も単純な端末は、最も単純なusbデバイスで動作する準備ができています。

ご覧のとおり、読み取りと書き込みはバイトの動的配列によって行われます。

受信した情報を処理し、現在のタスクに適した必要な交換プロトコルをコンパイルすることができます。

include 18f2455
--
enable_digital_io ()
--
alias Button is pin_B7
pin_B7_direction
= input
--
--
include usb_serial
--
usb_serial_init ()
var byte ch
var byte i --
forever loop --
usb_serial_flush ()
if ( usb_serial_read ( ch ) ) then --
case ch of --
0 : usb_serial_data = 0xff
1 : usb_serial_data = Button --
OTHERWISE block -- -
for 16 using i loop -- 10
usb_serial_data = ch + i -- ch ch+15
end loop
end block
end case
end if
end loop


追加機能


これで停止すると、ライブラリの使用例の詳細な説明が記載された通常の記事が得られますが、その中にはネットワークのオープンスペースに十分なものがあります。 したがって、もう少し詳細な情報を追加します。

データ送信の簡素化


1バイトで情報を送信することは必ずしも便利ではありません。 多くの場合、 印刷ライブラリが役立ちます。 これには、さまざまな形式のさまざまな長さのデータを送信するための手順が含まれています。バイト、16進数、10進数、ビン、ブール値は、プログラム内のデータの出力を単純化できます。

> include print
...
var dword data
print_dword_hex
( usb_serial_data , data )


すべてのコマンドの名前は、ライブラリファイルにあります。

PC接続を待っています


マイクロコントローラーのメインサイクルを開始する前に、まずPCとの接続を確立する必要がある場合は、その前に行を追加できます

while ( usb_cdc_line_status () == 0x00 ) loop
end loop


デバイスにポート番号をバインドします


そのままにしておくと、新しい接続ごとにシステムは最初の空きポート番号を割り当てます。 そして、これはあなたが常に彼に従う必要があることを意味します。
これを防ぐには、デバイスがusbライブラリを接続する前にシリアル番号に一意の値を割り当てる必要があります。
番号は任意の長さで、さまざまな文字を含めることができます。

const byte USB_STRING3 [ 24 ] =
{
24 , --
0x03 , -- bDescriptorType
"0" , 0x00 ,
"1" , 0x00 ,
"2" , 0x00 ,
"3" , 0x00 ,
"4" , 0x00 ,
"5" , 0x00 ,
"6" , 0x00 ,
"7" , 0x00 ,
"8" , 0x00 ,
"9" , 0x00 ,
"X" , 0x00
}


デバイス名を


ドライバーをインストールする前に、名前とシリアル番号を使用してアレイを宣言することにより、システムに表示されるデバイス名を変更できます。これは、USBライブラリを接続する前に行う必要があります。

const byte USB_STRING2 [ 28 ] =
{
28 , --
0x03 , -- bDescriptorType
"D" , 0x00 ,
"e" , 0x00 ,
"m" , 0x00 ,
"o" , 0x00 ,
" " , 0x00 ,
"B" , 0x00 ,
"o" , 0x00 ,
"a" , 0x00 ,
"r" , 0x00 ,
"d" , 0x00 ,
" " , 0x00 ,
"=" , 0x00 ,
")" , 0x00
}




ただし、ドライバをインストールした後、デバイスは名前を.infファイルで指定された名前に変更するため、ここでも名前を変更します
[文字列]
DESCRIPTION = "デモCDC"




デバイスの自動接続を整理します


悲しいかな、このタスクを達成する直接的な方法はないので、あなたは考えなければなりません。

まず、デバイスに一意のメーカーと製品の値を割り当てて、他の何百もの標準CDCファームウェアからデバイスを簡単に識別する必要があります。
denyuzhkuに対してVIDとPIDが発行されているため、中国人の道をたどります。明らかに自由な価値を静かに身につけてください。

ファームウェア:
ファームウェアでは、USBライブラリを接続する前に2つの変数を宣言する必要があります
const word USB_SERIAL_PRODUCT_ID = 0xFF10
const word USB_SERIAL_VENDOR_ID = 0xFF10

FF10の代わりに、任意の2ワード(2バイト)を挿入できます。 最終結果は添付のアーカイブに含まれています。

ドライバー:
ドライバーはVIDとPIDの組み合わせを対象としていないため、値を.infファイルに手動で追加します。

[DeviceList]
%DESCRIPTION%= DriverInstall、USB \ VID_FF10およびPID_FF10

[DeviceList.NTamd64]
%DESCRIPTION%= DriverInstall、USB \ VID_FF10およびPID_FF10


ソフト:
デバイスの接続/切断イベントをキャッチするには、ComponentUSBライブラリを接続します。 各行を説明する必要はないと思います。すべての変更は添付のドラフトで見ることができます。

結果


スクリーンショットで見分けることは困難ですが、接続されたデバイスが利用可能な場合にのみ送信ボタンがアクティブになり、50msごとにプログラムがボタンステータスを要求します(ただし、ボタンを押すとMKで処理されるため、これは間違っています)。



ご覧のとおり、USBを介したMKとPC間のデータ交換の整理は、最も難しいタスクではありません。 結果の接続は、最終目的だけでなく、プログラムのデバッグにも適しています。 結局のところ、計算の結果、レジスターと変数の現在の状態は、モールス信号のLEDのペアを点滅させるよりもはるかに明白です。

最後に、ムードランプのソースコードを調べることをお勧めします。 そこで、受信したデータを処理して便利な交換プロトコルを編成するための非常に良いオプションを見つけることができます。

PS
プロジェクトファイル

Source: https://habr.com/ru/post/J95925/


All Articles