VC++ 關於串口操作的配置參數的設定

來源:互聯網
上載者:User

基本環境:

編程環境:VS2008 多位元組編碼

串口環境:手機AT命令 進行手機與pc通訊
串口類是網上 下載的一個 CSerialPort類, 很多有關串口編程都有其原始碼

相關代碼:

//清除接受緩衝區<br />void ClearInputBuffer()<br />{<br />if(IsOpen())<br />::PurgeComm(m_hComm, PURGE_RXABORT | PURGE_RXCLEAR );<br />}<br />//清除發送緩衝區<br />void ClearOutputBuffer()<br />{<br />if(IsOpen())<br />::PurgeComm(m_hComm, PURGE_TXABORT | PURGE_TXCLEAR );<br />}

 

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

 

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

 

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

 

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

 

問題描述:
用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,這個錯誤消失了

 

這個問題就解決了。

 

不知道我這個分析的是否是正確的。。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.