串口IAP升级DAY2:串口发送接收调试流程

9 篇文章 0 订阅
8 篇文章 0 订阅
文章详细描述了嵌入式系统中进行串口接收中断处理的调试步骤,包括进入中断、检查定时器超时以及接收线程的执行。在中断服务函数中,处理接收数据和清除中断标志,并使用定时器监控接收超时。同时强调了底层配置的重要性,如串口时钟使能、GPIO初始化和DMA中断的正确处理。
摘要由CSDN通过智能技术生成

接收调试流程:

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();	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值