C#API读写串口问题

oushengfen 2010-03-03 04:13:48

由于我需要在wince下运行,不能使用重叠功能,现在出现读一直挂起(没有读到数据时)
        //打开串口
public int Com_Open(string ComSet, int BaudRate)
{

int hCommFile;
DCB dcb = new DCB();
COMMTIMEOUTS TimeOuts = new COMMTIMEOUTS();


hCommFile = CreateFile( ComSet,
GENERIC_READ | GENERIC_WRITE,
0, //{not shared}
0, //{no security ??}
OPEN_EXISTING,
0,
0 );

if(hCommFile == INVALID_HANDLE_VALUE)
{
throw(new ApplicationException("Comm Port Can Not Be Opened"));
}

// Is this a valid comm handle?
if(GetFileType( hCommFile ) != FILE_TYPE_CHAR)
{
CloseHandle( hCommFile );
//throw(new ApplicationException("File handle is not a comm handle "));
return INVALID_HANDLE_VALUE;

}

if(!SetupComm( hCommFile, 4096, 4096 ))
{
CloseHandle( hCommFile );
//throw(new ApplicationException("Cannot setup comm buffer"));
return INVALID_HANDLE_VALUE;
}

// purge any information in the buffer

PurgeComm( hCommFile, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

// Setting the time-out value
GetCommTimeouts( hCommFile, ref TimeOuts );

// The CommTimeout numbers will very likely change if you are
// coding to meet some kind of specification where
// you need to reply within a certain amount of time after
// recieving the last byte. However, If 1/4th of a second
// goes by between recieving two characters, its a good
// indication that the transmitting end has finished, even
// assuming a 1200 baud modem.

TimeOuts.ReadIntervalTimeout=500;
TimeOuts.ReadTotalTimeoutMultiplier=500;
TimeOuts.ReadTotalTimeoutConstant=5000;
TimeOuts.WriteTotalTimeoutMultiplier=500;
TimeOuts.WriteTotalTimeoutConstant=5000;

SetCommTimeouts(hCommFile, ref TimeOuts); // 设置超时

// Configure the comm settings.
// NOTE: Most Comm settings can be set through TAPI, but this means that
// the CommFile will have to be passed to this component.
GetCommState(hCommFile, ref dcb);

dcb.BaudRate = 28800;//BaudRate; // 波特率为
dcb.ByteSize=8; // 每个字符有8位
dcb.Parity = PAIRTY_EVEN; //奇偶校验
dcb.StopBits=ONESTOPBIT; //一个停止位

SetCommState(hCommFile, ref dcb);
Opened = true;
return hCommFile;

}

//写串口
public int ComReadFile(int ihCommFile, byte[] Readbuff, int ReadLen)
{
if (ihCommFile != INVALID_HANDLE_VALUE)
{
int NumberOfBytesTransferred = 0;
OVERLAPPED ovlCommPort = new OVERLAPPED();
if (ReadFile(ihCommFile, Readbuff, ReadLen, ref NumberOfBytesTransferred, ref ovlCommPort))//
{
if (ReadLen == NumberOfBytesTransferred)
{
return NumberOfBytesTransferred;
}
else return NumberOfBytesTransferred;

}
else return 0;
}
else return 0;
}

请问读,为何会挂起,我设置了超时,为何超时后不返回。我想超时后返回,如何写代码,注意,这是wince下使用,不是xp平台。
...全文
192 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
jcl007_ 2010-03-10
  • 打赏
  • 举报
回复
如何调用代码的代码你自已写了,我前边的这段代码是没问题的,在正式的工业产品中都使用好几年了,读写都正常。
oushengfen 2010-03-09
  • 打赏
  • 举报
回复
引用 2 楼 zhouzhangkui 的回复:
http://blog.csdn.net/solond/archive/2008/03/04/2146446.aspx


楼主,我使用你的类进行写时,总是不成功。为什么啊。
oushengfen 2010-03-09
  • 打赏
  • 举报
回复
public bool ComWriteFile(int ihCommFile, byte[] Writebuff, int WriteLen)
{
int BytesWritten = 0;
if (ihCommFile != INVALID_HANDLE_VALUE)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
PurgeComm(ihCommFile, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR);
if (WriteFile(ihCommFile, Writebuff, WriteLen, ref BytesWritten, ref ovlCommPort))
{
if (WriteLen == BytesWritten)
{
return true;
}
else return false;
}
else return false;
}
else
{
return false;
}
}
我在写的时候,这样会死机。还有一个问题,在wince下,打开串口,为何会得到负数的句柄.
oushengfen 2010-03-08
  • 打赏
  • 举报
