串口读取数据不成功

kittymimihh 2009-11-05 09:48:24
打开串口函数成功
BOOL CSerial::OpenPort(LPTSTR lpszPortName)
{

DWORD dwError,dwThreadID;
if(hPort)
{
return FALSE;
}
//打开串口
hPort = CreateFile (L"COM2", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);
//如果打开端口出错, 返回FALSE

if ( hPort == INVALID_HANDLE_VALUE )
{
//不能打开端口
CString strError;
strError.Format(_T("Unable to open %s, Error No.=%d"),
lpszPortName, GetLastError());
MessageBox (NULL, strError, TEXT("Error"), MB_OK);
return FALSE;
}
//指定端口监测的事件集
SetCommMask (hPort, EV_RXCHAR);
//分配设备缓冲区
SetupComm(hPort,1280,1280);
//初始化缓冲区中的信息
PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR);
//配置串行端口
////////////////////////////////
DCB myDCB;
GetCommState(hPort,&myDCB);
myDCB.BaudRate = CBR_9600;
myDCB.fBinary = TRUE;
myDCB.fParity = TRUE;
myDCB.ByteSize = 8;
myDCB.Parity = ODDPARITY;
myDCB.StopBits = ONESTOPBIT;
SetCommState(hPort,&myDCB);
/////////////////////////////////
if(!InitDCB())
return FALSE;
//设置端口超时值
if(!InitCommTimeouts())
return FALSE;
//设置端口上指定信号的状态
// SETDTR: 发送DTR (data-terminal-ready)信号
// SETRTS: 发送RTS (request-to-send)信号
EscapeCommFunction (hPort, SETDTR);
EscapeCommFunction (hPort, SETRTS);

//创建一个从串口读取数据的线程

