您的位置:首页 > 编程语言 > C语言/C++

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

2010-11-18 11:45 337 查看
基本环境:

编程环境: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,这个错误消失了

这个问题就解决了。

不知道我这个分析的是否是正确的。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: