⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 com.~cpp

📁 串口数据采集的上位机源码
💻 ~CPP
📖 第 1 页 / 共 2 页
字号:
         ExitThread(0);
       }
     }
   }
   else
   {
     //如果WaitCommEvent()返回true,检查输入缓冲区是否确实
     //有字节可读,若没有,则继续下一循环
     //ClearCommError()将更新串口状态结构并清除所有串口硬件错误
     ClearCommError(Port->m_hComm,&dwError,&ComStat);
     if (ComStat.cbInQue==0)   //输入缓冲队列长为0,无字符
       continue;
   }           
//以下为主等待函数,线程将被阻塞直到m_hEventArray中指定的某一
   //事件产生时函数返回,返回值为这一事件的序号
   Event=WaitForMultipleObjects(2,    //等待的事件的个数
         Port->m_hEventArray,  //事件数组
         false,    //任一事件产生时返回
         4000);    //等待4秒
   //判断使等待终止的事件
   switch (Event)
   {
     case 0:  //关闭串口事件,优先处理
     {
       Port->m_bThreadAlive = false;  //串口活动标志
       ExitThread(100);          //退出线程
     }
     case 1: //读串口事件
     {
       //获取串口事件掩码
       GetCommMask(Port->m_hComm,&CommEvent);
       if (CommEvent & EV_RXCHAR)  //收到一个字符
             ReceiveChar(Port);//读入一个字符
       break;
     }
   }
}
}
//----------------------------------------------------------------------
//接收一个字符
void __fastcall TSerialPort::ReceiveChar(TSerialPort* Port)
{
COMSTAT ComStat;
DWORD dwError=0;
bool bRead=true;
bool bResult;
DWORD BytesRead=0;
unsigned char ucRxBuff;

//开始无限循环,因为我不知到需要循环多少次.我的解决方法是开始一个无限循环,
//当我已处理了所有的有效数据后才退出.使用这种方法应小心的保证您的程序能
//正常退出循环.即便如此,我仍觉得这是最有效的解决办法
while(1)
{
   //ClearCommError()将更新串口状态结构并清除所有串口硬件错误
   ClearCommError(Port->m_hComm,&dwError,&ComStat);
   if (ComStat.cbInQue==0)
   {
     //缓冲区中已无数据,退出循环
     break;
   }
   //读串口
   bResult=ReadFile(Port->m_hComm,  //串口句柄
       &ucRxBuff,  //输入缓冲区地址
       1,    //想读入的字符数
       &BytesRead,  //实际被读入的字符数
       &Port->m_OverLapped);  //重叠结构指针
   //读串口失败,调用GetLastError()判断原因
   if(!bResult)
   {
     switch (dwError=GetLastError())
     {
       case ERROR_IO_PENDING:  //重叠操作在后台进行
       {
         bRead=false;
         BytesRead=0;
         break;
       }
       default:
       {
         //其它情况说明出错
         Port->ProcessErrorMessage("读串口");
         return;
       }
     }
   }
   if (!bRead)  //没有读到字符
   {
     //等待重叠操作结果
     bResult=GetOverlappedResult(Port->m_hComm,  //串口句柄
           &Port->m_OverLapped,  //重叠结构
           &BytesRead,  //实际读入字符数
           true);    //等待直到串口操作超时
     if (!bResult)  //重叠操作失败
     {
       Port->ProcessErrorMessage("(读串口时)获取重叠操作结果");
       return;
     }
     bRead = true;
   }
   //将收到的字符当作消息的参数投递到父窗口
   if(BytesRead!=1)  //没有读入要求的字符数
     continue;
   PostMessage((Port->m_pOwner)->Handle,WM_COMM_RXCHAR,
     (WPARAM)ucRxBuff,(LPARAM)Port->m_uPortNo);
}
}
//----------------------------------------------------------------------
//向串口写一个字符
bool TSerialPort::WriteChar(unsigned char ucChar)
{
bool bWrite=true;
bool bResult;
DWORD BytesSent=0;
OVERLAPPED ov;
ov.hEvent=CreateEvent(NULL, true, false, NULL);

//初始化重叠结构
ov.Offset=0;
ov.OffsetHigh=0;
PurgeComm(m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
//写串口
bResult = WriteFile(m_hComm,  //串口句柄
     &ucChar,  //输出缓冲区
     1,      //每次只发送一个字符
     &BytesSent,      //实际读入的字符数
     &ov);  //重叠结构
if(!bResult)  //写串口失败
{
   DWORD dwError=GetLastError();
   switch(dwError)
   {
     case ERROR_IO_PENDING:  //串口操作正在后台进行
     {
       BytesSent=0;
       bWrite=false;
       break;
     }
     default:  //失败
       return false;
   }
}
if(!bWrite)
{
   //等待重叠结果
   bResult=GetOverlappedResult(m_hComm,
       &ov,
       &BytesSent,  //实际发送字符数
       true);
   if (!bResult)  //重叠操作失败
     return false;
}
//检查实际发送的字符数是否与要求相符
if (BytesSent!=1)
{
   return false;
}
return true;
}
//----------------------------------------------------------------------
//向串口写一个字符
void __fastcall TSerialPort::WriteToPort(unsigned char ucTxData)
{
if(m_hComm==INVALID_HANDLE_VALUE)
{
   //mErrorMsg("串口句柄无效,无法发送数据.");
   return;
}
int i=3;
while(i)    //重发次数不超过3次
{
   if(WriteChar(ucTxData))  //成功发送
     break;
   i--;
   Application->ProcessMessages();
}
if(i==0)
{
   char sTemp[100];
   sprintf(sTemp,"数据\'%d\'未被成功发送.",ucTxData);
   //mErrorMsg(sTemp);
}
}
//---------------------------------------------------------------------------
//错误处理,显示原因
void __fastcall TSerialPort::ProcessErrorMessage(char* ErrorText)
{
char ErrorMsg[400];
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
     NULL,GetLastError(),     //获取错误信息标识
     MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),//使用系统缺省语言
     (LPTSTR)&lpMsgBuf, //消息缓冲区
     0,
     NULL);