回复
以上楼主没有考虑在读时,如果没有数据来,你的readfile会一直挂起的。

不过,能写得这么详细,还非常感谢。
jcl007_ 2010-03-04
  • 打赏
  • 举报
回复
// 关闭串口
public bool ClosePort()
{
try
{
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);

if (hComm == INVALID_HANDLE_VALUE)
{
return false;
}

if (CloseHandle(hComm))
{
hComm = INVALID_HANDLE_VALUE;
bOpened = false;
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}

// 往串口写数据
public bool WritePort(byte[] WriteBytes)
{
try
{
if (hComm != INVALID_HANDLE_VALUE)
{
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesWritten = 0;
WriteFile(hComm, WriteBytes, WriteBytes.Length, ref BytesWritten, ref ovlCommPort);
}
else
{
return false;
}
return true;
}
catch
{
return false;
}

}

// 从串口读数据
public bool ReadPort(int NumBytes, ref byte[] commRead)
{
if (hComm == INVALID_HANDLE_VALUE)
{
return false;
}

COMSTAT ComStat = new COMSTAT();
int dwErrorFlags = 0;

ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
if (dwErrorFlags != 0)
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);

if (ComStat.cbInQue > 0)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesRead = 0;
return ReadFile(hComm, commRead, NumBytes, ref BytesRead, ref ovlCommPort);
}
else
{
return false;
}
}

// 从串口读数据
public int ReadPortf(int NumBytes, ref byte[] commRead)
{
try
{
if (hComm == INVALID_HANDLE_VALUE)
{
return -1;
}

COMSTAT ComStat = new COMSTAT();
int dwErrorFlags = 0;

ClearCommError(hComm, ref dwErrorFlags, ref ComStat);
if (dwErrorFlags != 0)
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);

if (ComStat.cbInQue > 0)
{
OVERLAPPED ovlCommPort = new OVERLAPPED();
int BytesRead = 0;
if (ReadFile(hComm, commRead, NumBytes, ref BytesRead, ref ovlCommPort))
return BytesRead;
else
return -1;
}
else
{
return -1;
}
}
catch
{
return -1;
}
}

}
}
jcl007_ 2010-03-04
  • 打赏
  • 举报
回复
[DllImport("coredll")]
public static extern void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count);

[DllImport("coredll")]
private static extern int CreateFile(
string lpFileName, // file name
uint dwDesiredAccess, // access mode
int dwShareMode, // share mode
int lpSecurityAttributes, // SD
int dwCreationDisposition, // how to create
int dwFlagsAndAttributes, // file attributes
int hTemplateFile // handle to template file
);

[DllImport("coredll")]
private static extern bool GetCommState(
int hFile, // handle to communications device
ref DCB lpDCB // device-control block
);

[DllImport("coredll")]
private static extern bool BuildCommDCB(
string lpDef, // device-control string
ref DCB lpDCB // device-control block
);

[DllImport("coredll")]
private static extern bool SetCommState(
int hFile, // handle to communications device
ref DCB lpDCB // device-control block
);

[DllImport("coredll")]
private static extern bool GetCommTimeouts(
int hFile, // handle to comm device
ref COMMTIMEOUTS lpCommTimeouts // time-out values
);

[DllImport("coredll")]
private static extern bool SetCommTimeouts(
int hFile, // handle to comm device
ref COMMTIMEOUTS lpCommTimeouts // time-out values
);

[DllImport("coredll")]
private static extern bool ReadFile(
int hFile, // handle to file
byte[] lpBuffer, // data buffer
int nNumberOfBytesToRead, // number of bytes to read
ref int lpNumberOfBytesRead, // number of bytes read
ref OVERLAPPED lpOverlapped // overlapped buffer
);

[DllImport("coredll")]
private static extern bool WriteFile(
int hFile, // handle to file
byte[] lpBuffer, // data buffer
int nNumberOfBytesToWrite, // number of bytes to write
ref int lpNumberOfBytesWritten, // number of bytes written
ref OVERLAPPED lpOverlapped // overlapped buffer
);

