Using PocketPC serial port
Can anyone give me some advice about using serial ports in VS2005 beta 2 on a pocket_pc. At first glance it seems easy, just declare an object as
System.IO.Ports.SerialPort with events and process the datareceived event. Simple enough. However, putting this code in a class and tring to generate an event based on the DataReveived event results in
"An unhandled exception of type ' System.NotSupportedException occured in System.Drawing.dll" the Additional Information states "Control.Invoke must be used to interact with controls created on a seperate thread".This really has me confused since when you look at the code included, I am not even intentionally using threads. The application files included - opens as serial port when the user clicks button1 (this works ok), when data comes in the byte is passed to the GotTimeMessage routine via a RaiseEvent statement. At the GotTimeMessage routine I try to increment the value in the text box on the form I receive the above error message.
I have tried looking up information on "control.invoke" but have had little luck. Even trying to dim GotTimeMessage as a delegate seems to give a syntax error.
I Have included both the form code and the Class I have written. The form has 2 buttons (Button1 & Button2) and a textbox (textbox1).
| |
Public Class Form1PublicWithEvents CommsAsNew PMI_COMMSPrivateSub Button1_Click(ByVal senderAs System.Object,ByVal eAs System.EventArgs)Handles Button1.ClickIf Comms.OpenComm(PMI_COMMS.PanelType.Firelite)Then Button1.BackColor = Color.GreenEndSubPrivateSub Button2_Click(ByVal senderAs System.Object,ByVal eAs System.EventArgs)Handles Button2.Click Comms.ClosePort() EndSubPrivateSub Comms_GotTimeMessage(ByVal bDataAsByte)Handles Comms.GotTimeMessage TextBox1.Text = Str(Val(TextBox1.Text) + 1) EndSubEnd Class' CLASS CODEImports System.IO.PortsPublic Class PMI_COMMSPublicWithEvents Comm1AsNew System.IO.Ports.SerialPortPrivate InData()AsBytePrivate m_WaitingAsBoolean =FalsePrivateWithEvents TimeOutTimerAsNew System.Windows.Forms.TimerPublic MasterFormAs FormPublic PortOpenAsBooleanPublicEvent GotTimeMessage(ByVal bDataAsByte)PublicEnum PanelType Main = 0 Firelite = 1 EndEnumPublicSubNew()TimeOutTimer.Interval = 400 TimeOutTimer.Enabled = FalseEndSubPublicSub ClosePort()If Comm1.IsOpenThen Comm1.Close()PortOpen = FalseTimeOutTimer.Enabled = FalseEndSubPublicFunction OpenComm(ByVal pPanelAs PanelType)AsBooleanIfNot Comm1.IsOpenThenIf pPanel = PanelType.FireliteThenComm1.DtrEnable = FalseWith Comm1.BaudRate = 9600 .Parity = IO.Ports.Parity.None .StopBits = IO.Ports.StopBits.One .DiscardNull = False' .ReadBufferSize = 1024.PortName = "COM1".DtrEnable = TrueEndWithElseWith Comm1.BaudRate = 19200 .Parity = IO.Ports.Parity.None .StopBits = IO.Ports.StopBits.One .DiscardNull = False' .ReadBufferSize = 1024.PortName = "COM1".DtrEnable = TrueEndWithEndIfTryComm1.Open() Comm1.DiscardInBuffer() Comm1.DiscardOutBuffer() Comm1.DtrEnable = TrueComm1.DiscardInBuffer() Catch exAs ExceptionMsgBox( "No Com", MsgBoxStyle.OKOnly)EndTryEndIfPortOpen = Comm1.IsOpen OpenComm = Comm1.IsOpen EndFunctionPrivateSub Comm1_DataReceived(ByVal senderAsObject,ByVal eAs System.IO.Ports.SerialDataReceivedEventArgs)Handles Comm1.DataReceivedDim InData(Comm1.BytesToRead - 1)AsByteDim ErrorStringAsStringTryComm1.Read(InData, 0, InData.Length) Catch exAs ExceptionErrorString = ex.Message EndTryIf InData.Length > 0Then'if we have dataForEach tAsByteIn InDataRaiseEvent GotTimeMessage(t)NextEndIfEndSubEnd ClassPublic Class PMI_InfoPublicEnum MMTypesNoComms Firelite MainModule NewMainModule EndEnumPublicEnum MMStatesNone GotCOMMS RunningTest Firing EndEnumPublic SystemTypeAs MMTypesPublic CurrentStateAs MMStatesPublicSubNew()SystemType = MMTypes.NoComms CurrentState = MMStates.None EndSubEnd Class
|
Any and all suggestions or idea's welcome at this time...Thanks,
[17034 byte] By [
BigBoom] at [2008-1-26]
Hi,
I'm not very familiar with VB (I work with C#) but the solution seems simple.
First at class level
Delegate Sub AddTimeMessage(myByte as Byte)
Public myDel as AddTimeMessage
Then at FormLoad:
myDel = New AddTimeMessage(AddressOf MyNewSub)
Then in your Comms_GotTimeMessage replcace the code with
Invoke(myDel,New Object() {bData})
And finally add a sub
Sub MyNewSub(bData as Byte)
TextBox1.Text = Str(Val(TextBox1.Text) + 1)
end sub
This should work!
Here a simple C# example that works for me (I get data from a GPs device)
Assume you have two Buttons on your form and one Textbox.
Further a SerialPort with the DataReceived Event handled in the form.
| |
public class Form1 : Form { public delegate void SetText(string strPar); public SetText myDelegate; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { myDelegate = new SetText(SetTheText); serialPort1.BaudRate = 4800; serialPort1.Handshake = System.IO.Ports.Handshake.None; } private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { string strErg=serialPort1.ReadExisting(); this.Invoke(this.myDelegate, new object[] { strErg }); } private void SetTheText(string strText) { textBox1.Text=strText; } private void btnOpen_Click(object sender, EventArgs e) { serialPort1.Open(); } private void btnZu_Click(object sender, EventArgs e) { serialPort1.Close(); } |
HTH
Manfred
Thank you ManniAT, that was all I needed.
Just a comment about this forum: I have been doing Hardware and Software design for 25+ years and have never had a forum be as helpful as this one. I have posted 2 questions to the forum and had the answer to both of them almost as fast as I could check....
Hi BigBoom,
you are welcome.
Also a word about forums in gernal.
I moderate a forum about fishes - and there most of the problems are solved.
Why? Because a lot of people are sharing their knowledge.
The special thing here is, that the "manufacturer" himself reads and answers the posts.
So forums (or any kind of such communities) are great.
But the thing with the "manufacurer" gives this community a big extra!
Cheers
Manfred
Hello,
I using wince 4.2 device terminal, an bluetooth usb adapter and a bluetooth enabled mobile printer device. I am using c#.net, coredll.dll(p/invoke). The mobile printer is running serial port service(standard serial port (SPP)device via bluetooth link).
I want to connect to the mobile printer from the device using bluetooth USB adapter.
I checked the boot peripheral setup settings. There are onboard 3 serial ports and all the three are being used.
OnBoard Serial Port1 2F8h/COM2
OnBoard Serial Port2 3F8h/COM1
OnBoard Serial Port3 3E8h/COM4
Available options for OnBoard Serial Port assignment are:
Auto
Disabled
3F8h/COM1
2F8h/COM2
3E8h/COM3
2E8h/COM4
1) I want to figure out if i can connect from the device terminal to printer using Bluetooth USB adapter on serial port. The device does not support active sync. It does not have any input/output for serial cable. It has two USBs to connect keyboard etc. I am using one of these USB for the Bluetooth USB adapter. There is a scale down version of bluetooth monitor which only allows me to serach the bluetooth devices around and creating a bond. There is not software feature which allows to connect serially to bluetooth enable printer device.
2) From c#.net i make calls to coredll.dll functions CreateFile, WriteFile and ReadFile
CreateFile returns me the handle, but WriteFile returns runtime error 1359(unable to write to COM3).
3) Opening ports and writing on these is second step. I am unable to figure out how to connect to the device to the printer(on serial port).
I used RegisterDevice function call(coredll.dll) and passed the printer address with COM7(no other COM# returns handle). This properly returns an handle.
Please help me.
Thanks and regards,
pkul
Hi,
Can I Ask you a question. Looks that I have a problem with the physical directions of the serial ports. COM1 goes to physical COM2 loosing my physical COM1 because a can′t call it. (I can′t call the COM0) so...
Do you know whats happenig?
Thanks
Antonio.
?
Windows CE often uses one of the serial ports for debug output. This is probably where your port is
going. R
emember that there's no such thing as a 'physical COM1 port'. There might be a port that's addressed on
your PC at 0x3E8, but that's not COM1 by any way except convention.
Windows CE allows you to call any base address any name you want,
basically. You can shift the names around at random or whatever you want
to do, if you're the device builder. In any case, which port names are
available is *entirely* the responsibility of the device vendor...
Paul T.
style="PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
Hi,
Can I Ask you a question. Looks that I have a problem with the physical
directions of the serial ports. COM1 goes to physical COM2 loosing my physical
COM1 because a can′t call it. (I can′t call the COM0) so...
Do you know whats happenig?
Thanks
Antonio.
Hi, thanks for respond me,
I’m going to tell you my entire problem.
The original application was made in Embedded BV. I did use the msCommCe.dll library and everything Works well, because y call the ports by the number (port=1). But when I migrated the application to .NET 2005 CF. I encountered the ports problem, because when I call “COM1” I open the COM2 and when I call “COM2” don’t know what’s opening, I plugged a device in COM1 and I had not response. I tried everything. Using the open source serial library, frameworks 1.1, 2, 2 SP1, just Java and Embedded works with the serial ports.
I don’t understand why .Net can’t work with that.
The PDA show me COM1, COM2, COM3, COM4 & COM5. But no one is the real COM1.
The PDA is a Unitech 950 with dock station (1USB, 2Serial, 1IR, 1BarsReader). PPC 2003.
Exits any library or something that I can use to call the address (0x0E8) or the port number?
Thanks Antonio
Hi. I was experimentingwith code ManniAT posted and have some problems with debugging it. serialPort1
is, I guess, some object that should be in System.IO.Ports however I get
serialPort1 does not exist in current context. Can you please help me
understanding this code.
I add
public class Form1 : Form {
public delegate void SetText(string strPar);
public SetText myDelegate;
public SerialPort serialPort1;
But looks like I didn't get it right. If someone post me code that will just give GPS position in textbox1 using the sempel code ManniAT posted I will be very happy to finaly understand how it is working.
Thanks
Aneo
Just wantedto add that I use Windows Mobile 5.0 and when I debug directly to my PDA using
this declaration:
public SerialPortserialPort1;
and in From1_Load I add
serialPort1.PortName ="COM3";
because my GPS unit is communicating on COM3.
When I'm trying to click on btnOpen I get
NullReferenceException
I guess my entire problem is noob but I have just stared exploring PDA
development.
Hi,
I simply dragged a Serialport from the toolbox on my form.
This (as well as the name used) is common when creating a simple sample.
Anyhow - if you want to do it by hand like Aneo you have to instantiate the port!
In Form.Load add the line:
serialPort1=new SerialPort.......
Regards
Manfred
Thanks for fasty Repaly :) But I didn't still figure it out.
This the code I use witch is exacly the same code Manfred poste:
sing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace DeviceApplication1
{
public partial class Form1 : Form
{
public delegate void SetText(string strPar);
public SetText myDelegate;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
myDelegate = new SetText(SetTheText);
serialPort1.BaudRate = 4800;
serialPort1.Handshake = System.IO.Ports.Handshake.None;
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string strErg = serialPort1.ReadExisting();
this.Invoke(this.myDelegate, new object[] { strErg });
}
private void SetTheText(string strText)
{
textBox1.Text = strText;
}
private void btnOpen_Click(object sender, EventArgs e)
{
serialPort1.Open();
}
private void btnClose_Click(object sender, EventArgs e)
{
serialPort1.Close();
}
}
}
I do as was told (drag and drop SerialPort to Form) and set Serial protName as COM4. I use Windows Mobile 5.0 so in Settings->System->GPS and set Hardwer port to COM4 and Program Port to COM1. All other GPS base Aplication detect my GPS working on COM4. When I deploy this application to my PDA everything looks great. Then when I click on Open button I notice that GPS receiver is working coz the LED is starting to blink as it should when the signal is right but still textBox1 stay as it is and there is no sign of GPS position or any thing. Pleas Help me to understand this.
Regards
Maciej
I guess this is some event handler so I should add it by some kindof clicking :) and all I didn't was just type in the code. If so can someone
help me locate where to click :P
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string strErg = serialPort1.ReadExisting();
this.Invoke(this.myDelegate, new object[] { strErg });
}
Hi,
simply right click the serial port in the forms desing view and choose "Properties".
There (properties window) select the events and at the "DataReceived" event select the existing function from the dropdown.
Regards
Manfred
Manfred youare Mother Teresa of all developers (big one as BigBoom and small one as I) Now
I just have to interpret the code received. I'm getting something like
5213.2375,N02100.4153,E,0,,,,
If anyone have any tips I will be glad to hearbut hopefully I solve this soon :) and post my Idea ASAP.
cheers
Aneo
Hi Aneo,
by looking at your data is seems that "Michalowice" is well known to you, isn't it 
Regards and good luck
Manfred
Should came Warsaw out of this

