直接上代码,
我用的是COM1口,基本设置如下:
dcb.BaudRate = 9600; //波特率为9600
dcb.ByteSize = 8; //每个字节有8位
dcb.Parity = NOPARITY; //无奇偶校验位
dcb.StopBits = ONESTOPBIT; //一个停止位
//设定超时
COMMTIMEOUTS TimeOuts;
TimeOuts.ReadIntervalTimeout = MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier=1000;
TimeOuts.ReadTotalTimeoutConstant=1000;
//在读一次输入缓冲区的内容后读操作就立即返回,
//而不管是否读入了要求的字符。
//设定写超时
TimeOuts.WriteTotalTimeoutMultiplier=50;
TimeOuts.WriteTotalTimeoutConstant=5000;
读取代码
UINT __cdecl OnWatchCom(LPVOID lparam)
{
CBillDlg *pDlg = (CBillDlg *)lparam;
if(pDlg == NULL) return -1;
CString strResult;
char buff[128] = {0};
while(pDlg->m_IsWatching)
{
if(pDlg->m_Com.ReadCom(buff,128,2000))
{
pDlg->m_Com.ClearComBuf(PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
strResult.Format(_T("%s"),buff);
if(!strResult.IsEmpty())
{
pDlg->m_strBillNo = strResult;
pDlg->UpdateData(0);
}
}
Sleep(50);
}
return 0;
}
BOOL CComport::ReadCom(char *buff, int nlen, int dwMiniTimeout)
{
if(!IsOpen()) return FALSE;
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
COMSTAT ComStat;
DWORD dwErrorFlags;
memset(buff,'\0',nlen);
DWORD dwBytesRead=nlen;//读取的字节数
BOOL bReadStat;
ClearComErr(&dwErrorFlags,&ComStat);
dwBytesRead=min(dwBytesRead, (DWORD)ComStat.cbInQue);
bReadStat=ReadFile(m_hCom,buff,dwBytesRead,&dwBytesRead,&m_osRead);
if(!bReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
//GetOverlappedResult(m_hCom,&m_osRead,&dwBytesRead,TRUE);
WaitForSingleObject(m_osRead.hEvent,dwMiniTimeout);
//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
//当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号
//ResetEvent(m_osRead.hEvent);
}
}
CloseHandle(m_osRead.hEvent);
return TRUE;
}
不知道是读函数的问题还是超时设置的问题,我的条码是12位数字,网上写的大多数超时方式我都试过。可还是没什么效果.请指教
20 个解决方案
#1
最好专门开个线程来读数据,读到数据之后通过回调函数或者事件通知的方式,让应用程序取数据,个人意见。。
#2
这儿有一个参考,写法和楼主用的方法一样
http://www.vckbase.com/document/viewdoc/?id=1734
http://www.vckbase.com/document/viewdoc/?id=1734
#3
哥们儿,我就是照着这个经典的例子做的,
这个线程函数就是专门来读数据的.
UINT __cdecl OnWatchCom(LPVOID lparam)
这个线程函数就是专门来读数据的.
UINT __cdecl OnWatchCom(LPVOID lparam)
#4
其实同步读取可以完成任务,我就是想知道异步读取怎么做。
#5
100分怎么没人来拿?
#6
路过拾点什么……
#7
找个串口类,很简单。
要是读出半截来,你就把类中的sleep参数设大点。
见过几个串口操作的类,其中都有sleep
要是读出半截来,你就把类中的sleep参数设大点。
见过几个串口操作的类,其中都有sleep
#8
那个示例也有异步读取的方法啊。。
我之前按照那种方法写是可以的。
#9
你该做一个内存缓冲 来保存你读取的数据 然后检查数据的完整性
还有就是在线程里面不要 pDlg->UpdateData(0);
还有就是在线程里面不要 pDlg->UpdateData(0);
#10
两个小问题
ClearComErr(&dwErrorFlags,&ComStat);之后判断一下ComStat.cbInQue 是否为零
WaitForSingleObject(m_osRead.hEvent,-1);最好GetOverlappedResult代替 并且无限等待
ClearComErr(&dwErrorFlags,&ComStat);之后判断一下ComStat.cbInQue 是否为零
WaitForSingleObject(m_osRead.hEvent,-1);最好GetOverlappedResult代替 并且无限等待
#11
晕了 看了你的代码跟着你的思维走了
现在才发现你的架构有问题
应该是下面的步骤
1 CreateFile
2 SetCommMask注册读事件
3 WaitCommEvent 无限等待可读事件 你这里用循环不是浪费cpu么
4 ClearComErr 取得可读的数据的大小
5 ReadFile 在异步模式下100%错误的
6 GetOverlappedResult 无限等待读事件完成
这个模式下WaitCommEvent 会被卡住 你要停止线程运行 给WaitCommEvent的事件信号 让他完成等待
现在才发现你的架构有问题
应该是下面的步骤
1 CreateFile
2 SetCommMask注册读事件
3 WaitCommEvent 无限等待可读事件 你这里用循环不是浪费cpu么
4 ClearComErr 取得可读的数据的大小
5 ReadFile 在异步模式下100%错误的
6 GetOverlappedResult 无限等待读事件完成
这个模式下WaitCommEvent 会被卡住 你要停止线程运行 给WaitCommEvent的事件信号 让他完成等待
#12
嗯,一会下去试试你的方法,但现在的问题是我没有用注册事件的方法,数据是能读到的。就是有时容易截断。
而且我发现即使是异步,
只要你把ReadFile里面的第三个参数设成ClearComErr里面的可读数据数据大小,ReadFile就会返回TRUE,
这是我想不明白的地方,和超时有关吗?
#13
不管用不用注册事件的方式,调用ReadFile只要收到数据就能读出来的,至于数据长度取决于收到多少了。
假如你在WriteFile之后等的时间够长,估计每次都能读全,这是效率明显下降了。。
假如你在WriteFile之后等的时间够长,估计每次都能读全,这是效率明显下降了。。
#14
异步读取,ReadFile什么时候返回TRUE,什么时候返回FALSE呢?
#15
循环读,然后检测返回的数据中如果有0x0D,则返回开始读到的数据
#16
为什么ReadFile异步读取,总是返回TRUE?百思不得其解
#17
有一个CSerialPort的类,是用线程的。在界面中用消息得到数据,再自己拼条码试试。
#18
总觉得你的写法好怪。不要拍我:)
#19
顶起~没有人遇到吗?
#20
#21
#1
最好专门开个线程来读数据,读到数据之后通过回调函数或者事件通知的方式,让应用程序取数据,个人意见。。
#2
这儿有一个参考,写法和楼主用的方法一样
http://www.vckbase.com/document/viewdoc/?id=1734
http://www.vckbase.com/document/viewdoc/?id=1734
#3
哥们儿,我就是照着这个经典的例子做的,
这个线程函数就是专门来读数据的.
UINT __cdecl OnWatchCom(LPVOID lparam)
这个线程函数就是专门来读数据的.
UINT __cdecl OnWatchCom(LPVOID lparam)
#4
其实同步读取可以完成任务,我就是想知道异步读取怎么做。
#5
100分怎么没人来拿?
#6
路过拾点什么……
#7
找个串口类,很简单。
要是读出半截来,你就把类中的sleep参数设大点。
见过几个串口操作的类,其中都有sleep
要是读出半截来,你就把类中的sleep参数设大点。
见过几个串口操作的类,其中都有sleep
#8
那个示例也有异步读取的方法啊。。
我之前按照那种方法写是可以的。
#9
你该做一个内存缓冲 来保存你读取的数据 然后检查数据的完整性
还有就是在线程里面不要 pDlg->UpdateData(0);
还有就是在线程里面不要 pDlg->UpdateData(0);
#10
两个小问题
ClearComErr(&dwErrorFlags,&ComStat);之后判断一下ComStat.cbInQue 是否为零
WaitForSingleObject(m_osRead.hEvent,-1);最好GetOverlappedResult代替 并且无限等待
ClearComErr(&dwErrorFlags,&ComStat);之后判断一下ComStat.cbInQue 是否为零
WaitForSingleObject(m_osRead.hEvent,-1);最好GetOverlappedResult代替 并且无限等待
#11
晕了 看了你的代码跟着你的思维走了
现在才发现你的架构有问题
应该是下面的步骤
1 CreateFile
2 SetCommMask注册读事件
3 WaitCommEvent 无限等待可读事件 你这里用循环不是浪费cpu么
4 ClearComErr 取得可读的数据的大小
5 ReadFile 在异步模式下100%错误的
6 GetOverlappedResult 无限等待读事件完成
这个模式下WaitCommEvent 会被卡住 你要停止线程运行 给WaitCommEvent的事件信号 让他完成等待
现在才发现你的架构有问题
应该是下面的步骤
1 CreateFile
2 SetCommMask注册读事件
3 WaitCommEvent 无限等待可读事件 你这里用循环不是浪费cpu么
4 ClearComErr 取得可读的数据的大小
5 ReadFile 在异步模式下100%错误的
6 GetOverlappedResult 无限等待读事件完成
这个模式下WaitCommEvent 会被卡住 你要停止线程运行 给WaitCommEvent的事件信号 让他完成等待
#12
嗯,一会下去试试你的方法,但现在的问题是我没有用注册事件的方法,数据是能读到的。就是有时容易截断。
而且我发现即使是异步,
只要你把ReadFile里面的第三个参数设成ClearComErr里面的可读数据数据大小,ReadFile就会返回TRUE,
这是我想不明白的地方,和超时有关吗?
#13
不管用不用注册事件的方式,调用ReadFile只要收到数据就能读出来的,至于数据长度取决于收到多少了。
假如你在WriteFile之后等的时间够长,估计每次都能读全,这是效率明显下降了。。
假如你在WriteFile之后等的时间够长,估计每次都能读全,这是效率明显下降了。。
#14
异步读取,ReadFile什么时候返回TRUE,什么时候返回FALSE呢?
#15
循环读,然后检测返回的数据中如果有0x0D,则返回开始读到的数据
#16
为什么ReadFile异步读取,总是返回TRUE?百思不得其解
#17
有一个CSerialPort的类,是用线程的。在界面中用消息得到数据,再自己拼条码试试。
#18
总觉得你的写法好怪。不要拍我:)
#19
顶起~没有人遇到吗?