科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件VC下用串口与电台通信需注意的问题

VC下用串口与电台通信需注意的问题

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

最近我在用电台对外发送数据以及接收数据的时候,遇到了一个很棘手的问题,最后用示波器才找到了解决问题的办法

作者:cc_011 来源:VCCode 2007年10月19日

关键字: VC 串口 电台通信

  • 评论
  • 分享微博
  • 分享邮件
最近我在用电台对外发送数据以及接收数据的时候,遇到了一个很棘手的问题,最后用示波器才找到了解决问题的办法,在此特写此文章,以避免大家再出现这样的问题而没法解决了,如有不对,还请多多指教.。

  其实用无线电台进行发送数据以及接收数据,只是对串口进行读写数据,但是有一点不同的是需要注意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();

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章