电子说
本项目中,需要使用STM32的USART6串口与FPGA板(下位机)通信,需要发送和接收数据,有报文应答机制。
使用的报文规则如表格所示
板间报文的通信协议,校验使用的是和校验
U8 TX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
{
U8 i, ret = 0;
for(i=0; i< len; i++)
{
ret += *(buf++);
}
ret = ~ret;
return ret;
}
U8 RX_CheckSum(U8 *buf, U8 len) //buf为数组,len为数组长度
{
U8 i, ret = 0;
for(i=0; i< len; i++)
{
ret += *(buf++);
}
ret = ret;
return ret+1;
}
发送和接收的报文要满足不定长
如果要直接使用HAL库的中断接收函数,也就是HAL_UART_Receive_IT()函数
HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5); //下位机FPGA
在使用时,选择串口,选择接收的缓冲区,选择接收长度。
/**
* @brief Receives an amount of data in non blocking mode.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the received data is handled as a set of u16. In this case, Size must indicate the number
* of u16 available through pData.
* @param huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @param pData Pointer to data buffer (u8 or u16 data elements).
* @param Size Amount of data elements (u8 or u16) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/* Check that a Rx process is not already ongoing */
if (huart- >RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart- >pRxBuffPtr = pData;
huart- >RxXferSize = Size;
huart- >RxXferCount = Size;
huart- >ErrorCode = HAL_UART_ERROR_NONE;
huart- >RxState = HAL_UART_STATE_BUSY_RX;
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Parity Error Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
/* Enable the UART Data Register not empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
这个函数本质上其实不是中断接收函数,只是配置函数,配置开启中断的信息,并且接收多少定长的数据结束本数据接收,串口的中断接收还是在中断中进行。
我们本次的长度虽然也是定长,但是有两种长度数据的接收,所以还是从设计接收不定长的数据为最终效果。
对于不定长数据的接收,使用了状态机,分两次中断来接收数据
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart- >Instance == USART6) // 判断是由哪个串口触发的中断
{
if(StateMachine_USART6) //状态机为1,都接收完毕,准备校验
{
if(re_flag6 == 1)
{
UART6_RxCounter = 6;
re_flag6 = 0;
}
else
{
len_counter6 = 2+5+UART6_RxBuffer[2]+(UART6_RxBuffer[3]< < 8);
if(UART6_RxBuffer[len_counter6 - 1] == 0x55 && UART6_RxBuffer[0] == 0xAA)
{
UART6_RxCounter = len_counter6;
}
else
{
memset(UART6_RxBuffer,0,0x400);
UART6_RxCounter = 0;
}
}
StateMachine_USART6 = 0; //状态机为0
len_counter6 = 0;
HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
}
else //状态机为0,只接受到了前五个字节,继续接收后面的字节
{
if(UART6_RxBuffer[0] == 0xAA)
{
StateMachine_USART6 = 1;
UART6_RxCounter = 5;
if(UART6_RxBuffer[2] == 0 && UART6_RxBuffer[3] == 0)
{
HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 1);
re_flag6 = 1;
}
else
HAL_UART_Receive_IT(&huart6,(uint8_t*)&UART6_RxBuffer[5], 2 + UART6_RxBuffer[2] + (UART6_RxBuffer[3] < < 8));
}
else
{
memset(UART6_RxBuffer,0,0x400);
UART6_RxCounter = 0;
HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
}
}
}
}
核心思想就是先接收报文的头,根据头来判断后面的长度,把应答报文和音量数据报文区分开,不合格的报文直接舍去同时开启新的接收。
全部0条评论
快来发表一下你的评论吧 !