|
テクニカルノート04: シリアル通信April 2, 2003Copyright NS BASIC Corporation |
マイクロソフト社のドキュメントも参考にして下さい。
NS Basic/CE に於けるシリアル通信は、Microsoftの標準COMMオブジェクトを利用しており、すっきりとした分かりやすいものです。COMMオブジェクトがお使いのWindows CEデバイスにインストールされ、レジストリに正しく設定されていることを確認して下さい。
COMMオブジェクトのプロパティを設定することにより、通信の全てのコントロールを行います。これらのプロパティはポート設定をコントロールし、さらに、文字の入出力の為に使われます。
COMMオブジェクトは、プログラムにインフォメーションを送り返す必要がある場合は、comm_onCommサブルーチンを呼びます。その後、このサブルーチン(引数を持たない)は、comm.commEventプロパティをチェックし、なぜコールバックが上がってきたのかを確認します。最も一般的な理由は、入力バッファに文字があることを、プログラムに伝える為です。
コミュニケーション設定パネル内のCommunicate with PCの指定を外すことを忘れないで下さい。忘れた場合、Windows CEが既にポートを開いていた場合、それを開くことが出来なくなります。
COMMオブジェクトを初期化する為に、以下のラインをプログラム内に入れて下さい。ここに書かれている全ての引数を渡さない場合は、onCommは呼ばれません。
addObject "Comm","comm",0,0,0,0
From Kostas Bouzianas
テキストモードではIn/Outバッファーは文字列として認識します。バイナリーモードでは、これらはBYTE配列として認識します。これはComm.InputMode=0/1とした時にVarType(Comm.Input または Output)で確認できます。問題は、VBScriptの曖昧な変数宣言の為、確実にバイト配列を定義できないことです(Array(cbyte(&HXX),....)などの明らかな関数でも・・・)。VarTypeで確認すると8204(バリアント型の配列)を返します。
これですと、出力は動作しません(OutBufferCount: 0、OnCommイベント無し)。入力は通常タイプ不一致エラーになります。
最後に、バイナリーモードでの送信/受信は以下をすることによって影響されます。
InputMode=0 'Text
NullDiscard=False
送信:CHR関数で送信するバイトを変換
1つの文字列変数でバイトの連結(全てのバイトを1度に送信)
受信:InputLen=1 (1バイト単位で受信)
ASC関数を使って受信した文字列を数値に変換し、配列に保管
周辺機器用の開発をしている方へ:あなたのアプリケーションは動作するかもしれませんが、ハンドヘルドの低レベル信号は、周辺機器のRS232ポートを呼ばないかもしれません。テストの目的で、デスクトップ上でアプリケーションを作ると良いでしょう。
From Juan Garlos Garrido
Kostas Bouzianasのメモを読みましたが、バイナリーモードでcommコントロールを動作させる唯一の方法はinputlenを1にセットし、1バイト毎に受信すると言っていますが、これは正しくないようです。
commの".input"メソッドはバイト配列を返します。あなたがしなくてはならないのは、これをバリアントに代入し、配列として使用します。わたしはこれをバージョン2.10で試し、問題なく動作しました。(もちろん、全ての文字を受信する為に、inputlenは0です。)
以下は、私のプログラムから抜き出したサンプルプログラムです。これは1つのパケットを受信する関数です。スタートタイムアウト、キャラクタータイムアウト、および関数結果の定数はこの関数の外で定義しなければなりません。Com_portはcommです。オブジェクトは関数の外で作成され開かれていると仮定しています。
Function Receive(nr,s) 'Receives a packet, stopping when nr characters are received or timeout 's contains the packet received, and the function returns 'Result_err_TOUT or Result_OK constants 'Timeout for first character= st_tout* 20 ms 'Timeout betwen characters= c_tout* 20 ms 'st_tout and c_tout are global constants Dim B 'pointer to input buffer Dim ncr, i,Tim On Error Resume Next Tim=1 Do 'Waits until some characters are avalaible sleep (20) ncr = com_port.InBufferCount Tim=Tim+1 Loop Until (ncr > 0) Or (tim>st_tout) s = "" If ncr = 0 Then 'time-out receive = Result_err_TOUT Exit Function Else 'there are characters in the buffer B = com_port.Input For i = 0 To ncr - 1 s = s & Chr(b(i)) Next End If Tim=1 Do Until (Len(s) >= nr) Or (Tim>c_tout) ' Receives full packet sleep(20) ncr = com_port.InBufferCount If ncr > 0 Then Tim=1 'Resets timeout timer B = com_port.Input For i = 0 To ncr 1 'get all characters from input buffer s = s & Chr(b(i)) Next End If Loop Erase B ' dispose memory of input buffer If Len(s) >= nr then 'Reception completed receive = Result_OK ' Pck Else receive = Result_err_TOUT 'Tout End If End Function
プロパティ
comm.commEvent |
最後のイベントの整数コード。書き込み禁止。 |
comm.commID |
commデバイスのハンドル。書き込み禁止。 |
comm.commPort |
commポート(com1, com2, ...)。整数。Casio PPCの例、この値を1に設定。 |
comm.DSRHolding |
DSRラインの状態。 |
comm.DTREnable |
DTRラインの状態。True または False。 |
comm.Handshaking |
ハンドシェークプロトコル(handshaking protocol) |
comm.inBufferCount |
入力バッファ内の文字数。書き込み禁止。 |
comm.input |
入力バッファからの文字を返し、バッファをクリア。 |
comm.inputLen |
comm.inputが返す文字数。 |
comm.inputMode |
入力タイプ |
comm.nullDiscard |
null文字を排除すべきか? true または false。 |
comm.output |
出力文字列。書き込み専用。 |
comm.OutBufferCount |
出力バッファ内の文字数。書き込み禁止。 |
comm.portOpen |
ポートの開閉 |
comm.RThreshold |
onComm イベントが引き起こる前に受け取る文字数。 |
comm.Settings |
"BBBB,P,D,S"にフォーマットされた文字列。BBBBはボー(baud)、Pはパリティ(parity)、Dはデータビット数、Sはストップビット数。デフォルト値は "9600,N,8,1"。 |
comm.sThreshold |
onComm イベントが引き起こる前に送る文字数。 |
comm.RTSEnable |
RTSラインの状態。True または False。 |
comm.settings |
文字列内のボー、パリティ、データビット、ストップビット。 |
CommEvent エラー
定数 |
値 |
内容 |
comNoError |
0 |
エラー無し |
comEventBreak |
1001 |
ブレークシグナルを受信した |
comEventCTSTO |
1002 |
Clear To Send Timeout. Clear To Sendラインが文字を送信する時に使われるシステム定義された時間より短い。 |
comEventDSRTO |
1003 |
Data Set Ready Timeout. Data Set Readyラインが、文字を送信する時に使われるシステム定義された時間より短い。 |
comEventFrame |
1004 |
Framing error. ハードウェアがフレームエラーを検出した。 |
comEventOverrun |
1006 |
Port overrun. 次の文字が届いた時に、前の文字がハードウェアから読まれておらず失われた。 |
comEventCDTO |
1007 |
Carrier detect timeout. Carrier detectラインが文字を送信する時に使われるシステム定義された時間より短い。Carrier detectは、receive line signal detectとも呼ばれる。 |
comEventRxOver |
1008 |
Receive buffer overflow. 受信バッファーがオーバーフロー。 |
comEventRxParity |
1009 |
Parity error. ハードウェアがパリティーエラーを検出した。 |
comEventTxFull |
1010 |
Transmit buffer full. 文字をキューに入れようとした時、送信バーファーが一杯だった。 |
comEventDCB |
1011 |
ポート用のデバイスコントロールブロック取得時に予期せぬエラーが発生した。 |
CommEvent イベント
定数 |
値 |
内容 |
comEvSend |
1 |
送信バッファーにはSThreshold以下の数の文字がある。 |
comEvReceive |
2 |
RThreshold長の文字を受信。Inputプロパティを使って受信バッファーからデータを抜き取るまで、このイベントは継続的に発生する。 |
comEvCTS |
3 |
Clear To Sendラインに変更 |
comEvDSR |
4 |
Data Set Readyラインに変更。このイベントはDSRが1から0に変更された時にのみ発生する。 |
comEvCD |
5 |
Carrier detectラインに変更。 |
comEvRing |
6 |
リングを検出。いくつかのuniversal asynchronous receiver-transmitters (UARTs)はこのイベントをサポートしない。 |
comEvEOF |
7 |
End Of File (ASCII character 26) 文字を受信。 |
Example
このプログラムは、標準同期接続を使用してPC上で動作している、HyperTerminalなどのターミナルエミュレーションプログラムと対話します。プログラムが正常に動くように、いくつかの設定が必要ですので、心に留めておいて下さい。
1. デバイス上で、Settings...Communication Properties...PC Connectionと操作して下さい。"Allow connection with desktop computer when H/PC is attached"がチェックされていない事を確認して下さい。
2. PC上で、 ActiveSyncがアクティブ状態にないことを確認して下さい。
3. ローカル接続用に、ターミナルエミュレータをデバイスが接続しているシリアルポートにセットして下さい。以下のプログラムを実行する時、ボー(baud)、パリティ(parity)、データビット(databits)、ストップビット(stopbits)をプロパティに書かれているのと同様に設定して下さい。また、ハンドシェークも同様に設定して下さい。
rem Demonstrate serial communications
'see Tech Note for complete details
Option Explicit
dim selection,myString
addObject "comm","comm",0,0,0,0
selection=0
myString=""
while selection<>9
selection=inputbox("Choose Operation:" & chr(13) & "1. Open" & chr(13) & "2. Write" & chr(13) & "3. Properties " & chr(13) & "4. Read" & chr(13) & "5. Close" & chr(13) & "9. End Program", "COMM Demo")
select case selection
case 1
open_click
case 2
write_click
case 3
properties_click
case 4
read_click
case 5
close_click
case else
selection=9
Comm.PortOpen = 0
end select
wEnd
Private Sub Close_Click()
Comm.PortOpen = 0
End Sub
Private Sub Comm_OnComm()
Dim InString
Select Case Comm.CommEvent
Case 2 ' character In - collect until return is received
InString = Comm.Input
if asc(InString)=13 then
msgBox myString
myString=""
else
myString=myString & InString
end if
case else
msgbox "Other CommEvent Received:" & comm.commEvent
End Select
End Sub
Private Sub Read_click()
dim sRead
sRead=comm.input
msgbox sRead
end Sub
Private Sub Open_Click()
Comm.Rthreshold = 1 'event on every character in
Comm.InputMode = 0 'text mode
Comm.handshaking=1 '0=none, 1=XON/XOFF, 2=HW
Comm.RTSEnable=true
comm.DTREnable=true
Comm.PortOpen = True
if err<>0 then
msgbox "Open Comm: " & err.description
err.clear
end if
End Sub
Private Sub Write_Click()
Dim myString
myString = "This is being sent from CommCtl Test."
Comm.Output = myString
End Sub
Private Sub properties_click()
dim sOut, tab, CR
tab=chr(9)
CR=chr(13)
sOut="CommEvent:" & chr(9) & comm.commEvent & space(40) & CR
sOut=sOut & "CommID:" & tab & comm.commID & tab & "InputLen:" & chr(9) & comm.inputLen & CR
sOut=sOut & "CommPort:" & tab & comm.commPort & tab & "InputMode:" & comm.inputMode & CR
sOut=sOut & "Handshaking:" & tab & comm.Handshaking & tab & "CTSHolding:" & CR
sOut=sOut & "InBufferCount:" & tab & comm.inBufferCount & tab & "DSRHolding:" & comm.DSRHolding & CR
sOut=sOut & "OutBufferCount:" & comm.OutBufferCount & tab & "DTREnable:" & comm.DTREnable & CR
sOut=sOut & "PortOpen:" & tab & comm.portOpen & tab & "RTSEnable:" & comm.RTSEnable & CR
sOut=sOut & "RThreshold:" & tab & comm.RThreshold & tab & "NullDiscard:" & comm.nullDiscard & CR
sOut=sOut & "Settings:" & comm.settings
msgbox sOut,0,"COMM Properties"
end Sub