当前位置:网站首页>串口接收一包数据

串口接收一包数据

2022-07-07 23:10:00 Zelonal

以单片机N32G435为例,串口通信为GPS,配合定时器2接收一包数据。
通过在串口接收中断中不断更新定时器2的计数值,直到定时器2中断溢出(一般定时10ms),表示一包数据接收完成。
在调试过程中,发现接收中断只进了一次,一个字符串只接收到了一个字符,在网上查询后得出了几个解决办法,如下:

  1. 中断程序占用时间过长,导致后面的数据到达的时候无法接收。
  2. 中断清除标志位。
  3. 串口中断优先级太低,导致中断嵌套。将优先级设为最高。

本人中断函数中已添加中断清除,也提高了中断优先级,但并没有解决,后来发现将中断接收函数中的printf();函数删除,发现恢复正常,应该是printf();函数占用时间过长导致后面数据无法接到!!
下面将配置过程和处理部分做个笔记:

// 定时器2初始化配置
void TIM2_Int_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitType TIM_TimeBaseInitStructure;
	NVIC_InitType        NVIC_InitStructure;
	
	RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2,ENABLE);  ///使能TIM2时钟
	
  	TIM_TimeBaseInitStructure.Period = arr; 	//自动重装载值
	TIM_TimeBaseInitStructure.Prescaler=psc;  //定时器分频
	TIM_TimeBaseInitStructure.CntMode=TIM_CNT_MODE_UP; //向上计数模式
	TIM_TimeBaseInitStructure.ClkDiv=TIM_CLK_DIV1; 
	
	TIM_InitTimeBase(TIM2,&TIM_TimeBaseInitStructure);//初始化TIM2
	TIM_ConfigInt(TIM2,TIM_INT_UPDATE,ENABLE); //允许定时器3更新中断
	TIM_Enable(TIM2,DISABLE); //先失能定时器3
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; //定时器3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_ClrIntPendingBit(TIM2,TIM_INT_UPDATE);  //清除中断标志位
}
// 定时器2中断函数处理
void TIM2_IRQHandler(void)
{
	if(TIM_GetIntStatus(TIM2,TIM_INT_UPDATE)==SET) //溢出中断
	{
		Uart3DataNeedProcessFlag=1;//需要处理当前数据
		TIM_Enable(TIM2,DISABLE);//停止定时器
		TIM_ClrIntPendingBit(TIM2,TIM_INT_UPDATE);  //清除中断标志位  
	}
}
//GPS-UART配置
void Uart3Init (void)
{	
	GPIO_InitType   GPIO_InitStructure;
    USART_InitType  USART_InitStructure;
    NVIC_InitType   NVIC_InitStructure;
	
    //开时钟
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB,ENABLE); 
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART5,ENABLE);

    //GPIO口配置
    GPIO_InitStructure.Pin 			  = GPIO_PIN_8 ; //
    GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF6_UART5;
    GPIO_InitPeripheral(GPIOB,&GPIO_InitStructure); //
    
	GPIO_InitStructure.Pin 			  = GPIO_PIN_9;
	GPIO_InitStructure.GPIO_Pull      = GPIO_Pull_Up;
	GPIO_InitStructure.GPIO_Alternate = GPIO_AF6_UART5;
	GPIO_InitPeripheral(GPIOB,&GPIO_InitStructure); //
	
	//UART配置
	USART_InitStructure.BaudRate 	         = 9600;//串口波特率
	USART_InitStructure.WordLength           = USART_WL_8B;//字长为8位数据格式
	USART_InitStructure.StopBits             = USART_STPB_1;//一个停止位
	USART_InitStructure.Parity               = USART_PE_NO;//无奇偶校验位
	USART_InitStructure.HardwareFlowControl  = USART_HFCTRL_NONE;//无硬件数据流控制
	USART_InitStructure.Mode                 = USART_MODE_RX | USART_MODE_TX;	//收发模式
	USART_Init(UART5, &USART_InitStructure); // 

    //中断配置
 	NVIC_InitStructure.NVIC_IRQChannel                   = UART5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2 ;       //抢占优先级2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 2;        //子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;   //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
    
    USART_ConfigInt(UART5, USART_INT_RXDNE, ENABLE);
    USART_Enable(UART5, ENABLE);  
}
//中断函数处理,需要将此函数放到对应的中断函数中
void GPS_IRQHandler(void)
{
	volatile u8 Res;	
	if(USART_GetIntStatus(UART5,USART_INT_RXDNE)!=RESET)
	{		
			Res=USART_ReceiveData(UART5); 
			if(Uart3DataNeedProcessFlag==0)  
			{
				if(Uart3ReceiveDataNum<=UART3_RECEIVE_MAX_NUM)		
				{
					Uart3ReceiveData[Uart3ReceiveDataNum++] = Res;
					TIM_ClrIntPendingBit(TIM2,TIM_INT_UPDATE);//清除定时器溢出中断	
					TIM_Enable(TIM2,ENABLE);//开始计时			
					TIM_SetCnt(TIM2,0);//复位定时器
				}
				else
				{				
					Uart3ReceiveDataNum=0;
					Uart3DataNeedProcessFlag=1;
				}
			}
	}	 
}
原网站

版权声明
本文为[Zelonal]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_40821065/article/details/125526267