接收调试流程:
1、首先进入接收中断,看是否能够进入,如未能进入则可能:底层配置有问题、相关初始化未调用。
/**
* @brief IAP串口接收中断处理函数
* @param None
* @retval None
*/
void IAP_USART_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if(USART_GetITStatus(IAP_USART,USART_IT_RXNE) == SET)
{
/* 清除中断标志 */
USART_ClearITPendingBit(IAP_USART,USART_IT_RXNE);
/* 新方案 待校验*/
IAP_RX_BUF[IAP_Rxoffset%IAP_BUFF_LEN] = (u8)(USART_ReceiveData(IAP_USART) & 0xFF);
IAP_Rxoffset++;
if (IAP_Rxoffset >= IAP_BUFF_LEN) IAP_Rxoffset = 0;
/* 清零计数器, 并启动定时器 */
TIM_SetCounter(IAP_RX_TIM, 0);
TIM_Cmd(IAP_RX_TIM,ENABLE);
}
if (USART_GetITStatus(IAP_USART, USART_IT_ORE_RX) == SET)
{
USART_ClearITPendingBit(IAP_USART,USART_IT_ORE_RX);
USART_ReceiveData(IAP_USART);
}
/* leave interrupt */
rt_interrupt_leave();
}
2、其次进入定时器中断看是否超时,接收应当超时才正确。
/**
* @brief IAP串口接收定时器的中断处理函数
* @param None
* @retval None
*/
void IAP_RX_TIM_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (TIM_GetITStatus(IAP_RX_TIM, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(IAP_RX_TIM, TIM_IT_Update);
TIM_SetCounter(IAP_RX_TIM, 0);
/* TIM enable counter */
TIM_Cmd(IAP_RX_TIM, DISABLE);
rt_sem_release(&IapRx_OPSem);
}
/* leave interrupt */
rt_interrupt_leave();
}
3、最后看能否进入接收线程。
/**
* @brief IAP升级串口接收处理
* @param void *paramemter
* @retval None
*/
static void Bsp_iaprx_task(void *paramemter)
{
for (;;)
{
rt_sem_take(&IapRx_OPSem, RT_WAITING_FOREVER);
DRV_IAP_Receive_Task();
}
}
注:底层配置可能问题:
1、GPIO口的初始化可先配置,但在配置波特率和使能接收中断之前必须进行串口时钟使能,不使能时钟是没有电的,不能进行初始化。
/**
* @brief BSP层 IAP串口配置初始化
* @param None
* @retval None
*/
static void BSP_IapUartCFG_Init(void)
{
USART_InitTypeDef USART_InitStruct = {0};
/* RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE) */
RCC_IAP_UART_CLK_ENABLE();
USART_InitStruct.USART_BaudRate = IAP_BAUDRATE;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(IAP_USART, &USART_InitStruct);
USART_Cmd(IAP_USART,ENABLE); /* 该函数会使能串口 */
}
2、底层GPIO口的初始化、接收中断的初始化、串口波特率相关配置的初始化必须进行调用。
/**
* @brief BSP层 IAP串口的初始化
* 包括其接收中断、配置、发送DMA、接收定时器的初始化
* @param None
* @retval None
*/
void BSP_IAP_Uart_Init(void)
{
/* 配置初始化 */
BSP_IapUartCFG_Init();
/* 中断初始化 */
BSP_IapUartNVIC_Init();
/* DMA初始化 */
BSP_IapUartDMA_Init();
/* 定时器初始化 */
BSP_IapUartTIM_Init();
}
3、如在第一次接收发送完后,第二次发送无反应,调试进入DMA中断未清零,这里注意函数和参数是否匹配,如DMA_GetITStatus应对应IAP_TX_DMA_IT_TEIF,IT的对应IT,FLAG的对应FLAG。
/**
* @brief 背板串口DMA发送的中断处理函数
* @param None
* @retval None
*/
void IAP_DMA_TX_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
if (DMA_GetITStatus(IAP_TX_DMA_STREAM, IAP_TX_DMA_IT_TEIF))
{
DMA_ClearITPendingBit(IAP_TX_DMA_STREAM, IAP_TX_DMA_IT_TEIF);
DMA_Cmd(IAP_TX_DMA_STREAM,DISABLE); /* 传输完成以后关闭串口DMA */
}
if (DMA_GetITStatus(IAP_TX_DMA_STREAM, IAP_TX_DMA_IT_TCIF))
{
DMA_ClearITPendingBit(IAP_TX_DMA_STREAM, IAP_TX_DMA_IT_TCIF);
/* TODO 待完善发送完成需要关闭该关闭的东西 */
DMA_Cmd(IAP_TX_DMA_STREAM,DISABLE); /* 传输完成以后关闭串口DMA */
}
/* leave interrupt */
rt_interrupt_leave();
}