下载本文示例代码
最近我在用电台对外发送数据以及接收数据的时候,遇到了一个很棘手的问题,最后用示波器才找到了解决问题的办法,在此特写此文章,以避免大家再出现这样的问题而没法解决了,如有不对,还请多多指教.。 其实用无线电台进行发送数据以及接收数据,只是对串口进行读写数据,但是有一点不同的是需要注意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();
最近我在用电台对外发送数据以及接收数据的时候,遇到了一个很棘手的问题,最后用示波器才找到了解决问题的办法,在此特写此文章,以避免大家再出现这样的问题而没法解决了,如有不对,还请多多指教.。 其实用无线电台进行发送数据以及接收数据,只是对串口进行读写数据,但是有一点不同的是需要注意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();
下载本文示例代码
VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题VC下用串口与电台通信需注意的问题
阅读(243) | 评论(0) | 转发(0) |