功能實現(xiàn)背景介紹
本項目中,需要使用STM32的USART6串口與FPGA板(下位機(jī))通信,需要發(fā)送和接收數(shù)據(jù),有報文應(yīng)答機(jī)制。
使用的報文規(guī)則如表格所示
板間報文的通信協(xié)議,校驗使用的是和校驗
U8 TX_CheckSum(U8 *buf, U8 len) //buf為數(shù)組,len為數(shù)組長度
{
U8 i, ret = 0;
for(i=0; i< len; i++)
{
ret += *(buf++);
}
ret = ~ret;
return ret;
}
U8 RX_CheckSum(U8 *buf, U8 len) //buf為數(shù)組,len為數(shù)組長度
{
U8 i, ret = 0;
for(i=0; i< len; i++)
{
ret += *(buf++);
}
ret = ret;
return ret+1;
}
發(fā)送和接收的報文要滿足不定長
HAL庫的中斷接收函數(shù)
如果要直接使用HAL庫的中斷接收函數(shù),也就是HAL_UART_Receive_IT()函數(shù)
HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5); //下位機(jī)FPGA
在使用時,選擇串口,選擇接收的緩沖區(qū),選擇接收長度。
/**
* @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;
}
}
這個函數(shù)本質(zhì)上其實不是中斷接收函數(shù),只是配置函數(shù),配置開啟中斷的信息,并且接收多少定長的數(shù)據(jù)結(jié)束本數(shù)據(jù)接收,串口的中斷接收還是在中斷中進(jìn)行。
我們本次的長度雖然也是定長,但是有兩種長度數(shù)據(jù)的接收,所以還是從設(shè)計接收不定長的數(shù)據(jù)為最終效果。
狀態(tài)機(jī)的運用
對于不定長數(shù)據(jù)的接收,使用了狀態(tài)機(jī),分兩次中斷來接收數(shù)據(jù)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart- >Instance == USART6) // 判斷是由哪個串口觸發(fā)的中斷
{
if(StateMachine_USART6) //狀態(tài)機(jī)為1,都接收完畢,準(zhǔn)備校驗
{
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; //狀態(tài)機(jī)為0
len_counter6 = 0;
HAL_UART_Receive_IT(&huart6,UART6_RxBuffer,5);
}
else //狀態(tài)機(jī)為0,只接受到了前五個字節(jié),繼續(xù)接收后面的字節(jié)
{
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);
}
}
}
}
核心思想就是先接收報文的頭,根據(jù)頭來判斷后面的長度,把應(yīng)答報文和音量數(shù)據(jù)報文區(qū)分開,不合格的報文直接舍去同時開啟新的接收。
-
FPGA
+關(guān)注
關(guān)注
1629文章
21729瀏覽量
602991 -
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355739 -
下位機(jī)
+關(guān)注
關(guān)注
0文章
94瀏覽量
18753 -
串口中斷
+關(guān)注
關(guān)注
0文章
64瀏覽量
13882 -
USART串口
+關(guān)注
關(guān)注
0文章
32瀏覽量
6818
發(fā)布評論請先 登錄
相關(guān)推薦
評論