最近我在用电台对外发送数据以及接收数据的时候,遇到了一个很棘手的问题,最后用示波器才找到了解决问题的办法,在此特写此文章,以避免大家再出现这样的问题而没法解决了,如有不对,还请多多指教.。
其实用无线电台进行发送数据以及接收数据,只是对串口进行读写数据,但是有一点不同的是需要注意RTS(Request to send),一般情况下我们在用电台发送数据的之前的时间把RTS置为Enable,但这个时间不能太长,然后发送完毕的时候再设Disable, 我在写程序的时候 ,就有一个这样的错误。
在没有发送完数据的时候,就把RTS设为 Disable,这样导致数据没有被完整的发送完毕,但RTS置的时间不能太长,不然表示常发数据,时间长了,会把电台烧坏的.写串口用的是大家都很熟悉的CSerialPort ,我在些基础改了一些东西。
下面的一开始的是发送一个字节的数据所需的时间(ms), 首先是算出你发送一个字节的数据实际是多少个位,假设数据长度是8个位,一个起始位,一个终止位,如果有校验位的话,就是11位,算出每个字节所需的时间,这里这个RTS Enable 的时间应该稍比算出来的时间长一点,下面还有一些自己写的方法,以有用电台写数据的代码:
BOOL CSerialPort::InitPort(CWnd *pPortOwner,UINT portnr/* =-1 */,UINT baud/* =19200 */,char parity/* =’N’ */,UINT databits/* =8 */,UINT stopbits/* =1 */,DWORD dwCommEvents/* =EV_RXCHAR|EV_CTS */,UINT nBufferSize/* =512 */) { assert(portnr > 0 && portnr < 5); assert(pPortOwner != NULL);
//Calculate the time that delay time. int nTotalBits =0;
nTotalBits+=databits; nTotalBits+=stopbits; if (parity!=’N’) nTotalBits+=1; //Add a start bit. nTotalBits+=1;
//Use millisecond unit. nTotalBits*=1000; nTotalBits+=baud; m_uElapseTime = nTotalBits/baud;
// if the thread is alive: Kill if (m_bThreadAlive) { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); TRACE("Thread endedn"); }
// create events if (m_ov.hEvent != NULL) ResetEvent(m_ov.hEvent); m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hWriteEvent != NULL) ResetEvent(m_hWriteEvent); m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hShutdownEvent != NULL) ResetEvent(m_hShutdownEvent); m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// initialize the event objects m_hEventArray[0] = m_hShutdownEvent; // highest priority m_hEventArray[1] = m_ov.hEvent; m_hEventArray[2] = m_hWriteEvent;
// initialize critical section InitializeCriticalSection(&m_csCommunicationSyn);
// set buffersize for writing and save the owner m_pOwner = pPortOwner;
if (m_szWriteBuffer != NULL) delete [] m_szWriteBuffer; m_szWriteBuffer = new BYTE[nBufferSize];
m_nPortNr = portnr;
m_nWriteBufferSize = nBufferSize; m_dwCommEvents = dwCommEvents;
BOOL bResult = FALSE; char *szPort = new char[50]; char *szBaud = new char[50];
// now it critical! EnterCriticalSection(&m_csCommunicationSyn);
// if the port is already opened: close it if (m_hComm != NULL) { CloseHandle(m_hComm); m_hComm = NULL; }
// prepare port strings sprintf(szPort, "COM%d", portnr); sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
TRACE("%sn",szBaud);
// get a handle to the port m_hComm = CreateFile(szPort, // communication port string (COMX) GENERIC_READ | GENERIC_WRITE, // read/write types 0, // comm devices must be opened with exclusive access NULL, // no security attributes OPEN_EXISTING, // comm devices must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // Async I/O 0); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE) { // port not found delete [] szPort; delete [] szBaud;
return FALSE; }
// set the timeout values m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; m_CommTimeouts.ReadTotalTimeoutConstant = 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
// configure if (SetCommTimeouts(m_hComm, &m_CommTimeouts)) { if (SetCommMask(m_hComm, dwCommEvents)) { if (GetCommState(m_hComm, &m_dcb)) { m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high! if (BuildCommDCB(szBaud, &m_dcb)) { if (SetCommState(m_hComm, &m_dcb)) ; // normal operation... continue else ProcessErrorMessage("SetCommState()"); } else ProcessErrorMessage("BuildCommDCB()"); } else { ProcessErrorMessage("GetCommState()"); } } else ProcessErrorMessage("SetCommMask()"); } else ProcessErrorMessage("SetCommTimeouts()");
delete [] szPort; delete [] szBaud;
// flush the port PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // release critical section LeaveCriticalSection(&m_csCommunicationSyn); TRACE("Initialisation for communicationport %d completed.nUse Startmonitor to communicate.n", portnr);
return TRUE; }
void CSerialPort ::SetRTSEnable() { if (m_hComm == NULL) return;
GetCommState(m_hComm,&m_dcb); if (m_dcb.fRtsControl ==RTS_CONTROL_ENABLE) return; else { //Set the RTS enable. m_dcb.fRtsControl =RTS_CONTROL_ENABLE; SetCommState(m_hComm,&m_dcb); } }
void CSerialPort ::SetRTSDisable() { if (m_hComm == NULL) return; GetCommState(m_hComm,&m_dcb); if (m_dcb.fRtsControl ==RTS_CONTROL_DISABLE) return; else { //Set the RTS enable. m_dcb.fRtsControl =RTS_CONTROL_DISABLE; SetCommState(m_hComm,&m_dcb); } }
//Get the RTS state .If I send data need a few time. BOOL CSerialPort ::GetRTSState() { if (m_hComm == NULL) return FALSE;
DCB dcb; GetCommState(m_hComm,&dcb);
if (dcb.fRtsControl == RTS_CONTROL_ENABLE) return TRUE; else if (dcb.fRtsControl == RTS_CONTROL_DISABLE) return FALSE; else return FALSE; }
//Return the Elpase time that by the wireless. UINT CSerialPort::GetSleepTime() { return m_uElapseTime; }
//How to send data use wireless main station.
pFrame->m_pWireLessPort[j].SetRTSEnable(); Sleep(dwSleepTime); pFrame->m_pWireLessPort[j].WriteToPort(pti->pData,pti->nDataLen);
//At 2005/1/20’s afternoon .When I send data by the wireless. //At first ,I send data to the terminal ,the terminal receive //data,but the terminal don’t back me any data.I don’t know how to // deal with this problem.Finally ,the terminal designner Mr.Liu //use the oscillograph ,then found Because the RTS enable time is too short. //so that I don’t finish send data compeletly .So the the data that the terminal has //received is not a integrated data.Although the terminal receive data //but it is not a valid data .After I send data .then I need a few time to sleep. //Get the baund of the COM.
DWORD dwSleepTime = pti->nDataLen*pFrame->m_pWireLessPort[j].GetSleepTime()+10; Sleep(dwSleepTime); pFrame->m_pWireLessPort[j].SetRTSDisable(); |
|