项目做到最后了,上位机(普通台式计算机)需要接收下位机(实验板)处理过后的数据,由于返回的数据较少,一次可能就是几个字节,传输时间没有严格要求,所以选择了串口通信。串口通信方式简单。调试起来也比较简单。下位机的串口硬件调试是PK同学负责的,我负责上位机的串口程序的调试。
刚开始的调试想法是让计算机COM1口发送数据,然后COM2接收,后来发现计算机就只带有一个串口,那就用邻近同学的计算机发送数据吧,但是这样是无法通信的,因为我的串口线是对等的。后来根据小丫头同学调试串口的经验,让一个串口COM1自发自收,这样就不用考虑对等线还是交叉线的问题了。
调试计算机串口,需要一根串口线,对等线或者交叉线均可。
1、检测串口线是否能连通;检测方法,用万用表检测串口线的1-9号线是否对应连通。
2、检测计算机串口是否能正常工作;检测方法,将串口线一端接入计算机串口,另一端2、3两线用导线连通。下载串口调试助手观察计算机串口的自发自收情况。
3、检测自己程序的正确性;
以下串口类在原始是应用于WINCE下,我稍作修改即可在windows下运行。以下程序在VC2005下编译、测试通过。PSerialPort.cpp增加了TRACE调试的代码。
//From unkown author:unkonwn modified by IndexZ@xinzero.com //PSerialPort.h #pragma once typedef void (*LPDataArriveProc)(char *data,int length,DWORD userdata); class CPSerialPort { public: CPSerialPort(); virtual ~CPSerialPort(); BOOL OpenPort(LPCTSTR Port,int Baudrate, /*int DataBits,int StopBits,int Parity,*/ LPDataArriveProc proc=NULL,DWORD userdata=0); //打开串口 BOOL ClosePort(); //关闭串口 //激活与关闭持续接收 BOOL Activate(); BOOL Deactivate(); BOOL IsActive(); //接收数据线程函数 static DWORD WINAPI ReadPortThread(LPVOID lpParameter); DWORD ReadPort(char *data,int length); //读取一定长度的数据 DWORD WritePort(char *data,int length); //发送数据 DWORD WriteFileToPort(LPCTSTR FileName); //发送文件 private: HANDLE m_hComm; //串口设备handle HANDLE m_hReadThread; //读串口线程handle BOOL m_bReceiving; //是否持续接收 int m_nBufferSize; //缓冲大小 char *Buffer; //缓冲区 LPDataArriveProc m_lpDataArriveProc; DWORD m_dwUserData; //串口设置以及超时参数 DCB dcb; COMMTIMEOUTS CommTimeOuts; };
//From unkown author:unkonwn modified by IndexZ@xinzero.com //PSerialPort.cpp #include "StdAfx.h" #include "PSerialPort.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CPSerialPort::CPSerialPort() { m_hComm = INVALID_HANDLE_VALUE; m_hReadThread = NULL; m_bReceiving = FALSE; m_nBufferSize = 256; //缓冲大小 } CPSerialPort::~CPSerialPort() { ClosePort(); } DWORD WINAPI CPSerialPort::ReadPortThread(LPVOID lpParameter) { CPSerialPort* m_pSerial; m_pSerial=(CPSerialPort*)lpParameter; BOOL fReadState; DWORD dwLength; char* buf=new char[m_pSerial->m_nBufferSize]; while((m_pSerial->m_hComm!=INVALID_HANDLE_VALUE) &&(m_pSerial->m_bReceiving)) { fReadState=ReadFile(m_pSerial->m_hComm, buf,m_pSerial->m_nBufferSize,&dwLength,NULL); if(!fReadState) { AfxMessageBox(_T("无法从串口读取数据!")); } else { if(dwLength!=0) { //调试输出代码开始 TRACE("%d\n",dwLength); int *pint = (int*)buf; for(int i=0;i<(dwLength/(sizeof(int)));i++) { TRACE("%d\n",pint[i]); }//调试输出代码结束 //回送数据 if(m_pSerial->m_lpDataArriveProc!=NULL) { m_pSerial->m_lpDataArriveProc(buf, dwLength,m_pSerial->m_dwUserData); } } } Sleep(100); //休眠cpu } delete[] buf; return 0; } BOOL CPSerialPort::OpenPort(LPCTSTR Port,int BaudRate, /*int DataBits,int StopBits,int Parity,*/ LPDataArriveProc proc,DWORD userdata) { m_lpDataArriveProc = proc; m_dwUserData = userdata; if(m_hComm==INVALID_HANDLE_VALUE) { m_hComm=CreateFile(Port,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0); if(m_hComm==INVALID_HANDLE_VALUE ) { AfxMessageBox(_T("无法打开端口!请检查是否已被占用。")); return FALSE; } GetCommState(m_hComm,&dcb); dcb.BaudRate=BaudRate; //dcb.ByteSize=DataBits; //dcb.Parity=Parity; //dcb.StopBits=StopBits; dcb.fParity=FALSE; dcb.fBinary=TRUE; dcb.fDtrControl=0; dcb.fRtsControl=0; dcb.fOutX=dcb.fInX=dcb.fTXContinueOnXoff=0; //设置状态参数 SetCommMask(m_hComm,EV_RXCHAR); SetupComm(m_hComm,16384,16384); if(!SetCommState(m_hComm,&dcb)) { AfxMessageBox(_T("无法按当前参数配置端口,请检查参数!")); PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); ClosePort(); return FALSE; } //设置超时参数 GetCommTimeouts(m_hComm,&CommTimeOuts); CommTimeOuts.ReadIntervalTimeout=100; CommTimeOuts.ReadTotalTimeoutMultiplier=1; CommTimeOuts.ReadTotalTimeoutConstant=100; CommTimeOuts.WriteTotalTimeoutMultiplier=0; CommTimeOuts.WriteTotalTimeoutConstant=0; if(!SetCommTimeouts(m_hComm,&CommTimeOuts)) { AfxMessageBox(_T("无法设置超时参数!")); PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); ClosePort(); return FALSE; } PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); return TRUE; } return FALSE; } BOOL CPSerialPort::ClosePort() { Deactivate(); if(m_hComm!=INVALID_HANDLE_VALUE) { SetCommMask(m_hComm,0); PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); CloseHandle(m_hComm); m_hComm=INVALID_HANDLE_VALUE; return TRUE; } return TRUE; } BOOL CPSerialPort::Activate() { if(m_hComm==INVALID_HANDLE_VALUE) { return FALSE; } if(!m_bReceiving) { //开始接收线程 PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); m_bReceiving=TRUE; m_hReadThread=CreateThread(NULL,0,ReadPortThread,this,0,NULL); } if(m_hReadThread!=NULL) { return TRUE; } else { m_bReceiving=FALSE; return FALSE; } return FALSE; } BOOL CPSerialPort::Deactivate() { if(m_hComm==INVALID_HANDLE_VALUE) { return FALSE; } //停止接收线程 if(m_bReceiving) { m_bReceiving=FALSE; WaitForSingleObject(m_hReadThread,500); CloseHandle(m_hReadThread); m_hReadThread=NULL; return TRUE; } return FALSE; } BOOL CPSerialPort::IsActive() { return m_bReceiving; } DWORD CPSerialPort::WritePort(char *data,int length) { if(m_hComm == INVALID_HANDLE_VALUE) { return 0; } BOOL bFileWriteState; DWORD dwBytesWritten=0; bFileWriteState = WriteFile(m_hComm,data, length*sizeof(char),&dwBytesWritten,NULL); // AfxMessageBox(L"正在写串口数据。。。"); return dwBytesWritten; } DWORD CPSerialPort::ReadPort(char *data,int length) { BOOL bFileReadState; DWORD dwLength,dwByteRead; int TimeOutCount; dwByteRead=0; TimeOutCount=0; // AfxMessageBox(L"正在读串口数据。。。"); while(m_hComm!=INVALID_HANDLE_VALUE) { char* buf=new char[length]; bFileReadState = ReadFile(m_hComm,data,length,&dwLength,NULL); if(!bFileReadState) { break; } else { dwByteRead+=dwLength; data+=dwLength; } if(dwByteRead == (unsigned long)length) { break; } if(dwLength!=0) { TimeOutCount=0; } else { TimeOutCount++; Sleep(5); } if(TimeOutCount==5) { break; } } return dwByteRead; } DWORD CPSerialPort::WriteFileToPort(LPCTSTR FileName) { CFile cf; BOOL fWriteState,isOpen; DWORD dwBytesWritten; DWORD dwCharToWrite; dwCharToWrite=0; if(m_hComm==INVALID_HANDLE_VALUE) { return 0; } isOpen = cf.Open(FileName,CFile::modeRead); if(!isOpen) { //AfxMessageBox(_T("无法打开Hex文件!")); return 0; } dwCharToWrite=(DWORD)cf.GetLength(); cf.Seek(0,CFile::begin); dwBytesWritten=0; if(m_hComm!=INVALID_HANDLE_VALUE&&dwCharToWrite!=0) { char* buf=new char[dwCharToWrite]; cf.Read(buf,dwCharToWrite); fWriteState=WriteFile(m_hComm,buf,dwCharToWrite*sizeof(char), &dwBytesWritten,NULL); if(!fWriteState) { //AfxMessageBox(_T("无法向端口写入数据!")); } delete[] buf; } cf.Close(); return dwBytesWritten; }