1.你是不是直接在中断回调里面直接调用空闲接收函数了?又或者你进了错误中断没有重新开启接收吧,我使用的时候不需要开启这个__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
2.如果串口数据超过缓冲区长度,我工程里面HAL_UARTEx_RxEventCallback 这个函数我写了开启空闲接收DMA完成的判断,内容没写
如果超过数据长度,下面是我实际项目中用到的代码,如果有用的数据放到队列邮箱里面,无效的数据直接扔掉就行
需要注意的是如果在中断回调里面调用HAL库的重启接收函数(BSP_UART_ReceiveMode 函数里面的这几个函数)由于HAL_LOCK的关系,
主流程里面对应串口的发送函数需要在调用前关闭中断执行完开启中断,如下
HAL_NVIC_DisableIRQ(eIRQn);
HAL_UART_Transmit_IT(phuartx->huart, phuartx->pTxBuf, Size);
HAL_NVIC_EnableIRQ(eIRQn);
不做处理的话串口会卡死,原因就是主流程里面串口发送执行一半进入中断(HAL库串口状态此时为忙),这个时候如果中断回调里面调用接收函数会失败,因为串口此时为忙
[C] 纯文本查看 复制代码 /**
* @brief 串口接收事件回调函数 如果是空闲中断触发ReceptionType = HAL_UART_RECEPTION_STANDARD
*
* @param huart
* @param Size
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
BspUart_t *phuartx = UART_GetHandlePtr(huart);
/* HAL_UART_RECEPTION_TOIDLE 说明是DMA接收完成,或者半传输完成 */
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
{
if(Size == phuartx->rxSize)
{
phuartx->rxLen = Size;
phuartx->rxFlag = 2;
phuartx->pRxBuf[phuartx->rxSize ] = phuartx->rxLen/256;
phuartx->pRxBuf[phuartx->rxSize+1] = phuartx->rxLen%256;
osStatus_t tOSStatus = osMessageQueuePut(phuartx->rxMqId, phuartx->pRxBuf, 0U, 0U);
if(tOSStatus)
{
printf("tOSStatus:%d\r\n", tOSStatus);
}
BSP_UART_ReceiveMode(phuartx, phuartx->rxMode);
}
}
/* HAL_UART_RECEPTION_STANDARD 说明是空闲中断触发的接收事件 */
if (huart->ReceptionType == HAL_UART_RECEPTION_STANDARD)
{
/*结算接收到的数据长度 置rxFlag = 1,接收到一帧数据*/
phuartx->rxLen = Size;
phuartx->rxFlag = 1;
/* 如果不使用FIFO 计算接收长度,置帧接收完成标志 */
if(phuartx->rxCache == UART_CACHE_SRAM)
{
osThreadFlagsSet(phuartx->threadId, UART_RX_CPLT);
}
/* 如果使用FIFO 缓冲区最后一个字节作为接收长度,且将数据压入缓存区 */
else if(phuartx->rxCache == UART_CACHE_FIFO)
{
phuartx->pRxBuf[phuartx->rxSize ] = phuartx->rxLen/256;
phuartx->pRxBuf[phuartx->rxSize+1] = phuartx->rxLen%256;
osMessageQueuePut(phuartx->rxMqId, phuartx->pRxBuf, 0U, 0U);
}
/* 重新开启串口接收 如果在中断里面开启接收,发送函数需要开关中断
具体原因请看文档UART里面关于 __HAL_LOCK 说明 */
BSP_UART_ReceiveMode(phuartx, phuartx->rxMode);
}
}
[C] 纯文本查看 复制代码 /**
* @brief 串口IT中断模式发送函数 pData会copy到pTxBuf
*
* @param phuartx 串口句柄
* @param pData 串口发送数据地址
* @param Size 串口发送数据长度
*/
void BSP_UART_Transmit_IT(BspUart_t *phuartx, uint8_t *pData, uint16_t Size)
{
while(phuartx->txStat == UART_TX_STATE_BUSY)
{
}
phuartx->txStat = UART_TX_STATE_BUSY;
memcpy(phuartx->pTxBuf, pData, Size);
IRQn_Type eIRQn = (IRQn_Type)__UART_IRQ(phuartx->huart);
HAL_NVIC_DisableIRQ(eIRQn);
HAL_UART_Transmit_IT(phuartx->huart, phuartx->pTxBuf, Size);
HAL_NVIC_EnableIRQ(eIRQn);
}
/**
* @brief 串口DMA模式发送函数 pData会copy到pTxBuf
*
* @param phuartx 串口句柄
* @param pData 发送数据的缓存地址
* @param Size 发送数据的大小
*/
void BSP_UART_Transmit_DMA(BspUart_t *phuartx, uint8_t *pData, uint16_t Size)
{
while(phuartx->txStat == UART_TX_STATE_BUSY)
{
}
phuartx->txStat = UART_TX_STATE_BUSY;
memcpy(phuartx->pTxBuf, pData, Size);
IRQn_Type eIRQn = (IRQn_Type)__UART_IRQ(phuartx->huart);
HAL_NVIC_DisableIRQ(eIRQn);
HAL_UART_Transmit_DMA(phuartx->huart, phuartx->pTxBuf, Size);
HAL_NVIC_EnableIRQ(eIRQn);
}
[C] 纯文本查看 复制代码 void BSP_UART_ReceiveMode(BspUart_t *phuartx, uint8_t rxMode)
{
if(rxMode == UART_RX_IDLE_DMA)
{
HAL_UARTEx_ReceiveToIdle_DMA(phuartx->huart, phuartx->pRxBuf, phuartx->rxSize);
}
else if(rxMode == UART_RX_IDLE_IT)
{
HAL_UARTEx_ReceiveToIdle_IT(phuartx->huart, phuartx->pRxBuf, phuartx->rxSize);
}
else if(rxMode == UART_RX_ONLY_DMA)
{
HAL_UART_Receive_DMA(phuartx->huart, phuartx->pRxBuf, phuartx->rxSize);
}
else /* if(rxMode == UART_RX_ONLY_IT) */
{
HAL_UART_Receive_IT(phuartx->huart, phuartx->pRxBuf, phuartx->rxSize);
}
}
[C] 纯文本查看 复制代码 /* 串口控制句柄 */
BspUart_t *g_ptBspUart[UART_NUM];
/**
* @brief 通过huart->Instance 来获取串口号 0~7 [USART1~USART3 UART4~5 USART6 UART7~8]
*
* @param huart
* @return BspUart_t* 串口句柄指针
*/
static BspUart_t *UART_GetHandlePtr(UART_HandleTypeDef *huart)
{
uint8_t idx = __UART_INDEX(huart);
return g_ptBspUart[idx];
}
[C] 纯文本查看 复制代码 #define UART_NUM 8
#define __UART_INDEX(__HANDLE__) \
(((__HANDLE__)->Instance == USART1 ) ? 0 : \
((__HANDLE__)->Instance == USART2 ) ? 1 : \
((__HANDLE__)->Instance == USART3 ) ? 2 : \
((__HANDLE__)->Instance == UART4 ) ? 3 : \
((__HANDLE__)->Instance == UART5 ) ? 4 : \
((__HANDLE__)->Instance == USART6 ) ? 5 : \
((__HANDLE__)->Instance == UART7 ) ? 6 : \
((__HANDLE__)->Instance == UART8 ) ? 7 : \
0xFF)
|