WinCE开发How to大集合之 WinCE下读写串口非常简单好用的例程

WinCE下读写串口非常简单好用的例程

  1. //打开串口
  2. hPort=CreateFile(lpszPortName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  3. BOOL CSerial::InitDCB()
  4. {
  5. DCB PortDCB;//声明一个DCB结构
  6. DWORD dwError;
  7. PortDCB.DCBlength = sizeof (DCB); //初始化 DCBlength
  8. GetCommState (hPort, &PortDCB); //得到端口的默认设置信息
  9. //改变DCB结构设置
  10. PortDCB.BaudRate =CBR_115200; //波特率
  11. //其他还想改变的默认配置
  12. //根据DCB结构配置端口
  13. if (!SetCommState (hPort, &PortDCB))
  14. { //不能配置串行端口
  15. MessageBox (NULL, TEXT("Unable to configure the serial port!"), TEXT("Error!"), MB_OK);
  16. dwError = GetLastError (); //获得错误原因的代码
  17. return FALSE;
  18. }
  19. return TRUE;
  20. }
  21. BOOL CSerial::InitCommTimeouts()
  22. {
  23. COMMTIMEOUTS CommTimeouts; //声明一个COMMTIMEOUTS结构
  24. DWORD dwError;
  25. //得到超时参数
  26. GetCommTimeouts (hPort, &CommTimeouts);
  27. //改变COMMTIMEOUTS结构设置
  28. //不使用这个逾时功能,ReadFile直到所有字符接收完才会返回
  29. CommTimeouts.ReadIntervalTimeout = 0;
  30. CommTimeouts.ReadTotalTimeoutMultiplier = 0;
  31. CommTimeouts.ReadTotalTimeoutConstant = 0;
  32. //不使用这个逾时功能,WriteFile直到所有字符接收完才会返回
  33. CommTimeouts.WriteTotalTimeoutMultiplier = 0;
  34. CommTimeouts.WriteTotalTimeoutConstant=0;
  35. if (!SetCommTimeouts(hPort,&CommTimeouts)) //设置端口超时值
  36. { //不能设置超时值  
  37. MessageBox (NULL, TEXT("Unable to set the time-out parameters!"),TEXT("Error!"), MB_OK);
  38. dwError = GetLastError (); //获得错误原因的代码
  39. return FALSE;
  40. }
  41. return TRUE;
  42. }
  43. DWORD CSerial::WritePort(byte *buf,DWORD dwCharToWrite)
  44. {
  45. BOOL fWriteState;
  46. DWORD dwBytesWritten;
  47. //写入数据
  48. // PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
  49. //PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
  50. fWriteState=WriteFile(hPort,buf,dwCharToWrite,&dwBytesWritten,NULL);
  51. if(!fWriteState) //不能写数据
  52. {
  53. MessageBox(NULL,TEXT("You can't write the data to the port!"),TEXT("Error!"),MB_OK);
  54. dwBytesWritten=0;
  55. }
  56. //PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR);
  57. //PurgeComm(hPort,PURGE_TXCLEAR);
  58. return dwBytesWritten;
  59. }
  60. DWORD  WINAPI  ReadPortThread(LPVOID lpvoid)
  61. {
  62.     BOOL fReadState; //读入信息时返回值,若为TRUE就是正确读入
  63.     DWORD dwCommModemStatus; //串口状态,以判断是否有事件发生
  64.     DWORD dwLength; //读入信息的长度
  65.     COMSTAT ComStat; //串口状态的详细情况表,
  66.     DWORD dwErrorFlags; //读串口状态的标志
  67.     BOOL readStatus=FALSE; //读入信息的状态,若为TRUE就是正在读入但还没有读完
  68.     int iCounter=0;
  69.     DWORD dwBytes;
  70.     byte Byte;
  71.     SetCommMask(hPort,EV_RXCHAR); //设置程序响应的事件
  72.     PurgeComm(hPort,PURGE_RXCLEAR|PURGE_TXCLEAR); //清空串口的接收缓冲区,必要性不大,但有保证作用
  73.     //ClearCommError(hPort,&dwErrorFlags,&ComStat); //清除串口状态标志,并返回当前状态
  74.     while (hPort != INVALID_HANDLE_VALUE) //程序在串口有效的状态下,无限循环
  75.     {
  76.         if(WaitCommEvent(hPort, &dwCommModemStatus,0)) //等待串口的事件发生,当dwCommModemStatus值为1时表示接收到数据
  77.         {
  78.             SetCommMask (hPort, EV_RXCHAR); //重新设置程序响应的事件,但这个只是保证程序的安全性,一般并不起作用
  79.             if (dwCommModemStatus & EV_RXCHAR) //检测收到的事件是否为"接收字符"的事件
  80.             {
  81.                 ClearCommError(hPort,&dwErrorFlags,&ComStat); //清除串口状态标志,并返回当前状态
  82.                 dwLength=ComStat.cbInQue; //cbInQue返回在串行驱动程序输入队列中的字符数
  83.                 if(dwLength>0)//防止无故产生事件
  84.                 {
  85.                     //从串口读取数据
  86.                     //读入数据,并返回数据长度,采用同步方式
  87.                     if(dwLength <10240)
  88.                     {
  89.                         fReadState=ReadFile(hPort,&fbuf[0],dwLength,&dwLength,NULL);
  90.                         if(!fReadState)
  91.                         {
  92.                             MessageBox(NULL,TEXT("Can't fetch the data!"),TEXT("Reading Error!"),MB_OK); //不能从串口读取数据
  93.                         }
  94.                         else
  95.                         {
  96.                         //ProcessReceive((WPARAM)dwLength,(LPARAM)fbuf);
  97.                             ::SendMessage(m_hWnd,WM_COMM_RCHAR2,(WPARAM)dwLength,(LPARAM)fbuf); //通知主窗口数据已经得到可以处理
  98.                         }
  99.                     }
  100.                     else//当缓存溢出就处理读掉
  101.                     {
  102.                         DWORD j=dwLength%10240;
  103.                         for(int i=0;i <dwLength/10240;i++)
  104.                         fReadState=ReadFile(hPort,&fbuf[0],dwLength,&dwLength,NULL);
  105.                         fReadState=ReadFile(hPort,&fbuf[0],j,&j,NULL);
  106.                     }
  107.                 }
  108.             }
  109.         }
  110.         // PurgeComm(hPort,PURGE_RXCLEAR);//清空串口的接收缓冲区,必要性不大,但有保证作用
  111.         //重新获得串口状态,必要性不大,48表示没有事件产生
  112.         GetCommModemStatus (hPort, &dwCommModemStatus);
  113.     }
  114.     return 0;
  115. }
这个是个例子,不过不是在ADS下用的,因为调用了API接口,一般都是在microsoft的开发工具,比如EVC,VS2005上面使用
如果你是做WinCE应用程序的,就使用EVC或者VS2005吧
上面的例子我现在也在使用,还是非常好用的,因为如果直接Readfile,效率很低,要么等超时,要么无限等,都会让系统响应变慢,这种是利用类似Event的机制来激活线程
如果你不希望作为单独一个线程,可以稍作修改,就可以通过循环判断而得知read buffer的状态
参考:
  1. BOOL fReadState; //读入信息时返回值,若为TRUE就是正确读入
  2. DWORD dwCommModemStatus; //串口状态,以判断是否有事件发生
  3. DWORD dwLength; //读入信息的长度
  4. COMSTAT ComStat; //串口状态的详细情况表,
  5. DWORD dwErrorFlags; //读串口状态的标志
  6. BOOL readStatus=FALSE; //读入信息的状态,若为TRUE就是正在读入但还没有读完
  7. int iCounter=0;
  8. #if 1
  9. //检测收到的事件是否为"接收字符"的事件
  10. ::ClearCommError(g_hGSMCOM,&dwErrorFlags,&ComStat); //清除串口状态标志,并返回当前状态
  11. dwLength=ComStat.cbInQue; //cbInQue返回在串行驱动程序输入队列中的字符数
  12. if(dwLength > 0) { //防止无故产生事件
  13. DWORD dwRetLen = 0;
  14. DWORD dwTimes = (dwLength / (GSM_READBUFF_SIZE - 1)) + 1;
  15. DWORD j = dwLength % (GSM_READBUFF_SIZE-1);
  16. for(DWORD i = 0; i < dwTimes; i++) {
  17. DWORD dwRoundReadSize = ((dwTimes - i) == 1)? j:(GSM_READBUFF_SIZE-1);
  18. memset(g_szReadBuff, 0, dwRoundReadSize + 1);
  19. fReadState=::ReadFile( g_hGSMCOM,
  20. g_szReadBuff,
  21. dwRoundReadSize,
  22. &dwRetLen,
  23. NULL
  24. );
  25. if(!fReadState) {
  26. //RETAILMSG(GSM_DEBUG_ERROR,(TEXT("[%s]: Can't fetch the data!/r/n"), pszFname));
  27. MessageBox(NULL,TEXT("Can't fetch the data!"),TEXT("Reading Error!"),MB_OK); //不能从串口读取数据
  28. return 0;
  29. } else {
  30. g_szReadBuff[dwRoundReadSize] = 0;
  31. //MessageBox(NULL,TEXT("Read OK!"),TEXT("Reading OK!"),MB_OK);
  32. EnterCriticalSection(&g_csSendLock);
  33. g_pcMC55->CheckResult(g_szReadBuff, dwRoundReadSize);
  34. LeaveCriticalSection(&g_csSendLock);
  35. }
  36. }
  37. return dwLength;
  38. }
  39. #else
  40. if(::WaitCommEvent(g_hGSMCOM, &dwCommModemStatus,0)) { //等待串口的事件发生,当dwCommModemStatus值为1时表示接收到数据
  41. ::SetCommMask (g_hGSMCOM, EV_RXCHAR); //重新设置程序响应的事件,但这个只是保证程序的安全性,一般并不起作用
  42. if (dwCommModemStatus & EV_RXCHAR) {//检测收到的事件是否为"接收字符"的事件
  43. ::ClearCommError(g_hGSMCOM,&dwErrorFlags,&ComStat); //清除串口状态标志,并返回当前状态
  44. dwLength=ComStat.cbInQue; //cbInQue返回在串行驱动程序输入队列中的字符数
  45. if(dwLength > 0) { //防止无故产生事件
  46. DWORD dwRetLen = 0;
  47. DWORD dwTimes = (dwLength / (GSM_READBUFF_SIZE - 1)) + 1;
  48. DWORD j = dwLength % (GSM_READBUFF_SIZE-1);
  49. for(DWORD i = 0; i < dwTimes; i++) {
  50. DWORD dwRoundReadSize = ((dwTimes - i) == 1)? j:(GSM_READBUFF_SIZE-1);
  51. memset(g_szReadBuff, 0, dwRoundReadSize + 1);
  52. fReadState=::ReadFile( g_hGSMCOM,
  53. g_szReadBuff,
  54. dwRoundReadSize,
  55. &dwRetLen,
  56. NULL
  57.    );
  58. if(!fReadState) {
  59. //RETAILMSG(GSM_DEBUG_ERROR,(TEXT("[%s]: Can't fetch the data!/r/n"), pszFname));
  60. MessageBox(NULL,TEXT("Can't fetch the data!"),TEXT("Reading Error!"),MB_OK); //不能从串口读取数据
  61. return 0;
  62. } else {
  63. g_pcMC55->CheckResult(g_szReadBuff, dwRoundReadSize);
  64. }
  65. }
  66. return dwLength;
  67. }
  68. }
  69. }
  70. #endif
  71. // PurgeComm(hPort,PURGE_RXCLEAR);//清空串口的接收缓冲区,必要性不大,但有保证作用
  72. //重新获得串口状态,必要性不大,48表示没有事件产生
  73. //::GetCommModemStatus (g_hGSMCOM, &dwCommModemStatus);
  74. return 0;
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值