串口什么时候进回调函数? 答: 1)正常串口端无发送、无接收时,是不会进回调函数的。如果这种情况会进回调函数,TX、RX端外接上拉电阻稳定电平。 2)如果接收端有数据,立马就会进回调。事件是“接收超时事件”。 3)2541发送端发送完数据,会进回调函数。事件是“发送缓冲区空事件”。
这里的“接收超时事件”是通过轮询DMA中是否有数据,有数据则设置事件,然后跳转到串口回调函数,具体内容如下: 首先从初始化看起
void hal_Uart_Init(void)
{
NPI_InitTransport(simpleBLE_NpiSerialCallback); //simpleBLE_NpiSerialCallback 这就是串口回调函数
NPI_WriteTransport("nUart_Initrn", 12);
}
void NPI_InitTransport( npiCBack_t npiCBack )
{
halUARTCfg_t uartConfig;
// configure UART
uartConfig.configured = TRUE;
uartConfig.baudRate = NPI_UART_BR; //波特率
uartConfig.flowControl = NPI_UART_FC; //流控制
uartConfig.flowControlThreshold = NPI_UART_FC_THRESHOLD; //流控制阀值,当开启flowControl时,该设置有效
uartConfig.rx.maxBufSize = NPI_UART_RX_BUF_SIZE; //接收缓冲区大小
uartConfig.tx.maxBufSize = NPI_UART_TX_BUF_SIZE; //发送缓冲区大小
uartConfig.idletimeout = NPI_UART_IDLE_TIMEOUT;
uartConfig.intEnable = NPI_UART_INT_ENABLE; //是否开启中断
uartConfig.callBackFunc = (halUARTCBack_t)npiCBack; //接收回调函数 在这里uartConfig.callBackFunc指向它
// start UART
// Note: Assumes no issue opening UART port.
(void)HalUARTOpen( NPI_UART_PORT, &uartConfig );
return;
}
uint8 HalUARTOpen(uint8 port, halUARTCfg_t *config)
{
#if (HAL_UART_DMA == 1)
if (port == HAL_UART_PORT_0) HalUARTOpenDMA(config);
.......
}
static void HalUARTOpenDMA(halUARTCfg_t *config)
{
dmaCfg.uartCB = config->callBackFunc; //将串口回调函数地址给dmaCfg.uartCB全局变量
........
}
由上面几个函数知道,最终回调函数地址给到了dmaCfg.uartCB全局变量,然后在下面函数中进行跳转
static void HalUARTPollDMA(void)
{
uint8 evt = 0;
uint16 cnt;
#if DMA_PM
PxIEN &= ~DMA_RDYIn_BIT; // Clear to not race with DMA_RDY_IN ISR.
{
if (dmaRdyIsr || HAL_UART_DMA_RDY_IN() || HalUARTBusyDMA())
{
// Master may have timed-out the SRDY asserted state & may need a new edge.
#if HAL_UART_TX_BY_ISR
if (!HAL_UART_DMA_RDY_IN() && (dmaCfg.txHead != dmaCfg.txTail))
#else
if (!HAL_UART_DMA_RDY_IN() && ((dmaCfg.txIdx[0] != 0) || (dmaCfg.txIdx[1] != 0)))
#endif
{
HAL_UART_DMA_CLR_RDY_OUT();
}
dmaRdyIsr = 0;
if (dmaRdyDly == 0)
{
(void)osal_set_event(Hal_TaskID, HAL_PWRMGR_HOLD_EVENT);
}
if ((dmaRdyDly = ST0) == 0) // Reserve zero to signify that the delay expired.
{
dmaRdyDly = 0xFF;
}
HAL_UART_DMA_SET_RDY_OUT();
}
else if ((dmaRdyDly != 0) && (!DMA_PM_DLY || ((uint8)(ST0 - dmaRdyDly) > DMA_PM_DLY)))
{
dmaRdyDly = 0;
(void)osal_set_event(Hal_TaskID, HAL_PWRMGR_CONSERVE_EVENT);
}
}
PxIEN |= DMA_RDYIn_BIT;
#endif
#if !HAL_UART_TX_BY_ISR
HalUARTPollTxTrigDMA(); //
#endif
if (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead))
{
if (HAL_UART_DMA_NEW_RX_BYTE(uartRxBug))
{
do {
HAL_UART_RX_IDX_T_INCR(dmaCfg.rxHead);
} while (!HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead));
uartRxBug = dmaCfg.rxHead;
dmaCfg.rxTail = dmaCfg.rxHead;
}
HAL_UART_RX_IDX_T_INCR(uartRxBug);
}
cnt = HalUARTRxAvailDMA(); // Wait to call until after the above DMA Rx bug work-around.
#if HAL_UART_DMA_IDLE
if (dmaCfg.rxTick)
{
// Use the LSB of the sleep timer (ST0 must be read first anyway) to measure the Rx timeout.
if ((ST0 - dmaCfg.rxTick) > HAL_UART_DMA_IDLE)
{
dmaCfg.rxTick = 0;
evt = HAL_UART_RX_TIMEOUT;
}
}
else if (cnt != 0)
{
if ((dmaCfg.rxTick = ST0) == 0) // Zero signifies that the Rx timeout is not running.
{
dmaCfg.rxTick = 0xFF;
}
}
#else
if (cnt != 0)
{
evt = HAL_UART_RX_TIMEOUT; //设置为接收超时事件
}
#endif
if (cnt >= HAL_UART_DMA_FULL)
{
evt |= HAL_UART_RX_FULL;//接收为空事件???
}
else if (cnt >= HAL_UART_DMA_HIGH)
{
evt |= HAL_UART_RX_ABOUT_FULL;
if (!DMA_PM && (UxUCR & UCR_FLOW))
{
HAL_UART_DMA_CLR_RDY_OUT(); // Disable Rx flow.
}
}
if (dmaCfg.txMT)
{
dmaCfg.txMT = FALSE;
evt |= HAL_UART_TX_EMPTY;
}
if ((evt != 0) && (dmaCfg.uartCB != NULL))
{
dmaCfg.uartCB(HAL_UART_DMA-1, evt); //跳转到串口回调函数
}
if (DMA_PM && (dmaRdyDly == 0) && !HalUARTBusyDMA())
{
HAL_UART_DMA_CLR_RDY_OUT();
}
}
|