cheers
Aneo
Manfred maybe u know the wahy how to dealy reading from SerialPort or run it in a separate thread.
Hi,
it depends on what you want to achive.
One way is to handle the serial port via events.
In such an event you can than simply buffer the data or make some "first level processing".
For an example we have built a NMEA handling class. Such NMEA (a form of GPS data) starts wiht a $ sign and ends with a CR.
So we have some intelligent buffer which consumes the data from the serial port.
The reveice handler can than simply take the bytes from serial port and enter it into the buffer.
The buffer trigger for start / stop of a sentence - and if a complete sentence is found is parsed and a special event (XXXXSentenceGot) is fired.
If you don't want to handle events - or simply want to have a component which does the handling "in the background" you just start a thread which opens the port and does the rest.
One thing to consider:
Eventhandling is pretty easy but thread alow more isolation.
So you main up just instanciates the component, this registeres the event and starts a thread for handling the data.
If you get constant data (like in GPS) such a component can also check if the device is alive or.....
But don't forget about the two most essential things wiht threads:
Locking of shared data!!
And if you deal with the UI - use Control.Invoke if needed.
Regards
Manfred
Hi,
I wrote a GPS driver on WinCE 5.0 using Platform Builder 5. This driver uses COM1 as connection to the GPS hardware, and everything works fine.
I then had to move bach to WinCe 4.2, and the driver no longer works, what I see is that the Flow Control Commands (RTS ecc.) are working fine, but when I try to send data over the com port, the writefile functions returns no error, but no data are flowing throug the hardware.
I read the posts here, and looks like the debugger was trapping my requests but, I don't see the data on COM2, and also disabling the debugger (IMGNODEBUGGER=1) everything works on the same way.
Really thanks for any help in advance,
regards,
Fabio