VC++ 关于串口操作的配置参数的设置

基本环境:

编程环境:VS2008 多字节编码

串口环境:手机AT命令 进行手机与pc通信 串口类是网上 下载的一个 CSerialPort类, 很多有关串口编程都有其源代码

相关代码:

//清除接受缓冲区 void ClearInputBuffer() { if(IsOpen()) ::PurgeComm(m_hComm, PURGE_RXABORT | PURGE_RXCLEAR ); } //清除发送缓冲区 void ClearOutputBuffer() { if(IsOpen()) ::PurgeComm(m_hComm, PURGE_TXABORT | PURGE_TXCLEAR ); }

 

void CSerialPort::SetTimeouts(COMMTIMEOUTS& timeouts) { ASSERT(IsOpen()); if (!SetCommTimeouts(m_hComm, &timeouts)) { TRACE(_T("Failed in call to SetCommTimeouts/n")); AfxThrowSerialException(); } } void CSerialPort::GetTimeouts(COMMTIMEOUTS& timeouts) { ASSERT(IsOpen()); if (!GetCommTimeouts(m_hComm, &timeouts)) { TRACE(_T("Failed in call to GetCommTimeouts/n")); AfxThrowSerialException(); } }

 

void CSerialPort::GetState(DCB& dcb) { ASSERT(IsOpen()); if (!GetCommState(m_hComm, &dcb)) { DWORD dwErr = GetLastError(); TRACE(_T("Failed in call to GetCommState/n")); AfxThrowSerialException(); } } void CSerialPort::SetState(DCB& dcb) { ASSERT(IsOpen()); if (!SetCommState(m_hComm, &dcb)) { DWORD dwErr = GetLastError(); TRACE(_T("Failed in call to SetCommState/n")); AfxThrowSerialException(); } }

 

