急,如何用串口接收发送文件? 如何用串口发送和接收文件? 哪位能给个源程序? [email protected]小弟是初学者,多谢各位了 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/comm98/html/vbobjComm.asp HANDLE hCom;OVERLAPPED Write_OS, Read_OS, OS;//打开串口 int OpenComm(char *DeviceName){ hCom = CreateFile(DeviceName, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL); //创建串口,异步方式 if (hCom == INVALID_HANDLE_VALUE) return -1; //打开串口失败 else { SetCommMask( hCom, EV_RXCHAR|EV_TXEMPTY ); //设置串口事件 SetupComm( hCom, 4096,4096); //设置读写缓冲区大小 PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); memset(&Write_OS,0,sizeof(OVERLAPPED)); memset(&Read_OS,0,sizeof(OVERLAPPED)); memset(&OS,0,sizeof(OVERLAPPED)); COMMTIMEOUTS comTimeOut; //设置超时 comTimeOut.ReadIntervalTimeout = MAXDWORD; comTimeOut.ReadTotalTimeoutMultiplier = 3000; comTimeOut.ReadTotalTimeoutConstant = 200; comTimeOut.WriteTotalTimeoutMultiplier = 300; comTimeOut.WriteTotalTimeoutConstant = 200; SetCommTimeouts(hCom,&comTimeOut); Read_OS.Internal = 0; Read_OS.InternalHigh = 0; Read_OS.Offset = 0; Read_OS.OffsetHigh = 0; //设置结构 Write_OS.Internal = 0; Write_OS.InternalHigh = 0; Write_OS.Offset = 0; Write_OS.OffsetHigh = 0; //设置结构 Read_OS.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); Write_OS.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 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 ); return 0; }}例如:char comm[4]="COM1"; OpenComm(comm);//关闭串口void CloseComm(){ WaitForSingleObject(hReadThread, INFINITE); CloseHandle(hReadThread); CloseHandle(hCom);}//读取数据int ReadComm(){ Read_OS = {0}; DWORD dwRes; BYTE Buffer[255]; DWORD dwDataRead; ResetEvent(Read_OS.hEvent); if ( NULL == Read_OS.hEvent) return -1; if (ReadFile(hCom, Buffer, 3, NULL, &Read_OS)) return 0; //成功读出 else { dwRes = WaitForSingleObject(Read_OS.hEvent, 5000); //设置5秒超时 switch(dwRes) { case WAIT_OBJECT_0: if (!GetOverlappedResult(hCom, &Read_OS, &dwDataRead, TRUE)) { //操作失败,可用GetLastError()获取失败信息 return 1; } else { //成功 return 0; } break; case WAIT_TIMEOUT: //超时 return 2; break; default: break; } } CloseHandle(Read_OS.hEvent); return 0;}//写数据int WriteComm(){ Write_OS = {0}; DWORD dwRes; BYTE Buffer[255]; DWORD dwDataRead; ResetEvent(Write_OS.hEvent); if (NULL == Write_OS.hEvent) return -1; if(WriteFile(hCom, Buffer, 3, NULL, &Write_OS)) return 0; //成功 else { dwRes = WaitForSingleObject(&Write_OS, 5000); //设置5秒超时 switch(dwRes) { case WAIT_OBJECT_0: if (!GetOverlappedResult(hCom, &Write_OS, &dwDataRead, TRUE)) { //操作失败,可用GetLastError()获取失败信息 return 1; } else { //成功 return 0; } break; case WAIT_TIMEOUT: //超时 return 2; break; default: break; } } CloseHandle(Read_OS.hEvent); return 0;} 首先,在对话框中创建通信控件,若Control工具栏中缺少该控件,可通过菜单Project --> Add to Project --> Components and Control插入即可,再将该控件从工具箱中拉到对话框中。此时,你只需要关心控件提供的对 Windows 通讯驱动程序的 API 函数的接口。换句话说,只需要设置和监视MSComm控件的属性和事件。 打开所需串口后,需要考虑串口通信的时机。在接收或发送数据过程中,可能需要监视并响应一些事件和错误,所以事件驱动是处理串行端口交互作用的一种非常有效的方法。使用 OnComm 事件和 CommEvent 属性捕捉并检查通讯事件和错误的值。发生通讯事件或错误时,将触发 OnComm 事件,CommEvent 属性的值将被改变,应用程序检查 CommEvent 属性值并作出相应的反应// 若是在SDI中使用该控件则要调用下两句,在对话框程序中该语句有MFC自己创建// 所以不用人为添加DWORD style=WS_VISIBLE;m_MSComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1);// 串口控件的初始化DWORD style=WS_VISIBLE;m_MSComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1);if(m_MSComm.GetPortOpen()) //如果串口是打开的,则行关闭串口{ m_MSComm.SetPortOpen(FALSE);}m_MSComm.SetCommPort(1); //选择COM1m_MSComm.SetInBufferSize(1024); //接收缓冲区m_MSComm.SetOutBufferSize(1024);//发送缓冲区m_MSComm.SetInputLen(0);//设置当前接收区数据长度为0,表示全部读取m_MSComm.SetInputMode(1);//以二进制方式读写数据m_MSComm.SetRThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件m_MSComm.SetSettings("9600,n,8,1");//波特率9600无检验位,8个数据位,1个停止位if(!m_MSComm.GetPortOpen())//如果串口没有打开则打开 m_MSComm.SetPortOpen(TRUE);//打开串口else m_MSComm.SetOutBufferCount(0);// 控件事件的响应声明// *.h//{{AFX_MSG(CGolfView)afx_msg BOOL OnComm();DECLARE_EVENTSINK_MAP()//}}AFX_MSG// *.cppBEGIN_EVENTSINK_MAP(CGolfView, CView)//{{AFX_EVENTSINK_MAP(CAboutDlg)ON_EVENT(CGolfView, IDC_MSCOMM1, 1 /* OnComm */, OnComm, VTS_NONE)//}}AFX_EVENTSINK_MAPEND_EVENTSINK_MAP()// 控件事件的响应BOOL CGolfView::OnComm(){ VARIANT variant_inp; COleSafeArray safearray_inp; LONG len,k; BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed. CString strtemp; switch(m_MSComm.GetCommEvent()) { case 1: // comEvSend发送数据 break; case 2: // comEvReceive读取数据 // MessageBox(_T("读取数据事件"), _T("TRACE"), MB_OK); variant_inp=m_MSComm.GetInput(); //读缓冲区 safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量 len=safearray_inp.GetOneDimSize(); //得到有效数据长度 // 接受数据 for(k=0; k<len; k++) { safearray_inp.GetElement(&k,rxdata+k); //转换为BYTE型数组 BYTE bt=*(char*)(rxdata+k); //字符型 strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放 recd+=strtemp; } // UpdateData(TRUE); break; default: // 传输事件出错 m_MSComm.SetOutBufferCount(0); break; } UpdateData(FALSE); //更新图象内容 return TRUE;} 谢谢楼上的兄弟,小弟想知道,如果接收文件的话,用户需要选择文件存放路径的话应该怎么写呢?另外下面的代码请各位帮忙。。if(buf[0]=='0') //判断如果一帧数据第一字符是'0'的话就接收此文件{ //程序调到下一句的时候点确定会死掉大侠救命啊 if (AfxMessageBox("要接收文件吗?",NULL,MB_ICONWARNING|MB_OKCANCEL)==IDOK) { CFile cf; //BOOL fWriteState; DWORD dwBytesRead; DWORD dwCharToRead; dwCharToRead=0; dwCharToRead=(DWORD)cf.GetLength(); cf.Seek(0,CFile::begin); dwBytesRead=0; if(m_pSerial->m_hComm!=INVALID_HANDLE_VALUE&&dwCharToRead!=0) { char* buf=new char[dwCharToRead]; cf.Read(buf,dwCharToRead); if(!fReadState) { //AfxMessageBox(_T("无法向端口写入数据!")); } delete[] buf; } cf.Close(); return dwBytesRead; continue; // return; } } else { } MDI,怎样创建两个子窗口并显示不同内容? 求助一个关于存储bmp位图的问题。。。。 怎么点击IDC_BUTTON1后,使它的原标题"你好",改为"再见",再点一下换为"你好"啊? windows下一个Client最多能加入多少个组播? 100分,加RMB求解? 关于 创建的窗口顺序问题 给定一个DOUBLE型,如何判断他有几位小数? 紧急~~与WEB无关,却关乎所有中国人!! ADO的简单问题??? vc++初学者,win SDK和win MFC编程的区别? 文件的“占用空间”如何得到? 编写ftp服务器 求助,CStatic不能显示的问题
OVERLAPPED Write_OS, Read_OS, OS;//打开串口
int OpenComm(char *DeviceName)
{
hCom = CreateFile(DeviceName, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL); //创建串口,异步方式
if (hCom == INVALID_HANDLE_VALUE)
return -1; //打开串口失败
else
{
SetCommMask( hCom, EV_RXCHAR|EV_TXEMPTY ); //设置串口事件
SetupComm( hCom, 4096,4096); //设置读写缓冲区大小
PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
memset(&Write_OS,0,sizeof(OVERLAPPED));
memset(&Read_OS,0,sizeof(OVERLAPPED));
memset(&OS,0,sizeof(OVERLAPPED));
COMMTIMEOUTS comTimeOut; //设置超时
comTimeOut.ReadIntervalTimeout = MAXDWORD;
comTimeOut.ReadTotalTimeoutMultiplier = 3000;
comTimeOut.ReadTotalTimeoutConstant = 200;
comTimeOut.WriteTotalTimeoutMultiplier = 300;
comTimeOut.WriteTotalTimeoutConstant = 200;
SetCommTimeouts(hCom,&comTimeOut);
Read_OS.Internal = 0;
Read_OS.InternalHigh = 0;
Read_OS.Offset = 0;
Read_OS.OffsetHigh = 0; //设置结构
Write_OS.Internal = 0;
Write_OS.InternalHigh = 0;
Write_OS.Offset = 0;
Write_OS.OffsetHigh = 0; //设置结构 Read_OS.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
Write_OS.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
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 );
return 0;
}
}例如:
char comm[4]="COM1";
OpenComm(comm);
//关闭串口
void CloseComm()
{
WaitForSingleObject(hReadThread, INFINITE);
CloseHandle(hReadThread);
CloseHandle(hCom);
}//读取数据
int ReadComm()
{
Read_OS = {0};
DWORD dwRes;
BYTE Buffer[255];
DWORD dwDataRead; ResetEvent(Read_OS.hEvent);
if ( NULL == Read_OS.hEvent)
return -1; if (ReadFile(hCom, Buffer, 3, NULL, &Read_OS))
return 0; //成功读出
else
{
dwRes = WaitForSingleObject(Read_OS.hEvent, 5000); //设置5秒超时
switch(dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hCom, &Read_OS, &dwDataRead, TRUE))
{
//操作失败,可用GetLastError()获取失败信息
return 1;
}
else
{
//成功
return 0;
}
break;
case WAIT_TIMEOUT:
//超时
return 2;
break;
default:
break;
}
} CloseHandle(Read_OS.hEvent);
return 0;
}
//写数据
int WriteComm()
{
Write_OS = {0};
DWORD dwRes;
BYTE Buffer[255];
DWORD dwDataRead; ResetEvent(Write_OS.hEvent);
if (NULL == Write_OS.hEvent)
return -1; if(WriteFile(hCom, Buffer, 3, NULL, &Write_OS))
return 0; //成功
else
{
dwRes = WaitForSingleObject(&Write_OS, 5000); //设置5秒超时
switch(dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hCom, &Write_OS, &dwDataRead, TRUE))
{
//操作失败,可用GetLastError()获取失败信息
return 1;
}
else
{
//成功
return 0;
}
break;
case WAIT_TIMEOUT:
//超时
return 2;
break;
default:
break;
}
} CloseHandle(Read_OS.hEvent);
return 0;
}
// 所以不用人为添加DWORD style=WS_VISIBLE;
m_MSComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1);// 串口控件的初始化DWORD style=WS_VISIBLE;
m_MSComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1);
if(m_MSComm.GetPortOpen()) //如果串口是打开的,则行关闭串口
{
m_MSComm.SetPortOpen(FALSE);
}m_MSComm.SetCommPort(1); //选择COM1
m_MSComm.SetInBufferSize(1024); //接收缓冲区
m_MSComm.SetOutBufferSize(1024);//发送缓冲区
m_MSComm.SetInputLen(0);//设置当前接收区数据长度为0,表示全部读取
m_MSComm.SetInputMode(1);//以二进制方式读写数据
m_MSComm.SetRThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件
m_MSComm.SetSettings("9600,n,8,1");//波特率9600无检验位,8个数据位,1个停止位if(!m_MSComm.GetPortOpen())//如果串口没有打开则打开
m_MSComm.SetPortOpen(TRUE);//打开串口
else
m_MSComm.SetOutBufferCount(0);// 控件事件的响应声明
// *.h
//{{AFX_MSG(CGolfView)afx_msg BOOL OnComm();
DECLARE_EVENTSINK_MAP()
//}}AFX_MSG// *.cppBEGIN_EVENTSINK_MAP(CGolfView, CView)
//{{AFX_EVENTSINK_MAP(CAboutDlg)
ON_EVENT(CGolfView, IDC_MSCOMM1, 1 /* OnComm */, OnComm, VTS_NONE)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()// 控件事件的响应
BOOL CGolfView::OnComm()
{
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integerthat is not signed.
CString strtemp;
switch(m_MSComm.GetCommEvent())
{
case 1: // comEvSend发送数据
break;
case 2: // comEvReceive读取数据
// MessageBox(_T("读取数据事件"), _T("TRACE"), MB_OK);
variant_inp=m_MSComm.GetInput(); //读缓冲区
safearray_inp=variant_inp; //VARIANT型变量转换为ColeSafeArray型变量
len=safearray_inp.GetOneDimSize(); //得到有效数据长度
// 接受数据
for(k=0; k<len; k++)
{
safearray_inp.GetElement(&k,rxdata+k); //转换为BYTE型数组
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //将字符送入临时变量strtemp存放
recd+=strtemp;
} // UpdateData(TRUE);
break;
default: // 传输事件出错
m_MSComm.SetOutBufferCount(0);
break;
}
UpdateData(FALSE); //更新图象内容
return TRUE;
}
如果接收文件的话,用户需要选择文件存放路径的话应该怎么写呢?
另外下面的代码请各位帮忙。。
if(buf[0]=='0') //判断如果一帧数据第一字符是'0'的话就接收此文件
{
//程序调到下一句的时候点确定会死掉大侠救命啊
if (AfxMessageBox("要接收文件吗?",NULL,MB_ICONWARNING|MB_OKCANCEL)==IDOK)
{
CFile cf;
//BOOL fWriteState;
DWORD dwBytesRead;
DWORD dwCharToRead;
dwCharToRead=0;
dwCharToRead=(DWORD)cf.GetLength();
cf.Seek(0,CFile::begin);
dwBytesRead=0;
if(m_pSerial->m_hComm!=INVALID_HANDLE_VALUE&&dwCharToRead!=0)
{
char* buf=new char[dwCharToRead];
cf.Read(buf,dwCharToRead);
if(!fReadState)
{
//AfxMessageBox(_T("无法向端口写入数据!"));
}
delete[] buf;
}
cf.Close();
return dwBytesRead;
continue;
// return;
}
}
else
{
}