//sprintf(ErrorMsg, "COM%d: \\"%s\\" 由于以下错误而失败: \\n\\n%s",
   //m_uPortNo,ErrorText,lpMsgBuf);
Application->MessageBox(ErrorMsg, "串口错误", MB_ICONSTOP);
LocalFree(lpMsgBuf);
}
/*======================================================================================*/
/****************************************************************************************
@函数名称           : BYTE CvtXor(BYTE a,BYTE b)
@参数               : a,b要计算的数字
@返回值             : 转换成功的异或值
@描述               : 将数字转换异或值
*****************************************************************************************/
BYTE CvtXor(BYTE a,BYTE b)
{
  char t0,t1, t3;
  t0 = a & b;
  t1 = a | b;
  t3 = t0 | (~t1);
  return  ~ t3;
}
//----------------------------------------------------------------------
/*======================================================================================*/
/****************************************************************************************
@函数名称           : BYTE SendFrame(BYTE cmd,WORD DataLen,BYTE StandBy,BYTE *data)
@参数               : char cmd:命令字, 
@返回值             : 0,1
@描述               : 根据输入组成一个数据帧,并且发送出去
*****************************************************************************************/
BYTE TSerialPort::SendFrame(BYTE cmd,WORD DataLen,BYTE StandBy,BYTE *data)
{
   WORD i,j,k;
   BYTE bytHead[6],tmp;
   //'组织帧头
   bytHead[0] = 0x55;
   bytHead[1] = 0x7A;
   bytHead[2] = cmd;
   bytHead[3] = DataLen>>8;
   bytHead[4] = DataLen;
   bytHead[5] = StandBy;
   //计算异或
   tmp = bytHead[0];
   for(i=0;i<6;i++)
     {
	  WriteToPort(bytHead[i]);
	  tmp = CvtXor(tmp, bytHead[i]);
	 }
  
  if(DataLen==0)  //没有数据情况
    {
	  WriteToPort(tmp);
	  return 1;
	}
  for(i=0;i<DataLen;i++)
   {
     WriteToPort(data[i]);
	 tmp = CvtXor(tmp, data[i]);
   }
  WriteToPort(tmp);
  return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -