小弟通过电脑的232串口读取外部激光测距传感器的测量值,程序是根据龚建伟老师的串口调试助手写的。激光发射的函数通过OnTimer函数触发,每5s发射一次。我想从激光返回的CString类型的字符串获取测量的值,并转化成double类型的数据,下面是我的程序。
void SCOMM::OnComm()//10.23mhf 读串口数据
{ //char *str,*str1;
COleSafeArray safearray_inp;
VARIANT variant_inp;
LONG len,k;
BYTE rxdata[2048];
CString strtemp;
CString strry1;
CString strry;
if(m_comm.get_CommEvent()==2)
{
variant_inp=m_comm.get_Input();
//将str的指针指向数据缓冲区
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=5;k<len;k++) //将数组转换为Cstring型变量(我自己写的,从字符串中获取数据位)
{
BYTE bt=*(char*)(rxdata+k); //字符型
strry.Format("%c",bt); //将字符送入临时变量strtemp存放
strry1+=strry; //加入接收编辑框对应字符串
}
rs_l_err=_tstof(strry1);//转化成double类型
laser_l_err=rs_l_err;
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp
m_strRXData+=strtemp; //加入接收编辑框对应字符串
}
} UpdateData(FALSE); //更新编辑框内容
}单步调试的时候,激光每次返回的字符串是“128‘$’,6‘_’,130,48‘0’,46 ‘0’,49‘1’,57‘8’,152”,单步调试的时候可以读取正确的测量值0.19800000000001。但在正常运行的时候,激光每5s发射一次,这时候返回的值就不对。哪位大侠帮忙解答一下
void SCOMM::OnComm()//10.23mhf 读串口数据
{ //char *str,*str1;
COleSafeArray safearray_inp;
VARIANT variant_inp;
LONG len,k;
BYTE rxdata[2048];
CString strtemp;
CString strry1;
CString strry;
if(m_comm.get_CommEvent()==2)
{
variant_inp=m_comm.get_Input();
//将str的指针指向数据缓冲区
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=5;k<len;k++) //将数组转换为Cstring型变量(我自己写的,从字符串中获取数据位)
{
BYTE bt=*(char*)(rxdata+k); //字符型
strry.Format("%c",bt); //将字符送入临时变量strtemp存放
strry1+=strry; //加入接收编辑框对应字符串
}
rs_l_err=_tstof(strry1);//转化成double类型
laser_l_err=rs_l_err;
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp
m_strRXData+=strtemp; //加入接收编辑框对应字符串
}
} UpdateData(FALSE); //更新编辑框内容
}单步调试的时候,激光每次返回的字符串是“128‘$’,6‘_’,130,48‘0’,46 ‘0’,49‘1’,57‘8’,152”,单步调试的时候可以读取正确的测量值0.19800000000001。但在正常运行的时候,激光每5s发射一次,这时候返回的值就不对。哪位大侠帮忙解答一下
解决方案 »
- 2012 十项决定的清单 -- 刚刚看到别人写Web的,我觉得C的我也需要
- WaitForSingleObject(m_vClientTask[i].hThread, 1000)
- 请教高手们,对话框中CListCtrl列表控件的内容如何选择部分列,并实现打印功能!
- WTL中获得当前实例的句柄的函数是啥?
- 谁有图形界面的ping工具?
- 我自己写的类,在其中建立其他类的实例就出错?
- 怎么改变主窗口框架的颜色?
- 关于多台电脑的串口通信,请高手执教!!!!!!不够可以在加!!!!
- 把窗口设置为当前窗口的函数是哪个? 在线等
- 关于MSFlexGrid control控件的问题!!
- 如何拦截远程消息?
- Socket与多线程!
数组使用前要初始化memset(rxdata,0,2048);
后面for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp
m_strRXData+=strtemp; //加入接收编辑框对应字符串
}
这些完全多余
for(k=5;k<len;k++) //将数组转换为Cstring型变量(我自己写的,从字符串中获取数据位)
{
BYTE bt=*(char*)(rxdata+k); //字符型
strry.Format("%c",bt); //将字符送入临时变量strtemp存放
strry1+=strry; //加入接收编辑框对应字符串
}
rs_l_err=_tstof(strry1);//转化成double类型
laser_l_err=rs_l_err;
m_ctrComm.SetInputLen(0);//你设的0对吧,也就是缓冲区有多少你要多少但是一般串口的波特率设置为9600也就是10ms一个字节,你设置5ms发一次,这意味着什么?
先通过波特率和字节数算好你发的时间和接收的时间5ms太短
{ COleSafeArray safearray_inp;
VARIANT variant_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
CString strtemp;
CString strry1;
CString strry;
CString strry2;
CString strry3;
double rs_l_err1,rs_l_err2;
if(m_comm.get_CommEvent()==2)
{
variant_inp=m_comm.get_Input();//将str的指针指向数据缓冲区
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=5;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt2=*(char*)(rxdata+k); //字符型
strry3.Format("%c",bt2); //将字符送入临时变量strtemp存放
strry2+=strry3; //加入接收编辑框对应字符串
}
rs_l_err2=_tstof(strry2);//转化成double类型
Sleep(500);
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt1=*(char*)(rxdata+k); //字符型
strry.Format("%c",bt1); //将字符送入临时变量strtemp存放
strry1+=strry; //加入接收编辑框对应字符串
}
rs_l_err1=_tstof(strry1);//转化成double类型
rs_l_err=rs_l_err1/1000;
if(rs_l_err>0.00005)
{
laser_l_err=rs_l_err;
}
Sleep(600);
for(k=0;k<len;k++) //将数组转换为Cstring型变量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
m_strRXData+=strtemp; //加入接收编辑框对应字符串
}
}
UpdateData(FALSE); //更新编辑框内容
}void SCOMM::OnBnClickedOpenport()//10.23mhf 读串口数据
{
// TODO: 在此添加控件通知处理程序代码
m_Port=1;
m_comm.put_CommPort(m_Port);//设置串口
m_comm.put_InputMode(1);//设置数据读取格式为二进制
m_comm.put_Settings(_T("9600,n,8,1"));//传输参数,波特率9600,无校验,8个数据位,1个停止位
m_comm.put_RThreshold(1);//缓冲区内有一个字符就可以接收
m_comm.put_InBufferSize(4086);//接收缓冲区的大小2字节
m_comm.put_OutBufferSize(4086);//发送缓冲区大小2字节
m_comm.put_InBufferCount(0);//清空接收缓冲区
if(!m_comm.get_PortOpen())
{
m_comm.put_PortOpen(true);//打开串口
GetDlgItem(ID_OPENPORT)->EnableWindow(FALSE);
GetDlgItem(ID_CLOSEPORT)->EnableWindow(TRUE);
Is_open=true;
}
else
MessageBox(_T("串行口已经打开!"),_T("提示"));}void SCOMM::OnBnClickedCloseport()
{
// TODO: 在此添加控件通知处理程序代码
if(m_comm.get_PortOpen())
{
m_comm.put_PortOpen(false);//关闭串口
GetDlgItem(ID_OPENPORT)->EnableWindow(TRUE);
GetDlgItem(ID_CLOSEPORT)->EnableWindow(FALSE);
Is_open=false;
KillTimer(1);
}
}void SCOMM::OnBnClickedOne()//单步测量
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE); //读取编辑框内容
if(m_ctrlHexSend.GetCheck())
{
m_strSend="80060278";
CByteArray hexdata;
int len=String2Hex(m_strSend,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数
m_comm.put_Output(COleVariant(hexdata)); //发送十六进制数据
}
else
m_comm.put_Output(COleVariant(m_strSend));//发送ASCII字符数据
}int SCOMM::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;
}char SCOMM::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);
return 0;
}void SCOMM::OnBnClickedCon()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE); //读取编辑框内容
if(m_ctrlHexSend.GetCheck())
{
m_strSend="80060377";
CByteArray hexdata;
int len=String2Hex(m_strSend,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数
m_comm.put_Output(COleVariant(hexdata)); //发送十六进制数据
}
else
m_comm.put_Output(COleVariant(m_strSend));//发送ASCII字符数据
}void SCOMM::OnBnClickedStop()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE); //读取编辑框内容
if(m_ctrlHexSend.GetCheck())
{
m_strSend="8004027A";
CByteArray hexdata;
int len=String2Hex(m_strSend,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数
m_comm.put_Output(COleVariant(hexdata)); //发送十六进制数据
}
else
m_comm.put_Output(COleVariant(m_strSend));//发送ASCII字符数据
}void SCOMM::OnCheckAutosend()
{
// TODO: 在此添加控件通知处理程序代码
m_bAutoSend=!m_bAutoSend;
if(m_bAutoSend)
{
SetTimer(156,3000,NULL);
}
else
{
KillTimer(156);
}
}void SCOMM::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
UpdateData();
if(nIDEvent==156)
{
OnBnClickedOne();
}
UpdateData(0);
CDialog::OnTimer(nIDEvent);
}
不好意思有点长,我现在是rs_l_err1变量获取转化的double测量值,现在是可以获取最后两位的值