[DllImport("coredll")]
private static extern bool CloseHandle(
int hObject // handle to object
);

[DllImport("coredll")]
private static extern bool ClearCommError(
int hFile, // handle to file
ref int lpErrors,
ref COMSTAT lpStat
);

[DllImport("coredll")]
private static extern bool PurgeComm(
int hFile, // handle to file
uint dwFlags
);

[DllImport("coredll")]
private static extern bool SetupComm(
int hFile,
int dwInQueue,
int dwOutQueue
);

[DllImport("coredll")]
private static extern bool SetCommMask(
int hFile,
int dwEvtMask //梓隴岈璃腔栚鎢
);

[DllImport("coredll")]
private static extern bool WaitCommEvent(
int hFile,
ref int lpEvtMask,
ref OVERLAPPED lpOverlapped

);

[DllImport("coredll")]
private static extern int CreateEvent(
int lpSecurityAttributes,
bool bManualReset,
bool bInitialState,
string lpName
);



// SerialPort的成员变量
private int hComm = INVALID_HANDLE_VALUE;
private bool bOpened = false;

public bool Opened
{
get
{
return bOpened;
}
}

/// <summary>
///串口的初始化函数
///lpFileName 端口名
///baudRate 波特率
///parity 校验位
///byteSize 数据位
///stopBits 停止位
/// <summary>
public bool OpenPort(string lpFileName, int baudRate, byte parity, byte byteSize, byte stopBits)
{
try
{
// OPEN THE COMM PORT.
hComm = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);
// IF THE PORT CANNOT BE OPENED, BAIL OUT.
if (hComm != INVALID_HANDLE_VALUE)
{
SetupComm(hComm, MAXBLOCK, MAXBLOCK);

// SET THE COMM TIMEOUTS.
COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS();

GetCommTimeouts(hComm, ref ctoCommPort);

ctoCommPort.ReadIntervalTimeout = Int32.MaxValue;
ctoCommPort.ReadTotalTimeoutConstant = Int32.MaxValue;
ctoCommPort.ReadTotalTimeoutMultiplier = Int32.MaxValue;
ctoCommPort.WriteTotalTimeoutMultiplier = 10;
ctoCommPort.WriteTotalTimeoutConstant = 1000;
SetCommTimeouts(hComm, ref ctoCommPort);

// SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS.
// THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST.
// IF YOU WANT TO LATER ADD CODE FOR OTHER BAUD RATES, REMEMBER
// THAT THE ARGUMENT FOR BuildCommDCB MUST BE A POINTER TO A STRING.
// ALSO NOTE THAT BuildCommDCB() DEFAULTS TO NO HANDSHAKING.
DCB dcbCommPort = new DCB();
dcbCommPort.DCBlength = Marshal.SizeOf(dcbCommPort);
GetCommState(hComm, ref dcbCommPort);
dcbCommPort.BaudRate = baudRate;
dcbCommPort.Parity = parity;
dcbCommPort.ByteSize = byteSize;
dcbCommPort.StopBits = stopBits;
SetCommState(hComm, ref dcbCommPort);

PurgeComm(hComm, PURGE_RXCLEAR | PURGE_RXABORT);
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_TXABORT);

bOpened = true;
return true;
}
else
{
return false;
}
}
catch
{
return false;
}

}
jcl007_ 2010-03-04
  • 打赏
  • 举报
