📄 uart.cpp
字号:
/*===========================================================================
FUNCTION rcv_packet
DESCRIPTION
This function receives a complete packet.
It takes care of the async-HDLC state
machine, enforces a minimum packet length of 1 byte plus CRC, and
checks the CRC on the fly.
DEPENDENCIES
Uses the crc table.
RETURN VALUE
Once a good packet is received, returns its length including
but not including flags or byte stuffing escapes.
SIDE EFFECTS
If a NAK-able packet error is detected, this function generates a
suitable NAK response and does not return until a good packet is
received.
The watchdog is reset.
===========================================================================*/
int
CUART::RcvPacket (BYTE *buf, BOOL bCheckHeadFlag, BYTE cWait)
{
enum e_state
{
HDLC_HUNT_FOR_FLAG, /* Waiting for a flag to start a packet */
HDLC_GOT_FLAG, /* Have a flag, expecting the packet to start */
HDLC_GATHER, /* In the middle of a packet */
HDLC_PACKET_RCVD /* Now have received a complete packet */
};
/* State variable for decoding async HDLC */
enum e_state state, eStartState;
int chr;
/* Current character being received */
WORD len=0;
/* Length of packet collected so far */
WORD crc=0;
/* Cyclic Redundancy Check, computed as we go. */
/*lint -esym(644,len,crc) */
/* Lint can't tell that the state machine guarantees that
we initialize len and crc before use */
DWORD dwErr;
ClearCommError(m_hCom, &dwErr, &m_cs);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
if(bCheckHeadFlag)
eStartState = HDLC_HUNT_FOR_FLAG;
else
eStartState = HDLC_GOT_FLAG;
/* Look at characters and try to find a valid async-HDLC packet of
** length at least MIN_PACKET_LEN with a valid CRC.
** Keep looking until we find one. */
for (state = eStartState; state != HDLC_PACKET_RCVD; /* nil */)
{
chr = get_next_char(cWait); /* Get next character (wait for it) */
if (chr == UART_RX_ERR && m_bErrByte) /* If it's an error ... */
{
m_bErrByte = FALSE;
state = HDLC_HUNT_FOR_FLAG; /* Start over. */
continue;
}
if ( chr == UART_RX_OVERTIME )
{
return 0;
}
if( state == eStartState && chr == 0)
continue;
switch(state) /* Process according to which state */
{
/*lint -esym(788,HDLC_PACKET_RCVD) No need to deal with HDLC_PACKET_RCVD
since we're in a loop that guarantees we're not in that state. */
case HDLC_HUNT_FOR_FLAG: /* We're looking for a flag ... */
if (chr == ASYNC_HDLC_FLAG) /* and we got one ... */
{
state = HDLC_GOT_FLAG; /* so go on to the next step. */
}
break;
case HDLC_GOT_FLAG: /* Had a flag, now expect a packet */
if (chr == ASYNC_HDLC_FLAG) /* Oops, another flag. No change. */
{
break;
}
else
{ /* Ah, we can really begin a packet */
len = 0; /* The packet starts out empty */
crc = CRC_16_L_SEED; /* and the CRC in its initial state */
state = HDLC_GATHER; /* and we begin to gather a packet */
/* Fall through */ /* (starting with this byte) */
}
case HDLC_GATHER: /* We're gathering a packet */
if (chr == ASYNC_HDLC_FLAG) /* We've reached the end */
{
if (len < MIN_PACKET_LEN) /* Reject any too-short packets */
{
state = HDLC_HUNT_FOR_FLAG; /* Start over */
}
else if (crc != CRC_16_L_OK_NEG) /* Reject any with bad CRC */
{
state = HDLC_HUNT_FOR_FLAG; /* Start over */
}
else /* Yay, it's a good packet! */
{
state = HDLC_PACKET_RCVD; /* Done for now */
init_boot = FALSE;
}
break; /* However it turned out, this packet is over. */
}
/* It wasn't a flag, so we're still inside the packet. */
if (chr == ASYNC_HDLC_ESC) /* If it was an ESC */
{
chr = get_next_char(cWait); /* Get next character (wait for it) */
if (chr == UART_RX_ERR) /* If there was an error, */
{
state = HDLC_HUNT_FOR_FLAG; /* Start over */
break;
}
chr ^= ASYNC_HDLC_ESC_MASK; /* Otherwise, de-mask it */
/* No break; process the de-masked byte normally */
}
if (len >= MAX_PACKET_LEN) /* Make sure there's room */
{
state = HDLC_HUNT_FOR_FLAG; /* Start over */
}
else
{
buf[len++] = (BYTE) chr; /* Add byte to buffer */
crc = CRC_16_L_STEP(crc, (WORD) chr); /* Update the CRC */
}
break;
default: /* Shouldn't happen with an enum, but for safety ... */
state = HDLC_HUNT_FOR_FLAG; /* Start over */
break;
}/* switch on state */
}/* for (packet not found) */
return len;
} /* rcv_packet() */
//--------------------------------------------------------------------------------------------------
// FUNCTION:
// CUART::TransmitPacket
// DESCRIPTION:
// This function transmits a packet data.
// ARGUMENTS PASSED:
// pBuf the buffer stored the transmitting data.
// RETURN VALUE:
// None
// PRE-CONDITIONS:
// The CUART::InitComm function must be called.
// POST-CONDITIONS:
// None
// IMPORTANT NOTES:
// None
//--------------------------------------------------------------------------------------------------
void
CUART::TransmitPacket(BYTE *pBuf)
{
const BYTE *data;
data = (BYTE*)(((pkt_buffer_type*)pBuf)->buf);
theComm.TransmitByte(ASYNC_HDLC_FLAG); //Supply the leading flag
do
{
theComm.TransmitByte(*data); // Transmit bytes from the buffer
}
while (*data++ != ASYNC_HDLC_FLAG); // Until we've transmitted a flag
}
BOOL
CUART::SetBaudRateTo38400()
{
COMMCONFIG CC;
GetCommState(m_hCom, &(CC.dcb));
CC.dcb.BaudRate = 38400;
if(!SetCommState(m_hCom, &CC.dcb))
return false;
return true;
}
BOOL
CUART::SetBaudRateTo115200()
{
COMMCONFIG CC;
GetCommState(m_hCom, &(CC.dcb));
CC.dcb.BaudRate = 115200;
if(!SetCommState(m_hCom, &CC.dcb))
return false;
return true;
}
BOOL
CUART::SetBaudRate(enum baud_rate_type bt)
{
COMMCONFIG CC;
GetCommState(m_hCom, &(CC.dcb));
switch(bt)
{
case 0:
CC.dcb.BaudRate = 57600;
break;
case 1:
CC.dcb.BaudRate = 115200;
break;
case 2:
CC.dcb.BaudRate = 230400;
break;
case 4:
CC.dcb.BaudRate = 460800;
break;
default:
CC.dcb.BaudRate = 115200;
break;
}
if(!SetCommState(m_hCom, &CC.dcb))
return false;
return true;
}
BYTE
CUART::GetCurrentPort()
{
return m_cPort;
}
BOOL
CUART::SetCurrentPort(BYTE cPort)
{
if(m_hCom == INVALID_HANDLE_VALUE)
return false;
CloseComm();
return InitComm(cPort);
}
//--------------------------------------------------------------------------------------------------
//Internal Member Fucntions
//--------------------------------------------------------------------------------------------------
int
CUART::ReceiveByte(BYTE cWait)
{
if(m_hCom == INVALID_HANDLE_VALUE)
{
TRACE0("com init Err!");
return UART_RX_ERR;
}
DWORD dwErr = 0;
DWORD dwBytesRead = 0;
time_t t1, t2;
time(&t1);
do{
time(&t2);
ClearCommError(m_hCom, &dwErr, &m_cs);
}while( (m_cs.cbInQue == 0) && (t2 < (t1 + cWait)) );
if(m_cs.cbInQue == 0)
return UART_RX_OVERTIME;
if(!ReadFile(m_hCom, m_rbuf, 1, &dwBytesRead, NULL))
{
dwErr = GetLastError();
switch(dwErr)
{
case ERROR_IO_PENDING:
TRACE("\n\nRead IO_PENDING Err!");
break;
default:
TRACE("\n\nErrCode:%d\n",dwErr);
break;
}
ClearCommError(m_hCom, &dwErr, &m_cs);
m_bErrByte = TRUE;
return UART_RX_ERR;
}
else
{
static int cout = 1;
BYTE tmp = m_rbuf[0];
TRACE("\ncou: %d Bytes:%X \n", cout++, tmp);
return m_rbuf[0];
}
}
void
CUART::TransmitByte(BYTE cByte)
{
if(m_hCom == INVALID_HANDLE_VALUE)
{
TRACE0("com init Err!");
return;
}
m_sbuf[0] = cByte;
DWORD dwBytesWrite = 0;
DWORD dwErr;
if(!WriteFile(m_hCom, (LPCVOID)m_sbuf, 1, &dwBytesWrite, NULL))
{
dwErr = GetLastError();
switch(dwErr)
{
case ERROR_IO_PENDING:
TRACE("\n\nWrite IO_PENDING Err!\n");
break;
default:
TRACE("\n\nErrCode:%d\n",dwErr);
break;
}
ClearCommError(m_hCom, &dwErr, &m_cs);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -