调试串口通信程序

2008-05-27 20:05 阅读 797 次 评论 2 条

项目做到最后了,上位机(普通台式计算机)需要接收下位机(实验板)处理过后的数据,由于返回的数据较少,一次可能就是几个字节,传输时间没有严格要求,所以选择了串口通信。串口通信方式简单。调试起来也比较简单。下位机的串口硬件调试是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; 
}
版权声明:本文著作权归原作者所有,欢迎分享本文,谢谢支持!
转载请注明:调试串口通信程序 | 起点博客

发表评论


表情