BOOL Open(int nPort, DWORD dwBaud = 9600, Parity parity = NoParity, BYTE DataBits = 8, StopBits stopbits = OneStopBit, FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE) { //Validate our parameters ASSERT(nPort>0 && nPort<=255); //Call CreateFile to open up the comms port CString sPort; sPort.Format(_T("////.//COM%d"), nPort); m_hComm = CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, bOverlapped ? FILE_FLAG_OVERLAPPED : 0, NULL); if (m_hComm == INVALID_HANDLE_VALUE) { TRACE(_T("Failed to open up the comms port/n")); return FALSE; } m_bOverlapped = bOverlapped; //Get the current state prior to changing it DCB dcb = {sizeof(DCB)}; GetState(dcb); //Setup the baud rate dcb.BaudRate = dwBaud; //Setup the Parity switch (parity) { case EvenParity: dcb.Parity = EVENPARITY; break; case MarkParity: dcb.Parity = MARKPARITY; break; case NoParity: dcb.Parity = NOPARITY; break; case OddParity: dcb.Parity = ODDPARITY; break; case SpaceParity: dcb.Parity = SPACEPARITY; break; default: ASSERT(FALSE); break; } //Setup the data bits dcb.ByteSize = DataBits; //Setup the stop bits switch (stopbits) { case OneStopBit: dcb.StopBits = ONESTOPBIT; break; case OnePointFiveStopBits: dcb.StopBits = ONE5STOPBITS; break; case TwoStopBits: dcb.StopBits = TWOSTOPBITS; break; default: ASSERT(FALSE); break; } //Setup the flow control dcb.fDsrSensitivity = FALSE; switch (fc) { case NoFlowControl: { dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fOutX = FALSE; dcb.fInX = FALSE; break; } case CtsRtsFlowControl: { dcb.fOutxCtsFlow = TRUE; dcb.fOutxDsrFlow = FALSE; dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; dcb.fOutX = FALSE; dcb.fInX = FALSE; break; } case CtsDtrFlowControl: { dcb.fOutxCtsFlow = TRUE; dcb.fOutxDsrFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; dcb.fOutX = FALSE; dcb.fInX = FALSE; break; } case DsrRtsFlowControl: { dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = TRUE; dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; dcb.fOutX = FALSE; dcb.fInX = FALSE; break; } case DsrDtrFlowControl: { dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = TRUE; dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; dcb.fOutX = FALSE; dcb.fInX = FALSE; break; } case XonXoffFlowControl: { dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fOutX = TRUE; dcb.fInX = TRUE; dcb.XonChar = 0x11; dcb.XoffChar = 0x13; dcb.XoffLim = 100; dcb.XonLim = 100; break; } default: { ASSERT(FALSE); break; } } //标记2 //Now that we have all the settings in place, make the changes SetState(dcb); this->ClearInputBuffer(); this->ClearOutputBuffer(); DWORD dwErr; COMSTAT comstat; ClearCommError(this->m_hComm, &dwErr, &comstat); COMMTIMEOUTS time; this->GetTimeouts(time); //标记3 this->SetTimeouts(time); return TRUE; }

 

//测试函数 BOOL CSerialPort::SupportATCommand() { this->ClearInputBuffer(); this->ClearOutputBuffer(); CString command = _T("AT/r"); this->Write(command); CString result; result.Empty(); result = this->ReadExisting(); return result.Find(_T("OK")) >= 0; }

 

问题描述: 用CSerialPort类进行串口通讯,出现这样一个问题:

步骤1:当我打开(或重启)电脑并正确连接手机,

步骤2:运行自己的VC程序,正确打开串口,调用测试函数,

现象1:程序运行在标记4位置处就运行不下去,永远的停在这里。

步骤3:当我用.NET 自带的类(SerialPort类)进行初始化的并且用.NET中的类进行串口通讯

现象2:正常的读写操作,可以发送命令,接收数据

重新执行步骤2, 出现现象2,现象1不出现,

多次执行步骤2,依然是出现现象2而不出现现象1.

执行步骤1,步骤2,出现现象1..........

这个奇怪的问题, 我发了个帖子询问了下:

帖子链接地址:http://topic.csdn.net/u/20101109/22/bf1a0519-358e-4932-9321-8763071e56b4.html

 

根据网友的回答,我认为这个可能性很高导致出现这个问题:

原因大致是串口配置不正确,串口打开后工作于最近起作用的配置,所以能正常工作。

 

因此我开始进行对串口配置参数进行跟踪

首先是DCB 的参数:

如果执行步骤1,步骤2 在标记2处设下断点后,dcb的数据只有 波特率等参数

如果执行步骤3后,重新执行步骤2, dcb的数据多出以下的内容:

内容1:

dcb.fDtrControl = 1;

dcb.fErrorChar = 1;

dcb.fRtsControl = 1;

dcb.XonLim = 4096;

dcb.XoffLim = 4096;

dcb.XonChar = 0x11;

dcb.XoffChar = 0x13;

dcb.ErrorChar = 0x3F;

dcb.EofChar = 0x1A;

dcb.EvtChar = 0x1A;

 

因此可以设想,执行步骤1和步骤2,出现现象1肯定是这里的参数忘记设置了 因此我把内容1的代码添加到标记2位置处,

重新执行步骤1,步骤2, 依然出现错误

 

继续考虑串口配置问题:

那现在就只剩下 time 这个参数了 同刚才找出dcb 参数之间差别一样的办法:

默认的是:

time.ReadIntervalTimeout = 0;

time.ReadTotalTimeoutMultiplier = 0;

time.ReadTotalTimeoutConstant = 0;

time.WriteTotalTimeoutMultiplier = 0;

time.WriteTotalTimeoutConstant = 0;

 

而正确的是:

内容2:

time.ReadIntervalTimeout = 4294967295;

time.ReadTotalTimeoutMultiplier = 4294967295;

time.ReadTotalTimeoutConstant = 100;//.net中设置 读取超时时间(串口打开后工作于最近起作用的配置)

time.WriteTotalTimeoutMultiplier = 0; time.WriteTotalTimeoutConstant = 2000;//.net中设置 写入超时时间 把内容2的代码添加到标记3位置处, 重新执行步骤1,步骤2,这个错误消失了

 

这个问题就解决了。

 

不知道我这个分析的是否是正确的。。

你可能感兴趣的:(工作,.net,command,手机,vc++,通讯)