c++串口上位机调试助手的总结和部分代码

在初始化函数中添加:

 // TODO: Add extra initialization here

 m_bAutoSend=FALSE;  //m_bAutoSend为全局变量
 m_nCycleTime=1000;

 m_GPSCOM.SetCommPort(1);   //选择COM1
 m_GPSCOM.SetInputMode(1); //输入方式为二进制方式
 m_GPSCOM.SetInBufferSize(1024); //设置输入缓冲区大小
 m_GPSCOM.SetOutBufferSize(512); //设置输出缓冲区大小
// m_GPSCOM.SetSettings("9600,n,8,1"); //波特率115200,无校验,8个数据位,1个停止位 
 if(m_GPSCOM.GetPortOpen())   //如果串口是打开的
   m_GPSCOM.SetPortOpen(FALSE);//则关闭串口

 //参数1表示每当串口接收缓冲区中有多于
 //或等于1个字符时将引发一个接收数据的OnComm事件
 m_GPSCOM.SetRThreshold(1); 
 m_GPSCOM.SetInputLen(0);  //设置当前接收区数据长度为0
 //m_GPSCOM.GetInput();    //先预读缓冲区以清除残留数据 

显示接收到的内容

m_RXDATA建立的变量是CEidtl类型,不是CString

static long  RXcount=0;
void CGPS_COM1Dlg::OnGPSCOM()           //编辑框接收函数——用于显示串口接收到的数据
{
 // TODO: Add your control notification handler code here
 VARIANT variant_inp;
 COleSafeArray safearray_inp;
 LONG len,k;
 BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
 CString strtemp;
 CString strRXData;
  
 strRXData.Empty();
    if(m_GPSCOM.GetCommEvent()==2)     //事件值为2表示接收缓冲区内有字符
 {
  variant_inp=m_GPSCOM.GetInput();   //读缓冲区
  safearray_inp=variant_inp;           //VARIANT型变量转换为ColeSafeArray型变量
  len=safearray_inp.GetOneDimSize(); //得到有效数据长度
  for(k=0;k<len;k++)
   safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组

  for(k=0;k<len;k++)             //将数组转换为Cstring型变量
  {
   BYTE bt=*(char*)(rxdata+k);      //字符型
   if(m_hexdisplay.GetCheck())
   {
    strtemp.Format("%02x ",bt);         //将十六进制送入临时变量strtemp存放
   }
   else
   {
    strtemp.Format("%c",bt);         //将字符送入临时变量strtemp存放
   }
   strRXData=strRXData+strtemp;    //加入接收编辑框对应字符串 
   
  }

  m_RXDATA.ReplaceSel(strRXData);
  
  RXcount=RXcount+len;
  CString rxdatacount;
  rxdatacount.Format("%ld",RXcount);
//  rxdatacount="接收:"+rxdatacount;

  m_RXdatacount.SetWindowText(rxdatacount); //显示接收计数 
  
 }
}

//不用UpdateData(),这样写的好处就是当一直在接收时,也能自由发送而不受UpdateData()函数影响。

串口打开或关闭

void CGPS_COM1Dlg::OnButton1()     //串口打开或关闭
{
 // TODO: Add your control notification handler code here
 if(m_ctrlAutoSend.GetCheck())
 {
  AfxMessageBox("请先关闭自动发送,才可以关闭串口");
 }
 else
 {
  
  if(!m_GPSCOM.GetPortOpen())
  {
   m_GPSCOM.SetPortOpen(TRUE);//打开串口
   SetDlgItemText(IDC_BUTTON1,"关闭串口");

  }
  else
  {
   m_GPSCOM.SetPortOpen(FALSE);//关闭串口
   SetDlgItemText(IDC_BUTTON1,"打开串口");
  }
 }
}

 m_TXDATA建立的变量是CEidtl类型,不是CString

