Friday, July 25, 2008

c# serial port data download

I recently posted a link to very good tutorial on communication with serial port using .Net c#.

In terms of the structure, the tutorial demonstrate the way to send command, and register SerialDataReceivedEventHandler
to handle DataReceived event.

The point I want to make is because it is a separate thread, if you wanted to change UI in that thread, Invoke delegate functions.
In addition, communication with serial port will involve CRC checking. So, before you do any thing to the data, check it.
Normally, you might need to send multiple commands to the port. You should send it by sequence, and send it before the previous command is handled. For example, check all the data is correctly received. If there are missing or error data, or even timeout, Resend the request command again. Finally, If you wanted to save data onto disk, You don't have to use asynchronous method, because the data received is very small, and in Windows, you won't enhance the performance of IO if your data block is less than 64K.

The final trick, don't use Thread.Sleep() in your GUI. Since you need to wait until the previous command is handled, doesn't mean you have to stuck in an infinite loop, or call Sleep to hang your GUI. You can simply create a timer to perform the checking and sending.


Thursday, July 24, 2008

c# Asynchronous read write file

Quite often, you need to perform IO in .Net.
It is very useful that when coding windows form application, you perform asynchronous actions. Nobody like a freezing UI.
http://www.devsource.com/c/a/Using-VS/Making-Asynchronous-File-IO-Work-in-NET-A-Survival-Guide/



static void asyncWrite()
{
byte[] data = new byte[BUFFER_SIZE];
FileStream fs = new FileStream("writetest.dat", FileMode.Create,
FileAccess.Write, FileShare.None, 1, true);
try
{
// initiate an asynchronous write
Console.WriteLine("start write");
IAsyncResult ar = fs.BeginWrite(data, 0,
data.Length, null, null);
if (ar.CompletedSynchronously)
{
Console.WriteLine("Operation completed synchronously.");
}
else
{
// write is proceeding in the background.
// wait for the operation to complete
while (!ar.IsCompleted)
{
Console.Write('.');
System.Threading.Thread.Sleep(10);
}
Console.WriteLine();
}
// harvest the result
fs.EndWrite(ar);
Console.WriteLine("data written");
}
finally
{
fs.Close();
}
}



c# CRC16 ccitt

While working with serial port, I was required to perform crc checking on data that I received.
I used the following code.



using System;
using System.Collections.Generic;
using System.Text;

namespace SerialPortTerminal
{
public enum InitialCrcValue { Zeros, NonZero1 = 0xffff, NonZero2 = 0x1D0F }

public class Crc16Ccitt
{
const ushort poly = 4129;
ushort[] table = new ushort[256];
ushort initialValue = 0;

public ushort ComputeChecksum(byte[] bytes)
{
ushort crc = this.initialValue;
for (int i = 0; i < bytes.Length; i++)
{
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}

public byte[] ComputeChecksumBytes(byte[] bytes)
{
ushort crc = ComputeChecksum(bytes);
return new byte[] { (byte)(crc >> 8), (byte)(crc & 0x00ff) };
}

public Crc16Ccitt(InitialCrcValue initialValue)
{
this.initialValue = (ushort)initialValue;
ushort temp, a;
for (int i = 0; i < table.Length; i++)
{
temp = 0;
a = (ushort)(i << 8);
for (int j = 0; j < 8; j++)
{
if (((temp ^ a) & 0x8000) != 0)
{
temp = (ushort)((temp << 1) ^ poly);
}
else
{
temp <<= 1;
}
a <<= 1;
}
table[i] = temp;
}
}
}
}





C# convert between int and byte array

BitConverter is a native way of converting int and byte[]. In fact, converting byte array into float(single in C#), double, Int16,Int32 etc....

For example:
int tmp = 10;
byte[] b = BitConverter.GetBytes(tmp);

// convert to float
byte[] b = new byte[4];
BitConverter.ToSingle(b, 0);

Depending on how you want the byte[] to be converted, BitConverter has whole lot functions to do that.Only to remember, if you are about to convert 8 bit byte array, you can simply cast it to int.

One interesting thing is that when you wanted to receive bytes from network, you might need to worry about big endian and little endian issue. I saw some hard solutions, but found a simple way of doing it.

byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
Array.Reverse(receiveBytes);

Enjoy

Tuesday, July 22, 2008

.Net C# serial port

http://msmvps.com/blogs/coad/archive/2005/03/23/SerialPort-_2800_RS_2D00_232-Serial-COM-Port_2900_-in-C_2300_-.NET.aspx

The above sample code is one of the best tutorial I have ever find discussing serial port programming using .Net. I recently been asked to download data from device through serial port.
To start with, I used the demo example to send simple command to the device and see whether the response is what I expected. Then I start working on my own application. Enjoy.