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秒\r\n");
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);
}