long TX_count=0;
void CGPS_COM1Dlg::OnButton2Tx()   //数据发送函数
{
 // TODO: Add your control notification handler code here
 if(!m_GPSCOM.GetPortOpen())
 {
  AfxMessageBox("请先打开串口");
 }
 else
 {
  UpdateData(TRUE); //读取编辑框内容
  if(m_strHexSend.GetCheck())
  {
   CByteArray hexdata;
   int len=String2Hex(m_TXDATA,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数
   m_GPSCOM.SetOutput(COleVariant(hexdata)); //发送十六进制数据
   TX_count+=(long) ((m_TXDATA.GetLength()+1)/3); //十六进制计数要注意算法
  }
  else 
  {
   m_GPSCOM.SetOutput(COleVariant(m_TXDATA));//发送ASCII字符数据
   TX_count+=m_TXDATA.GetLength();
  }
  CString strTemp;
  strTemp.Format("%d",TX_count);
  m_TXcount.SetWindowText(strTemp);
 }
}

void CGPS_COM1Dlg::OnButton3Clear()  //清除接收编辑框
{
 // TODO: Add your control notification handler code here
 m_RXDATA.SetWindowText("");//清除接收对话框中的数据


}

void CGPS_COM1Dlg::OnCHECK1hexdisplay() 
{
 // TODO: Add your control notification handler code here
 
}


void CGPS_COM1Dlg::OnCOMchose() 
{
 // TODO: Add your control notification handler code here 
 char str[10];
 
 int iPos=m_COMChose.GetCurSel();
 int iNum=m_COMChose.GetLBText( iPos, (LPTSTR) str) ;
 int i=atoi(str+3);
 if(m_GPSCOM.GetPortOpen())
 {
  AfxMessageBox("请先关闭串口,再选择COM口");
 }
 if(!m_GPSCOM.GetPortOpen())
 {
  m_GPSCOM.SetCommPort(i);   //选择COM口

 }

}

void CGPS_COM1Dlg::OnHexSend() 
{
 // TODO: Add your control notification handler code here


}


void CGPS_COM1Dlg::OnTimer(UINT nIDEvent) 
{
 // TODO: Add your message handler code here and/or call default
 switch(nIDEvent)
 {
  case 1:  OnButton2Tx();
   break;
/*  case 2:
   m_strCurPath.SetWindowText(m_strCurPath); //重新显示路径
   KillTimer(2);//关闭定时器

*/
  default:      ;
   break;
 
 }
 CDialog::OnTimer(nIDEvent);
}

void CGPS_COM1Dlg::OnCheck2_AutoSend() 
{
 // TODO: Add your control notification handler code here
 
 m_bAutoSend=!m_bAutoSend;  //标志是否打开自动发送
 if(m_bAutoSend)
 {
  if(!m_GPSCOM.GetPortOpen())
  {
   m_bAutoSend=!m_bAutoSend;
   m_ctrlAutoSend.SetCheck(0);
   AfxMessageBox("串口没有打开,请打开串口");
   return;
  }
  else
   SetTimer(1,m_nCycleTime,NULL); //设置定时器1 m_nCycleTime
 }
 else
 {
  KillTimer(1);  //“杀”掉定时器1
 }
}

void CGPS_COM1Dlg::OnChangeEdit_CycleTime() 
{
 // TODO: If this is a RICHEDIT control, the control will not
 // send this notification unless you override the CDialog::OnInitDialog()
 // function and call CRichEditCtrl().SetEventMask()
 // with the ENM_CHANGE flag ORed into the mask.
 
 // TODO: Add your control notification handler code here
 
 CEdit* pEdit=(CEdit*)GetDlgItem(IDC_EDIT1);
 CString strText;
 pEdit->GetWindowText(strText);
 m_nCycleTime=atoi(strText);


}

void CGPS_COM1Dlg::OnClearCount() 
{
 // TODO: Add your control notification handler code here
 RXcount=0;  
 TX_count=0;
 m_RXdatacount.SetWindowText("");//清除接收对话框中的数据 
 m_TXcount.SetWindowText("");//清除接收对话框中的数据 
}

void CGPS_COM1Dlg::OnButtonSavedata() 
{
 // TODO: Add your control notification handler code here
 UpdateData(TRUE);

 CFile m_rFile;
 LPCSTR lpszPath="c:\comdata";   //存盘路径为c:\comdata
 SetCurrentDirectory(lpszPath);

 CString  m_Filename,m_name1;
 m_name1=m_strFilename;   //填写的名字
 m_Filename=m_name1+".txt";  //以TXT格式存储
 if(0==m_strFilename.GetLength())
 {
  AfxMessageBox("请先输入保存的文件名");
 }
 else
 {
  if(!m_rFile.Open(m_Filename,CFile::modeCreate | CFile::modeWrite))
  {
   AfxMessageBox("创建记录文件失败!");
   return;
  }

  char TxtTemp[60000];   //字符串的长度
  int Maxsize=60000;    //
  int i=m_RXDATA.GetWindowText(TxtTemp,Maxsize);//将接受编辑框的数据取出放到数组TxtTemp中
  
  //在文件开始处写上保存日期
  CTime t=CTime::GetCurrentTime();
  CString str=t.Format("%Y年%m月%d日%H时%M分%S秒 ");
  m_rFile.Write((LPCTSTR)str,str.GetLength());
  //保存数据
  m_rFile.Write((LPCTSTR)TxtTemp,m_RXDATA.GetWindowTextLength());
  m_rFile.Flush(); 
  m_rFile.Close();  //关闭文件
  AfxMessageBox("保存成功");
  UpdateData(FALSE);
 }
}

在头文件中要声明这两个函数

  //由于这个转换函数的格式限制,在发送框中的十六制字符应该每两个字符之间插入一个空隔
  //如:A1 23 45 0B 00 29
  //CByteArray是一个动态字节数组,可参看MSDN帮助
int CGPS_COM1Dlg::String2Hex(CString str, CByteArray &senddata)
{
  int hexdata,lowhexdata;
  int hexdatalen=0;
  int len=str.GetLength();
  senddata.SetSize(len/2);
  for(int i=0;i<len;)
  {
   char lstr,hstr=str[i];
   if(hstr==' ')
   {
    i++;
    continue;
   }
   i++;
   if(i>=len)
   break;

   lstr=str[i];
   hexdata=ConvertHexChar(hstr);
   lowhexdata=ConvertHexChar(lstr);
   if((hexdata==16)||(lowhexdata==16))
    break;
   else 
    hexdata=hexdata*16+lowhexdata;
   i++;
   senddata[hexdatalen]=(char)hexdata;
   hexdatalen++;
  }
  senddata.SetSize(hexdatalen);
  return hexdatalen;
}

  //这是一个将字符转换为相应的十六进制值的函数
  //好多C语言书上都可以找到
  //功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1
char CGPS_COM1Dlg::ConvertHexChar(char ch) 
{
  if((ch>='0')&&(ch<='9'))
   return ch-0x30;
  else if((ch>='A')&&(ch<='F'))
    return ch-'A'+10;
  else if((ch>='a')&&(ch<='f'))
    return ch-'a'+10;
  else return (-1);
}

原文地址:https://www.cnblogs.com/jack-jia-moonew/p/4178663.html