回复
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Common
{
/// <summary>
/// Comms 的摘要说明。
/// </summary>
public class Comms
{
//win32 api constants
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const int OPEN_EXISTING = 3;
private const int INVALID_HANDLE_VALUE = -1;
private const int MAXBLOCK = 4096;

private const uint PURGE_TXABORT = 0x0001; // Kill the pending/current writes to the comm port.
private const uint PURGE_RXABORT = 0x0002; // Kill the pending/current reads to the comm port.
private const uint PURGE_TXCLEAR = 0x0004; // Kill the transmit queue if there.
private const uint PURGE_RXCLEAR = 0x0008; // Kill the typeahead buffer if there.

private const int EV_RXCHAR = 0x0001;

public Comms()
{
//
// TODO: 在此处添加构造函数逻辑
//
}

[StructLayout(LayoutKind.Sequential)]
private struct DCB
{
//taken from c struct in platform sdk
public int DCBlength; // sizeof(DCB)
public int BaudRate; // current baud rate
public int fBinary; // binary mode, no EOF check
public int fParity; // enable parity checking
public int fOutxCtsFlow; // CTS output flow control
public int fOutxDsrFlow; // DSR output flow control
public int fDtrControl; // DTR flow control type
public int fDsrSensitivity; // DSR sensitivity
public int fTXContinueOnXoff; // XOFF continues Tx
public int fOutX; // XON/XOFF out flow control
public int fInX; // XON/XOFF in flow control
public int fErrorChar; // enable error replacement
public int fNull; // enable null stripping
public int fRtsControl; // RTS flow control
public int fAbortOnError; // abort on error
public int fDummy2; // reserved
public ushort wReserved; // not currently used
public ushort XonLim; // transmit XON threshold
public ushort XoffLim; // transmit XOFF threshold
public byte ByteSize; // number of bits/byte, 4-8
public byte Parity; // 0-4=no,odd,even,mark,space
public byte StopBits; // 0,1,2 = 1, 1.5, 2
public char XonChar; // Tx and Rx XON character
public char XoffChar; // Tx and Rx XOFF character
public char ErrorChar; // error replacement character
public char EofChar; // end of input character
public char EvtChar; // received event character
public ushort wReserved1; // reserved; do not use
}

[StructLayout(LayoutKind.Sequential)]
private struct COMMTIMEOUTS
{
public int ReadIntervalTimeout;
public int ReadTotalTimeoutMultiplier;
public int ReadTotalTimeoutConstant;
public int WriteTotalTimeoutMultiplier;
public int WriteTotalTimeoutConstant;
}

[StructLayout(LayoutKind.Sequential)]
private struct OVERLAPPED
{
public int Internal;
public int InternalHigh;
public int Offset;
public int OffsetHigh;
public int hEvent;
}

[StructLayout(LayoutKind.Sequential)]
private struct COMSTAT
{
public int cbOutQue;
public int cbInQue;
public int fReserved;
public int fTxim;
public int fEof;
public int fXoffSent;
public int fXoffHold;
public int fRlsdHold;
public int fDsrHold;
public int fCtsHold;
}
oushengfen 2010-03-04
  • 打赏
  • 举报
回复
引用 2 楼 zhouzhangkui 的回复:
http://blog.csdn.net/solond/archive/2008/03/04/2146446.aspx


以上对DCB结构进行了分析,确实不错,这个我倒发觉了,只是不知道如何处理,我目前,好像按老方法定义,也没有出现问题,对了,我建议,楼主,的读函数进行处理。你看看我是这样处理的

        //向串口读数据
public int ComReadFile(int ihCommFile, byte[] Readbuff, int ReadLen)
{
uint dwStart=0, dwStop=0;
if (ihCommFile != INVALID_HANDLE_VALUE)
{
int NumberOfBytesTransferred = 0;
OVERLAPPED ovlCommPort = new OVERLAPPED();
COMSTAT ComStat = new COMSTAT();
dwStart = GetTickCount();
dwStop = dwStart;
while (dwStop - 200 < dwStart) //相当于等待超时,最大等待800
{
int dwErrorFlags = 0;
ClearCommError(ihCommFile, ref dwErrorFlags, ref ComStat);
if (dwErrorFlags != 0)
PurgeComm(ihCommFile, PURGE_RXCLEAR | PURGE_RXABORT);
if (ComStat.cbInQue > 0)
break;
dwStop = GetTickCount();
}

if (ComStat.cbInQue > 0)
{
if (ReadFile(ihCommFile, Readbuff, ReadLen, ref NumberOfBytesTransferred, ref ovlCommPort))//
{
if (ReadLen == NumberOfBytesTransferred)
{
return NumberOfBytesTransferred;
}
else return NumberOfBytesTransferred;

}
else return 0;
}
else return 0;
}
else return 0;
}
masky5310 2010-03-03
  • 打赏
  • 举报
回复
关注啊下。。。呵呵恶化
周药师 2010-03-03
  • 打赏
  • 举报
回复
SerialPort方便些
wince下 可以用SerialPort

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