if (hReadThread = CreateThread (NULL, 0, ReadPortThread, this, 0,&dwThreadID))
{
}
else
{
//不能创建线程
MessageBox (NULL, TEXT("Unable to create the read thread"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return FALSE;
}
m_bConnected=TRUE;
return TRUE;
}

读线程函数
DWORD WINAPI ReadPortThread(LPVOID lpvoid)
{

BOOL fReadState;
DWORD dwCommModemStatus;
DWORD dwLength;
COMSTAT ComStat;
DWORD dwErrorFlags;
CSerial *pOwner = (CSerial*)lpvoid;
char szBuf[1200];
memset(szBuf,0,1200);
OVERLAPPED Rol= {0};
while (hPort != INVALID_HANDLE_VALUE)
{
//等待串口的事件发生
WaitCommEvent (hPort, &dwCommModemStatus, 0);
if (dwCommModemStatus & EV_RXCHAR)
{
ClearCommError(hPort,&dwErrorFlags,&ComStat);
//cbInQue返回在串行驱动程序输入队列中的字符数
dwLength=ComStat.cbInQue;
n = dwLength;
if(dwLength>0)
{
//从串口读取数据
buf=szBuf;
ZeroMemory(buf,1200);
n = dwLength;
Rol.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(Rol.hEvent == NULL)
{
AfxMessageBox(L"hEvent空",0,0);
return -1;
}
fReadState = ReadFile(hPort,buf,1200,&dwLength,&Rol);
n = fReadState;
n = dwLength;
if(!fReadState)
{
//不能从串口读取数据
MessageBox(NULL,TEXT("Error in read from serial port"),TEXT("Read Error"),MB_OK);
}
else
{
pOwner->DealData(szBuf,(int)dwLength);
}
}
}
GetCommModemStatus (hPort, &dwCommModemStatus);
}
return 0;
}

读线程函数在调用ReadFile返回值为0.
不知道错误在哪
查了很久了
忘大家竭力相助
...全文
471 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
kittymimihh 2009-11-06
  • 打赏
  • 举报
回复
EGetLastError()返回值是RROR_INVALID_PARAMETER
Yao-debo 2009-11-05
  • 打赏
  • 举报
回复
If hFile is opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset that is specified in the OVERLAPPED structure, and ReadFile may return before the read operation is complete. In this scenario, ReadFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING, which allows the calling process to continue while the read operation completes. The event specified in the OVERLAPPED structure is set to the signaled state when the read operation is complete, and then the caller must adjust the position of the file pointer.

由于你CreateFile指定了FILE_FLAG_OVERLAPPED , 所以串口操作是重叠IO模式.
ReadFile会返回FALSE, 这个时候并不是说就错误了, 你需要等待Rol.hEvent信号. 有数据读取出来时, Event 会有信号;

tech_study_00 2009-11-05
  • 打赏
  • 举报
回复
你参考一下别人的代码

//打开串口 缺省 baud_rate, n, 8, 1
bool CSerialPort::Open(DWORD dwPort, DWORD dwBaudRate, int ByteSize/* = 8*/, int StopBits/* = 1*/)
{
// [fush]: must refresh parameter
printf("READY to open com, port: %d, BaudRate: %d...\r\n", dwPort, dwBaudRate);
_dwPort = dwPort;
_DCB.BaudRate = dwBaudRate;
_DCB.ByteSize = ByteSize;
_DCB.StopBits = StopBits;

if(dwPort < 1 || dwPort > 1024)
return false;

BindCommPort(dwPort);

if(!OpenCommPort())
return false;

if(!SetupPort())
return false;

printf("Open com, port: %d, BaudRate: %d SUCCESS!\r\n", dwPort, dwBaudRate);

return SetState(dwBaudRate);
}

//绑定串口
void CSerialPort::BindCommPort(DWORD dwPort)
{
assert(dwPort >= 1 && dwPort <= 1024);

char p[5];

_dwPort = dwPort;
strcpy(_szCommStr, "\\\\.\\COM");
ltoa(_dwPort, p, 10);
strcat(_szCommStr, p);
}

//打开串口
bool CSerialPort::OpenCommPort()
{
if(IsOpen())
Close();

_hCommHandle = ::CreateFile(
_szCommStr,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | _dwIOMode,
NULL
);

if(_fAutoBeginThread)
{
if(IsOpen() && BeginThread())
return true;
else
{
Close();
//创建线程失败
return false;
}
}
return IsOpen();
}

//设置串口
bool CSerialPort::SetupPort()
{
if(!IsOpen())
return false;


if(!::SetupComm(_hCommHandle, 4096, 4096))
return false;


if(!::GetCommTimeouts(_hCommHandle, &_CO))
return false;
_CO.ReadIntervalTimeout = 0;
_CO.ReadTotalTimeoutMultiplier = 1;
_CO.ReadTotalTimeoutConstant = 1000;
_CO.WriteTotalTimeoutMultiplier = 1;
_CO.WriteTotalTimeoutConstant = 1000;
if(!::SetCommTimeouts(_hCommHandle, &_CO))
return false;


if(!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
return false;

return true;
}

//设置串口参数:波特率,停止位,等
bool CSerialPort::SetState(DWORD dwBaudRate, DWORD dwByteSize/* = 8*/, DWORD dwParity/* = NOPARITY*/, DWORD dwStopBits /*= ONESTOPBIT*/)
{
if(IsOpen())
{
if(::GetCommState(_hCommHandle, &_DCB) != TRUE)
return false;
_DCB.BaudRate = dwBaudRate;
_DCB.ByteSize = (unsigned char)dwByteSize;
_DCB.Parity = (unsigned char)dwParity;
_DCB.StopBits = (unsigned char)dwStopBits;
return ::SetCommState(_hCommHandle, &_DCB) == TRUE;
}
return false;
}

程序员小哈 2009-11-05
  • 打赏
  • 举报
回复
为什么不用串口控件或者下一个别人写好的串口类呢,自己写太麻烦了,在别人的基础上改也方便啊
feilinhe 2009-11-05
  • 打赏
  • 举报
回复
加一下演示,因为可能正在读取,还没读完:
if(!fReadState)
{
//不能从串口读取数据
MessageBox(NULL,TEXT("Error in read from serial port"),TEXT("Read Error"),MB_OK);
}
改成:
if(!fReadState)
{
if(GetLastError()==ERROR_IO_PENDING)
//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(Rol.hEvent,2000);
//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
//当串口读操作进行完毕后,Rol的hEvent事件会变为有信号
}
}
zoulie 2009-11-05
  • 打赏
  • 举报
回复
先确定下发送方有没有问题,
在ReadFile之后用GetLastError()确定返回的错误码,看是什么错误
kittymimihh 2009-11-05
  • 打赏
  • 举报
回复
回复3楼:
dwLength是缓存内的数据长度,当dwLength大于0时才执行读的操作,并且Rol.hEvent为FALSE我会返回值-1.程序并没有运行到那个地方。

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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