功能實現背景介紹
本項目中,需要使用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庫的中斷接收函數,也就是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);
}
}
}
}
核心思想就是先接收報文的頭,根據頭來判斷后面的長度,把應答報文和音量數據報文區分開,不合格的報文直接舍去同時開啟新的接收。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
FPGA
+關注
關注
1641文章
21912瀏覽量
611716 -
STM32
+關注
關注
2283文章
10986瀏覽量
361139 -
下位機
+關注
關注
0文章
94瀏覽量
19018 -
串口中斷
+關注
關注
0文章
67瀏覽量
14182 -
USART串口
+關注
關注
0文章
32瀏覽量
6994
發布評論請先 登錄
相關推薦
STM32之串口DMA接收不定長數據
使用stm32或者其他單片機的時候,會經常使用到串口通訊,那么如何有效地接收數據呢?假如這段數據是不定長的有如何高效接收呢?同學A:數據來了
發表于 12-24 19:03
?30次下載

評論