5069
- 收藏
- 点赞
- 分享
- 举报
串口发送数据的程序vc实现
给你一个api的例子吧:
⑴.在中mainfrm.cpp定义全局变量
handle hcom; // 准备打开的串口的句柄
handle hcommwatchthread ;//辅助线程的全局函数
⑵.打开串口,设置串口
hcom =createfile( "com2", generic_read | generic_write, // 允许读写
0, // 此项必须为0
null, // no security attrs
open_existing, //设置产生方式
file_flag_overlapped, // 我们准备使用异步通信
null );
请大家注意,我们使用了file_flag_overlapped结构。这正是使用api实现非阻塞通信的关键所在。
assert(hcom!=invalid_handle_value); //检测打开串口操作是否成功
setcommmask(hcom, ev_rxchar|ev_txempty );//设置事件驱动的类型
setupcomm( hcom, 1024,512) ; //设置输入、输出缓冲区的大小
purgecomm( hcom, purge_txabort | purge_rxabort | purge_txclear
| purge_rxclear ); //清干净输入、输出缓冲区
commtimeouts commtimeouts ; //定义超时结构,并填写该结构
…………
setcommtimeouts( hcom, &commtimeouts ) ;//设置读写操作所允许的超时
dcb dcb ; // 定义数据控制块结构
getcommstate(hcom, &dcb ) ; //读串口原来的参数设置
dcb.baudrate =9600; dcb.bytesize =8; dcb.parity = noparity;
dcb.stopbits = onestopbit ;dcb.fbinary = true ;dcb.fparity = false;
setcommstate(hcom, &dcb ) ; //串口参数配置
上述的commtimeouts结构和dcb都很重要,实际工作中需要仔细选择参数。
⑶启动一个辅助线程,用于串口事件的处理。
windows提供了两种线程,辅助线程和用户界面线程。区别在于:辅助线程没有窗口,所以它没有自己的消息循环。但是辅助线程很容易编程,通常也很有用。
在次,我们使用辅助线程。主要用它来监视串口状态,看有无数据到达、通信有无错误;而主线程则可专心进行数据处理、提供友好的用户界面等重要的工作。
hcommwatchthread=
createthread( (lpsecurity_attributes) null, //安全属性
0,//初始化线程栈的大小,缺省为与主线程大小相同
(lpthread_start_routine)commwatchproc, //线程的全局函数
getsafehwnd(), //此处传入了主框架的句柄
0, &dwthreadid );
assert(hcommwatchthread!=null);
⑷为辅助线程写一个全局函数,主要完成数据接收的工作。
请注意overlapped结构的使用,以及怎样实现了非阻塞通信。
uint commwatchproc(hwnd hsendwnd){
dword dwevtmask=0 ;
setcommmask( hcom, ev_rxchar|ev_txempty );//有哪些串口事件需要监视?
waitcommevent( hcom, &dwevtmask, os );// 等待串口通信事件的发生
检测返回的dwevtmask,知道发生了什么串口事件:
if ((dwevtmask & ev_rxchar) == ev_rxchar){ // 缓冲区中有数据到达
comstat comstat ; dword dwlength;
clearcommerror(hcom, &dwerrorflags, &comstat ) ;
dwlength = comstat.cbinque ; //输入缓冲区有多少数据?
if (dwlength > 0) {
bool freadstat ;
freadstat = readfile( hcom, lpbuffer,dwlength, &dwbytesread,
&read_os( npttyinfo ) ); //读数据
注:我们在crearefile()时使用了file_flag_overlapped,现在readfile()也必须使用
lpoverlapped结构.否则,函数会不正确地报告读操作已完成了.
使用lpoverlapped结构, readfile()立即返回,不必等待读操作完成,实现非阻塞
通信.此时, readfile()返回false, getlasterror()返回error_io_pending.
if (!freadstat){
if (getlasterror() == error_io_pending){
while(!getoverlappedresult(hcom,
&read_os( npttyinfo ), & dwbytesread, true )){
dwerror = getlasterror();
if(dwerror == error_io_incomplete) continue;
//缓冲区数据没有读完,继续
…… ……
::postmessage((hwnd)hsendwnd,wm_notifyprocess,0,0);//通知主线程,串口收到数据 }
所谓的非阻塞通信,也即异步通信。是指在进行需要花费大量时间的数据读写操作时,一旦调用readfile()、writefile(), 就能立即返回,而让实际的读写操作在后台运行;相反,如使用阻塞通信,则必须在读或写操作全部完成后才能返回。由于操作可能需要任意长的时间才能完成,于是问题就出现了。
非常阻塞操作还允许读、写操作能同时进行,在实际工作中非常有用。
要使用非阻塞通信,首先在createfile()时必须使用file_flag_overlapped;然后在 readfile()时lpoverlapped参数一定不能为null,接着检查函数调用的返回值,调用getlasterror(),看是否返回error_io_pending。如是,最后调用getoverlappedresult()返回重叠操作(overlapped operation)的结果;writefile()的使用类似。
⑸.在主线程中发送下行命令。
bool fwritestat ; char szbuffer[count];
…………//准备好发送的数据,放在szbuffer[]中
fwritestat = writefile(hcom, szbuffer, dwbytestowrite,
&dwbyteswritten, &write_os( npttyinfo ) ); //写数据
注:我们在crearefile()时使用了file_flag_overlapped,现在writefile()也必须使用 lpoverlapped结构.否则,函数会不正确地报告写操作已完成了.
使用lpoverlapped结构,writefile()立即返回,不必等待写操作完成,实现非阻塞 通信.此时, writefile()返回false, getlasterror()返回error_io_pending.
int err=getlasterror();
if (!fwritestat) {
if(getlasterror() == error_io_pending){
while(!getoverlappedresult(hcom, &write_os( npttyinfo ),
&dwbyteswritten, true )) {
dwerror = getlasterror();
if(dwerror == error_io_incomplete){
// normal result if not finished
dwbytessent += dwbyteswritten; continue; }
发表者:delphihero
回车用 /r/n 表示;如果用mscomm 控件也很简单
如果你还没有下载源程序,又对本文有兴趣,请 立即下载
1.建立项目:打开vc++6.0,建立一个基于对话框的mfc应用程序scommtest;
2.在项目中插入mscomm控件 选择project菜单下add to project子菜单中的 components and controls…选项,在弹出的对话框中双击registered activex controls项,则所有注册过的activex控件出现在列表框中。 选择microsoft communications control, version 6.0,,单击insert按钮将它插入到我们的project中来,接受缺省的选项。,
这时在classview视窗中就可以看到cmscomm类了,,并且在控件工具栏controls中出现了电话图标,现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
3.利用classwizard定义cmscomm类控制对象 打开classwizard->member viariables选项卡,选择cscommtestdlg类,为idc_mscomm1添加控制变量:m_ctrlcomm,这时你可以看一看,在对话框头文件中自动加入了//{{afx_includes() #include "mscomm.h" //}}afx_includes 。
4.在对话框中添加控件 向主对话框中添加两个编辑框,一个用于接收显示数据id为idc_edit_rxdata,另一个用于输入发送数据,id为idc_edit_txdata,再添加一个按钮,功能是按一次就把发送编辑框中的内容发送一次,将其id设为idc_button_manualsend。别忘记了将接收编辑框的properties->styles中把miltiline和vertical scroll属性选上,发送编辑框若你想输入多行文字,也可选上miltiline。
再打开classwizard->member viariables选项卡,选择cscommtestdlg类, 为idc_edit_rxdata添加cstring变量m_strrxdata, 为idc_edit_txdata添加cstring变量m_strtxdata。说明: m_strrxdata和m_strtxdata分别用来放入接收和发送的字符数据。
5.添加串口事件消息处理函数oncomm() 打开classwizard->message maps,选择类cscommtestdlg,选择idc_mscomm1,双击消息oncomm,将弹出的对话框中将函数名改为oncomm,ok。
这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们在oncomm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码:
void cscommtestdlg::oncomm()
{
// 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;
if(m_ctrlcomm.getcommevent()==2) //事件值为2表示接收缓冲区内有字符
{ ////////以下你可以根据自己的通信协议加入处理代码
variant_inp=m_ctrlcomm.getinput(); //读缓冲区
safearray_inp=variant_inp; //variant型变量转换为colesafearray型变量
len=safearray_inp.getonedimsize(); //得到有效数据长度
for(k=0;k
safearray_inp.getelement(&k,rxdata+k);//转换为byte型数组
for(k=0;k
{
byte bt=*(char*)(rxdata+k); //字符型
strtemp.format("%c",bt); //将字符送入临时变量strtemp存放
m_strrxdata+=strtemp; //加入接收编辑框对应字符串
}
}
updatedata(false); //更新编辑框内容
}
到目前为止还不能在接收编辑框中看到数据,因为我们还没有打开串口,但运行程序不应该有任何错误,不然,你肯定哪儿没看仔细,因为我是打开vc6对照着做一步写一行的,运行试试。没错吧?那么做下一步:
6.打开串口和设置串口参数 你可以在你需要的时候打开串口,例如在程序中做一个开始按钮,在该按钮的处理函数中打开串口。现在我们在主对话框的cscommtestdlg::oninitdialog()打开串口,加入如下代码:
// todo: add extra initialization here
if(m_ctrlcomm.getportopen())
m_ctrlcomm.setportopen(false);
m_ctrlcomm.setcommport(1); //选择com1
if( !m_ctrlcomm.getportopen())
m_ctrlcomm.setportopen(true);//打开串口
else
afxmessagebox("cannot open serial port");
m_ctrlcomm.setsettings("9600,n,8,1"); //波特率9600,无校验,8个数据位,1个停止位
m_ctrlcomm.setinputmodel(1); //1:表示以二进制方式检取数据
m_ctrlcomm.setrthreshold(1);
//参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的oncomm事件
m_ctrlcomm.setinputlen(0); //设置当前接收区数据长度为0
m_ctrlcomm.getinput();//先预读缓冲区以清除残留数据
现在你可以试试程序了,将串口线接好后,打开串口调试助手,并将串口设在com2,选上自动发送,也可以等会手动发送。再执行你编写的程序,接收框里应该有数据显示了。
7.发送数据 先为发送按钮添加一个单击消息即bn_clicked处理函数,打开classwizard->message maps,选择类cscommtestdlg,选择idc_button_manualsend,双击bn_clicked添加onbuttonmanualsend()函数,并在函数中添加如下代码:
void cscommtestdlg::onbuttonmanualsend()
{
// todo: add your control notification handler code here
updatedata(true); //读取编辑框内容
m_ctrlcomm.setoutput(colevariant(m_strtxdata));//发送数据
}
运行程序,在发送编辑框中随意输入点什么,单击发送按钮,啊!看看,在另一端的串口调试助手接收框里出现了什么。
最后说明一下,由于用到vc控件,在没有安装vc的计算机上运行时要从vc中把mscomm32.ocx、msvcrt.dll、mfc42.dll拷到windows目录下的system子目录中
⑴.在中mainfrm.cpp定义全局变量
handle hcom; // 准备打开的串口的句柄
handle hcommwatchthread ;//辅助线程的全局函数
⑵.打开串口,设置串口
hcom =createfile( "com2", generic_read | generic_write, // 允许读写
0, // 此项必须为0
null, // no security attrs
open_existing, //设置产生方式
file_flag_overlapped, // 我们准备使用异步通信
null );
请大家注意,我们使用了file_flag_overlapped结构。这正是使用api实现非阻塞通信的关键所在。
assert(hcom!=invalid_handle_value); //检测打开串口操作是否成功
setcommmask(hcom, ev_rxchar|ev_txempty );//设置事件驱动的类型
setupcomm( hcom, 1024,512) ; //设置输入、输出缓冲区的大小
purgecomm( hcom, purge_txabort | purge_rxabort | purge_txclear
| purge_rxclear ); //清干净输入、输出缓冲区
commtimeouts commtimeouts ; //定义超时结构,并填写该结构
…………
setcommtimeouts( hcom, &commtimeouts ) ;//设置读写操作所允许的超时
dcb dcb ; // 定义数据控制块结构
getcommstate(hcom, &dcb ) ; //读串口原来的参数设置
dcb.baudrate =9600; dcb.bytesize =8; dcb.parity = noparity;
dcb.stopbits = onestopbit ;dcb.fbinary = true ;dcb.fparity = false;
setcommstate(hcom, &dcb ) ; //串口参数配置
上述的commtimeouts结构和dcb都很重要,实际工作中需要仔细选择参数。
⑶启动一个辅助线程,用于串口事件的处理。
windows提供了两种线程,辅助线程和用户界面线程。区别在于:辅助线程没有窗口,所以它没有自己的消息循环。但是辅助线程很容易编程,通常也很有用。
在次,我们使用辅助线程。主要用它来监视串口状态,看有无数据到达、通信有无错误;而主线程则可专心进行数据处理、提供友好的用户界面等重要的工作。
hcommwatchthread=
createthread( (lpsecurity_attributes) null, //安全属性
0,//初始化线程栈的大小,缺省为与主线程大小相同
(lpthread_start_routine)commwatchproc, //线程的全局函数
getsafehwnd(), //此处传入了主框架的句柄
0, &dwthreadid );
assert(hcommwatchthread!=null);
⑷为辅助线程写一个全局函数,主要完成数据接收的工作。
请注意overlapped结构的使用,以及怎样实现了非阻塞通信。
uint commwatchproc(hwnd hsendwnd){
dword dwevtmask=0 ;
setcommmask( hcom, ev_rxchar|ev_txempty );//有哪些串口事件需要监视?
waitcommevent( hcom, &dwevtmask, os );// 等待串口通信事件的发生
检测返回的dwevtmask,知道发生了什么串口事件:
if ((dwevtmask & ev_rxchar) == ev_rxchar){ // 缓冲区中有数据到达
comstat comstat ; dword dwlength;
clearcommerror(hcom, &dwerrorflags, &comstat ) ;
dwlength = comstat.cbinque ; //输入缓冲区有多少数据?
if (dwlength > 0) {
bool freadstat ;
freadstat = readfile( hcom, lpbuffer,dwlength, &dwbytesread,
&read_os( npttyinfo ) ); //读数据
注:我们在crearefile()时使用了file_flag_overlapped,现在readfile()也必须使用
lpoverlapped结构.否则,函数会不正确地报告读操作已完成了.
使用lpoverlapped结构, readfile()立即返回,不必等待读操作完成,实现非阻塞
通信.此时, readfile()返回false, getlasterror()返回error_io_pending.
if (!freadstat){
if (getlasterror() == error_io_pending){
while(!getoverlappedresult(hcom,
&read_os( npttyinfo ), & dwbytesread, true )){
dwerror = getlasterror();
if(dwerror == error_io_incomplete) continue;
//缓冲区数据没有读完,继续
…… ……
::postmessage((hwnd)hsendwnd,wm_notifyprocess,0,0);//通知主线程,串口收到数据 }
所谓的非阻塞通信,也即异步通信。是指在进行需要花费大量时间的数据读写操作时,一旦调用readfile()、writefile(), 就能立即返回,而让实际的读写操作在后台运行;相反,如使用阻塞通信,则必须在读或写操作全部完成后才能返回。由于操作可能需要任意长的时间才能完成,于是问题就出现了。
非常阻塞操作还允许读、写操作能同时进行,在实际工作中非常有用。
要使用非阻塞通信,首先在createfile()时必须使用file_flag_overlapped;然后在 readfile()时lpoverlapped参数一定不能为null,接着检查函数调用的返回值,调用getlasterror(),看是否返回error_io_pending。如是,最后调用getoverlappedresult()返回重叠操作(overlapped operation)的结果;writefile()的使用类似。
⑸.在主线程中发送下行命令。
bool fwritestat ; char szbuffer[count];
…………//准备好发送的数据,放在szbuffer[]中
fwritestat = writefile(hcom, szbuffer, dwbytestowrite,
&dwbyteswritten, &write_os( npttyinfo ) ); //写数据
注:我们在crearefile()时使用了file_flag_overlapped,现在writefile()也必须使用 lpoverlapped结构.否则,函数会不正确地报告写操作已完成了.
使用lpoverlapped结构,writefile()立即返回,不必等待写操作完成,实现非阻塞 通信.此时, writefile()返回false, getlasterror()返回error_io_pending.
int err=getlasterror();
if (!fwritestat) {
if(getlasterror() == error_io_pending){
while(!getoverlappedresult(hcom, &write_os( npttyinfo ),
&dwbyteswritten, true )) {
dwerror = getlasterror();
if(dwerror == error_io_incomplete){
// normal result if not finished
dwbytessent += dwbyteswritten; continue; }
发表者:delphihero
回车用 /r/n 表示;如果用mscomm 控件也很简单
如果你还没有下载源程序,又对本文有兴趣,请 立即下载
1.建立项目:打开vc++6.0,建立一个基于对话框的mfc应用程序scommtest;
2.在项目中插入mscomm控件 选择project菜单下add to project子菜单中的 components and controls…选项,在弹出的对话框中双击registered activex controls项,则所有注册过的activex控件出现在列表框中。 选择microsoft communications control, version 6.0,,单击insert按钮将它插入到我们的project中来,接受缺省的选项。,
这时在classview视窗中就可以看到cmscomm类了,,并且在控件工具栏controls中出现了电话图标,现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
3.利用classwizard定义cmscomm类控制对象 打开classwizard->member viariables选项卡,选择cscommtestdlg类,为idc_mscomm1添加控制变量:m_ctrlcomm,这时你可以看一看,在对话框头文件中自动加入了//{{afx_includes() #include "mscomm.h" //}}afx_includes 。
4.在对话框中添加控件 向主对话框中添加两个编辑框,一个用于接收显示数据id为idc_edit_rxdata,另一个用于输入发送数据,id为idc_edit_txdata,再添加一个按钮,功能是按一次就把发送编辑框中的内容发送一次,将其id设为idc_button_manualsend。别忘记了将接收编辑框的properties->styles中把miltiline和vertical scroll属性选上,发送编辑框若你想输入多行文字,也可选上miltiline。
再打开classwizard->member viariables选项卡,选择cscommtestdlg类, 为idc_edit_rxdata添加cstring变量m_strrxdata, 为idc_edit_txdata添加cstring变量m_strtxdata。说明: m_strrxdata和m_strtxdata分别用来放入接收和发送的字符数据。
5.添加串口事件消息处理函数oncomm() 打开classwizard->message maps,选择类cscommtestdlg,选择idc_mscomm1,双击消息oncomm,将弹出的对话框中将函数名改为oncomm,ok。
这个函数是用来处理串口消息事件的,如每当串口接收到数据,就会产生一个串口接收数据缓冲区中有字符的消息事件,我们刚才添加的函数就会执行,我们在oncomm()函数加入相应的处理代码就能实现自已想要的功能了。请你在函数中加入如下代码:
void cscommtestdlg::oncomm()
{
// 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;
if(m_ctrlcomm.getcommevent()==2) //事件值为2表示接收缓冲区内有字符
{ ////////以下你可以根据自己的通信协议加入处理代码
variant_inp=m_ctrlcomm.getinput(); //读缓冲区
safearray_inp=variant_inp; //variant型变量转换为colesafearray型变量
len=safearray_inp.getonedimsize(); //得到有效数据长度
for(k=0;k
for(k=0;k
byte bt=*(char*)(rxdata+k); //字符型
strtemp.format("%c",bt); //将字符送入临时变量strtemp存放
m_strrxdata+=strtemp; //加入接收编辑框对应字符串
}
}
updatedata(false); //更新编辑框内容
}
到目前为止还不能在接收编辑框中看到数据,因为我们还没有打开串口,但运行程序不应该有任何错误,不然,你肯定哪儿没看仔细,因为我是打开vc6对照着做一步写一行的,运行试试。没错吧?那么做下一步:
6.打开串口和设置串口参数 你可以在你需要的时候打开串口,例如在程序中做一个开始按钮,在该按钮的处理函数中打开串口。现在我们在主对话框的cscommtestdlg::oninitdialog()打开串口,加入如下代码:
// todo: add extra initialization here
if(m_ctrlcomm.getportopen())
m_ctrlcomm.setportopen(false);
m_ctrlcomm.setcommport(1); //选择com1
if( !m_ctrlcomm.getportopen())
m_ctrlcomm.setportopen(true);//打开串口
else
afxmessagebox("cannot open serial port");
m_ctrlcomm.setsettings("9600,n,8,1"); //波特率9600,无校验,8个数据位,1个停止位
m_ctrlcomm.setinputmodel(1); //1:表示以二进制方式检取数据
m_ctrlcomm.setrthreshold(1);
//参数1表示每当串口接收缓冲区中有多于或等于1个字符时将引发一个接收数据的oncomm事件
m_ctrlcomm.setinputlen(0); //设置当前接收区数据长度为0
m_ctrlcomm.getinput();//先预读缓冲区以清除残留数据
现在你可以试试程序了,将串口线接好后,打开串口调试助手,并将串口设在com2,选上自动发送,也可以等会手动发送。再执行你编写的程序,接收框里应该有数据显示了。
7.发送数据 先为发送按钮添加一个单击消息即bn_clicked处理函数,打开classwizard->message maps,选择类cscommtestdlg,选择idc_button_manualsend,双击bn_clicked添加onbuttonmanualsend()函数,并在函数中添加如下代码:
void cscommtestdlg::onbuttonmanualsend()
{
// todo: add your control notification handler code here
updatedata(true); //读取编辑框内容
m_ctrlcomm.setoutput(colevariant(m_strtxdata));//发送数据
}
运行程序,在发送编辑框中随意输入点什么,单击发送按钮,啊!看看,在另一端的串口调试助手接收框里出现了什么。
最后说明一下,由于用到vc控件,在没有安装vc的计算机上运行时要从vc中把mscomm32.ocx、msvcrt.dll、mfc42.dll拷到windows目录下的system子目录中
我来回答
回答0个
时间排序
认可量排序
暂无数据
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
相关问答
-
2020-10-21 17:20:36
-
2018-12-12 17:24:05
-
2020-10-22 14:55:26
-
2018-12-21 14:11:29
-
2020-04-07 13:57:54
-
2018-12-21 14:27:46
-
2018-12-19 16:40:29
-
2015-04-01 19:01:44
-
2020-10-26 14:01:00
-
2022-05-09 11:28:37
-
2020-08-29 10:50:04
-
02008-08-02 00:49:24
-
2018-11-28 15:13:24
-
2018-06-25 15:14:10
-
2020-10-29 11:14:15
-
2020-10-21 17:18:07
-
2014-12-21 08:57:26
-
2018-12-03 15:22:06
-
2018-11-01 13:41:21
无更多相似问答 去提问
点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
悬赏问答
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
-
10求HI3519DV500_SDK_V2.0.1.1
-
5有偿求HI3516DV500 + OV5647驱动
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认