有关问题未结,再发一蛋——MSCOMM控件 and CSerialport类,强淫们请进!
问题未结,再发一蛋——MSCOMM控件 and CSerialport类,强淫们请进!!
程序功能:向串口写指令数据。
已采用MSCOMM控件方式实现,代码见下面所附,其中函数SendGpsCmd();是我用来往串口写“指令数据”的函数。
其中定义了两种发送模式:
第一种模式ModeAnsi用来发送诸如“$PSRF100,0,57600,8,1,0*37”格式的指令数据;
第二种模式ModeHex用来发送诸如“A0A20007961E540006000A0118B0B3”格式的指令数据(谁能解释一下这种指令的格式规则?);
该函数工作正常。有一款软件叫“串口调试精灵”,就是这样实现的。它有一种“按十六进制发送”方式,就是上述第二种模式的方式。
//参数i我用来标示不同的串口
void CGpsTestWizardDlg::SendGpsCmd(int i,int iMode, CString szSendStr)
{
int len;
CByteArray hexdata;
switch(iMode)
{
case ModeAnsi:
pCom[i]-> SetOutput(COleVariant(szSendStr));
break;
case ModeHex:
len=StringToHex(szSendStr,hexdata);
pCom[i]-> SetOutput(COleVariant(hexdata));
break;
}
}
int CGpsTestWizardDlg::StringToHex(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];//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;
}
//这是一个将 "字符 "转换为相应的十六进制值的函数
//功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1
char CGpsTestWizardDlg::ConvertHexChar(char ch)
{
if((ch> = '0 ')&&(ch <= '9 '))//0的ascii码是48,即0x30
return ch-0x30;
else if((ch> = 'A ')&&(ch <= 'F '))//A-- 65
return ch- 'A '+10;
else if((ch> = 'a ')&&(ch <= 'f '))//a --97
return ch- 'a '+10;
else return (-1);
}
程序目标:要在新创建的线程中操作和使用mscomm控件,而在主程序中读取mscomm控件从串口中出来的数据。却发现MSCOMM无法与多线程联合使用(ps:或者是我未得其法?),所以考虑使用网络上的CSerialport类来实现。
CSerialport类往串口写数据的函数是:CSerialPort::WriteToPort(char* string);
熟悉CSerailport类的达人注意了,问题在此:
我用该函数发送“$PSRF100,0,57600,8,1,0*37”是正常的。
可是用来发送“A0A20007961E540006000A0118B0B3”则不对,跟预期不一致。也就是说怎么使用WriteToPort(char* string)完成上述第二种模式的数据发送?是要对该函数作什么改写,还是要对“十六进制字符串”作什么处理?
内容比较多,希望表述清楚了,先感谢大家帮忙!急待
------解决方案--------------------
楼主,MSCOMM空间控件可以在多线程中使用,我以前用过,同时工作十几个串口两两工作为一个线程。
用文件形式做串口通讯,楼主要注意都是以字节char 形势发送的,变成别的形势需要楼主自己处理。
------解决方案--------------------
A0A20007961E540006000A0118B0B3
这样的数据需要使用无符号字符数组来发送,你需要转换为unsigned char型
------解决方案--------------------
CSerailport处理发送NULL(0x00)字符会有问题,因为WriteToPort是按char*发送的,0x00被自动截断了,解决方法,增加一个函数,如:
// Write a BYTE[] to the port
//
void CSerialPort::WriteToPort(BYTE bWriteBuffer[],int nWriteBufferSize)
{
assert(m_hComm != 0);
//int nSize = sizeof(bWriteBuffer)/sizeof(BYTE);
memcpy(m_szWriteBuffer, bWriteBuffer, nWriteBufferSize);
m_nWriteBufferSize = nWriteBufferSize;
// set event for write
SetEvent(m_hWriteEvent);
}
------解决方案--------------------
程序功能:向串口写指令数据。
已采用MSCOMM控件方式实现,代码见下面所附,其中函数SendGpsCmd();是我用来往串口写“指令数据”的函数。
其中定义了两种发送模式:
第一种模式ModeAnsi用来发送诸如“$PSRF100,0,57600,8,1,0*37”格式的指令数据;
第二种模式ModeHex用来发送诸如“A0A20007961E540006000A0118B0B3”格式的指令数据(谁能解释一下这种指令的格式规则?);
该函数工作正常。有一款软件叫“串口调试精灵”,就是这样实现的。它有一种“按十六进制发送”方式,就是上述第二种模式的方式。
//参数i我用来标示不同的串口
void CGpsTestWizardDlg::SendGpsCmd(int i,int iMode, CString szSendStr)
{
int len;
CByteArray hexdata;
switch(iMode)
{
case ModeAnsi:
pCom[i]-> SetOutput(COleVariant(szSendStr));
break;
case ModeHex:
len=StringToHex(szSendStr,hexdata);
pCom[i]-> SetOutput(COleVariant(hexdata));
break;
}
}
int CGpsTestWizardDlg::StringToHex(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];//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;
}
//这是一个将 "字符 "转换为相应的十六进制值的函数
//功能:若是在0-F之间的字符,则转换为相应的十六进制字符,否则返回-1
char CGpsTestWizardDlg::ConvertHexChar(char ch)
{
if((ch> = '0 ')&&(ch <= '9 '))//0的ascii码是48,即0x30
return ch-0x30;
else if((ch> = 'A ')&&(ch <= 'F '))//A-- 65
return ch- 'A '+10;
else if((ch> = 'a ')&&(ch <= 'f '))//a --97
return ch- 'a '+10;
else return (-1);
}
程序目标:要在新创建的线程中操作和使用mscomm控件,而在主程序中读取mscomm控件从串口中出来的数据。却发现MSCOMM无法与多线程联合使用(ps:或者是我未得其法?),所以考虑使用网络上的CSerialport类来实现。
CSerialport类往串口写数据的函数是:CSerialPort::WriteToPort(char* string);
熟悉CSerailport类的达人注意了,问题在此:
我用该函数发送“$PSRF100,0,57600,8,1,0*37”是正常的。
可是用来发送“A0A20007961E540006000A0118B0B3”则不对,跟预期不一致。也就是说怎么使用WriteToPort(char* string)完成上述第二种模式的数据发送?是要对该函数作什么改写,还是要对“十六进制字符串”作什么处理?
内容比较多,希望表述清楚了,先感谢大家帮忙!急待
------解决方案--------------------
楼主,MSCOMM空间控件可以在多线程中使用,我以前用过,同时工作十几个串口两两工作为一个线程。
用文件形式做串口通讯,楼主要注意都是以字节char 形势发送的,变成别的形势需要楼主自己处理。
------解决方案--------------------
A0A20007961E540006000A0118B0B3
这样的数据需要使用无符号字符数组来发送,你需要转换为unsigned char型
------解决方案--------------------
CSerailport处理发送NULL(0x00)字符会有问题,因为WriteToPort是按char*发送的,0x00被自动截断了,解决方法,增加一个函数,如:
// Write a BYTE[] to the port
//
void CSerialPort::WriteToPort(BYTE bWriteBuffer[],int nWriteBufferSize)
{
assert(m_hComm != 0);
//int nSize = sizeof(bWriteBuffer)/sizeof(BYTE);
memcpy(m_szWriteBuffer, bWriteBuffer, nWriteBufferSize);
m_nWriteBufferSize = nWriteBufferSize;
// set event for write
SetEvent(m_hWriteEvent);
}
------解决方案--------------------