Tech Note 03c: Serial CommunicationsJanuary 29, 2007© NSB Corporation. All rights reserved. |
There is additional documentation on Microsoft's website.This TechNote describes Microsoft's Serial control for Windows CE. There is also a new third party control with additional features available from Franson. It includes support for Bluetooth and has many other improved features. There is some sample code using this control at the end of this Tech Note.
Serial communications are straightforward in NSBasic/CE. They make use of Microsoft's standard COMM control. Make sure it is installed on your Windows CE device and that it is properly set up in the Registry.
Communications are controlled completely by setting properties in the Comm object. These properties control port setting and are used to input and output characters.
If the Comm object needs to send information back to your program, it will call a subroutine in your program coalled Comm_onComm. This subroutine (which has no arguments) can then check the comm.commEvent property to see why there was a callback. The most common reason is to notify the program that there are characters in the input buffer.
Remember to turn off Communicate with PC in the Communication settings panel. Otherwise, you will be unable to open the port as Windows CE will already have it open.
To initialize the Comm object, put the following line in your program. If you do not supply the full list of arguments, onComm will not be called.
addObject "Comm","comm",0,0,0,0
Notes
From Kostas BouzianasIn text mode In/Out buffers represented as strings. In binary mode they are represented as BYTE arrays This can be checked with VarType(Comm.Input or Output) when put Comm.InputMode=0/1 (I did not imagine how useful VarType was before). The problem is that due to VBScript's fuzzy declaration of variables, I could not strictly define a byte array (loss of As Byte), even in most obvious function like Array(cbyte(&HXX),....). Checking by VarType returns 8204 which is array with variant subscripts.
In such a way, Output does not run (OutBufferCount: 0, no OnComm events) while input usually gives a Type mismatch Error.
Finally, transmission/reception on Binary mode was affected by doing the following.:
InputMode=0 'Text
NullDiscard=False
Transmission: Conversion of bytes to transmit with CHR function Concatenation of bytes in a string variable (transmission of all bytes at once)
Reception: InputLen=1 (reception byte by byte) Conversion of received strings to numbers by using ASC function and storage in array.
For those developing for peripheral devices: Your application may run but low level signals of handheld may not trigger RS232 port of your peripheral. Make a respective application in desktop for testing.
From Juan Garlos Garrido
I read the note by Kostas Bouzianas, and he said that the only way of working with comm control in binary mode is setting inputlen by 1, and receive char by char, and this is not really true.
The ".input" comm Method returns a byte array, and the only thing you have to do is assign it to a variant and then use it as an array. I've been doing it with my old 2.10 version and works fine. (of course, inputlen is 0 in order to receive all characters avalaible)
Here is a sample that demonstrates it (extracted from one of my programs). It is a function that receives a packet. Constants for Start timeout, character timeout, and function result must be defined outside of the function. Com_port is the comm. Control created and opened outside of the function.
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 Tim = Tim + 1 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
Properties
comm.commEvent |
The integer code of the last event. Read only. |
comm.commID |
The handle of the comm device. Read only. |
comm.commPort |
The comm port (as in com1, com2...). Integer. For example, on a Casio PPC, set this value to 1. |
comm.DSRHolding |
State of the DSR line. |
comm.DTREnable |
State of DTR line. True or false. |
comm.Handshaking |
Handshaking protocol |
comm.inBufferCount |
Number of characters in input buffer. Read only. |
comm.input |
Returns characters from input buffer and clears it |
comm.inputLen |
Number of characters comm.input will return |
comm.inputMode |
Type of input |
comm.nullDiscard |
Should null chars be discarded? true or false. |
comm.output |
Output string. Write only. |
comm.OutBufferCount |
Number of characters in output buffer. Read only. |
comm.portOpen |
Opens and closes port. |
comm.RThreshold |
Number of receive characters before onComm event triggered. |
comm.Settings |
A string of the format "BBBB,P,D,S", where BBBB is the baud, P is the parity, D is the number of data bits, and S is the number of stop bits. The default value is "9600,N,8,1" |
comm.sThreshold |
Number of send characters before onComm event triggered. |
comm.RTSEnable |
State of RTS line. True or False. |
comm.settings |
baud, parity, databits, stopbits in a string. |
CommEvent Errors
Constant |
Value |
Description |
comNoError |
0 |
No Error. |
comEventBreak |
1001 |
A break signal was received. |
comEventCTSTO |
1002 |
Clear To Send Timeout. The Clear To Send line was lower than the system- specified amount of time used when transmitting a character. |
comEventDSRTO |
1003 |
Data Set Ready Timeout. The Data Set Ready line was lower than the system specified amount of time used when to transmitting a character. |
comEventFrame |
1004 |
Framing error. The hardware detected a framing error. |
comEventOverrun |
1006 |
Port overrun. A character was not read from the hardware before the next character arrived and was lost. |
comEventCDTO |
1007 |
Carrier detect timeout. The carrier detect line was low for the system specified amount of time while trying to transmit a character. Carrier detect is also known as the receive line signal detect. |
comEventRxOver |
1008 |
Receive buffer overflow. There is no room in the receive buffer. |
comEventRxParity |
1009 |
Parity error. The hardware detected a parity error. |
comEventTxFull |
1010 |
Transmit buffer full. The transmit buffer was full when trying to queue a character. |
comEventDCB |
1011 |
Unexpected error retrieving device control block for the port. |
CommEvent Events
Constant |
Value |
Description |
comEvSend |
1 |
There are fewer than SThreshold number of characters in the transmit buffer. |
comEvReceive |
2 |
Received RThreshold number of characters. This event is generated continuously until you use the Input property to remove the data from the receive buffer. |
comEvCTS |
3 |
Change in Clear To Send line. |
comEvDSR |
4 |
Change in Data Set Ready line. This event is fired only when DSR changes from 1 to 0. |
comEvCD |
5 |
Change in carrier detect line. |
comEvRing |
6 |
Ring detected. Some universal asynchronous receiver-transmitters (UARTs) may not support this event. |
comEvEOF |
7 |
End Of File (ASCII character 26) character received. |
Example
This program will talk to a terminal emulation program, such as HyperTerminal, running on a PC using the standard synch connnection. There are a few setup things to keep in mind so the program will work.
1. On your device, go into Settings...Communication Properties...PC Connection. Make sure the box "Allow connection with desktop computer when H/PC is attached is not checked.
2. On your PC, make sure ActiveSync is not enabled.
3. Set your terminal emulator for a local connection to the serial port your device is plugged into. Make sure baud, parity, databits and stop bits are all set the same as shown in Properties when running the following program. Also, make sure the handshaking is set the same way.
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
Sample using Franson Serial Control
'Contributed by Michael Newett 'This example works for Pocket PC or Desktop devices, with any length 'of file, any baudrate, serial or bluetooth. 'Note** The devices (PDA or desktop) Bluetooth must be turned ON 'before running the code. 'For CE Device use the following AddObject "serialce.port.1","objPort" 'For CE Device AddObject "serialce.license","objlicense" 'For CE Device 'For WindowsXP Device use the following AddObject "serialxp.port.1","objPort" AddObject "serialxp.license","objlicense" 'For all devices objLicense.LicenseKey = "xxx Enter license key here xxx" Form1_Load Sub StartCommandButton_Click objPort.BaudRate = 9600 objPort.ComPort = 8 'enter bluetooth outbound COM port number here objPort.ByteSize = 8 objPort.Parity = 0 objPort.StopBits = 0 '0 means 1 stop bit objPort.Enabled = True 'enable comm. port objPort.NoEvents = True objPort.DTR = True objPort.RTS = True Sleep 100 'delay to enable comm port to initialise End Sub Sub StopCommandButton_Click objPort.Enabled = False 'disable comm port End Sub Sub WriteCommandButton_Click objPort.Write "Enter String to Write here"+vbCr 'Send command to device. Add vbCr or vbLf as applicable Finished=False Str="" Do until Finished=True Size=objPort.Buffersize 'get number of bytes received from device Newstr=objPort.Read(Size,1000) 'read response from device. Timeout if nothing received after 1000ms If IsNull(Newstr) Then Finished=True Else Str=Str&Newstr End If Loop If IsNull(Str) Then Str="Device Timed out" Msgbox Str End Sub Sub Form1_load AddObject "CommandButton", "StartCommandButton", 75, 125, 100, 25 bStart.Caption = "Start Comms" bStart.FontSize = 8.25 AddObject "CommandButton", "StopCommandButton", 75, 225, 100, 25 bStop.Caption = "Stop Comms" bStop.FontSize = 8.25 AddObject "CommandButton", "WriteCommandButton", 75, 175, 100, 25 Write.Caption = "Write" Write.FontSize = 8.25 End Sub