STM32F1 串口接受不定长数据总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wekic/article/details/84753016

串口接受不定长数据,就是数据格式不确定,长度不确定,我们需要找到判断是否接收完成的.

如果是一个数据侦,接收时数据字节之间的间隔时间是很短,但接收完成时,我们就无收到数据了,所以我们判断是否接收完成,就是判断数据字节间的间隔

我想到的到的方法有2:

1.串口接收数据+定时做超时判断

2.串口接收数据+IDLE空闲中断

3.DMA串口数据接收+IDLE空闲中断

以下是我整理的代码:

Usart_Init 串口初始化,看链接STM32F1 串口初始化的整理

#include "ESP8266.h"
#include "usart.h"
//接收不定长度信息,两种处理方法
//方法1:串口接收数据,定时判断超时取出数据
//方法2:DMA接收 +IDLE中断取出数据
//方法3:串口接收+IDLE中断取出数据

/*---------------------------------------------------------------------------------------|
 * DMA串口通道表                                                                         |
 *-----|-------|-----------|------------|-----------|-----------|-----------|------------|
 *通道 |   1   |     2     |       3    |    4      |    5      |    6      |     7      |
 *-----|-------|-----------|------------|-----------|-----------|-----------|------------|
 *DMA1 |  NC   | USART3_TX | USART3_RX  | USART1_TX | USART1_RX | USART2_RX | USART2_TX  |
 *-----|-------|-----------|------------|-----------|-----------|-----------|------------|
 *DMA2 |  NC   |    NC     | UART4_RX   |    NC     | UART4_TX  |    NC     |     NC     |
 *-----|-------|-----------|------------|-----------|-----------|-----------|------------|
 */
//WiFi模块使用的是串口


//方法2:DMA接收 +IDLE中断取出数据
//参数(DMA通道,外设地址,储存地址,储存长度)
void DMAx_InitRX ( DMA_Channel_TypeDef *DMAn_Channelx, u32 par, u32 mar, u16 ndtr )
{
    DMA_InitTypeDef  DMA_InitStructure;		
		if(	DMAn_Channelx== DMA1_Channel1 || \
			  DMAn_Channelx== DMA1_Channel2 || \
			  DMAn_Channelx== DMA1_Channel3 || \
			  DMAn_Channelx== DMA1_Channel4 || \
			  DMAn_Channelx== DMA1_Channel5 || \
			  DMAn_Channelx== DMA1_Channel6 || \
			  DMAn_Channelx== DMA1_Channel7 ){
     RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_DMA1, ENABLE ); //DMA1时钟使能		
		}else{
		 RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_DMA2, ENABLE ); //DMA1时钟使能		
		}
    //DMA_DeInit(DMAy_Channelx);

    /* 配置 DMA */
    DMA_InitStructure.DMA_PeripheralBaseAddr = par;															//DMA外设地址
    DMA_InitStructure.DMA_MemoryBaseAddr 		 = mar;															//DMA 存储器0地址
    DMA_InitStructure.DMA_DIR            		 = DMA_DIR_PeripheralSRC;						//外设作为数据传输的来源
    DMA_InitStructure.DMA_BufferSize 				 = ndtr;					                  //数据传输量
    DMA_InitStructure.DMA_PeripheralInc 		 = DMA_PeripheralInc_Disable;       //外设非增量模式
    DMA_InitStructure.DMA_MemoryInc 			   = DMA_MemoryInc_Enable;					  //存储器增量模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;     //外设数据长度:8位
    DMA_InitStructure.DMA_MemoryDataSize 		 = DMA_MemoryDataSize_Byte;				  //存储器数据长度:8位
    DMA_InitStructure.DMA_Mode 			         = DMA_Mode_Normal;									// 使用普通模式
    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;							//中等优先级
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;  								//DMA通道x没有设置为内存到内存传输
    DMA_Init ( DMAn_Channelx, &DMA_InitStructure ); //初始化DMA
}

void ESP8266_Init2( COM_TypeDef COMx, u32 Baud, u8 Priority1, u8 Priority2 ,DMA_Channel_TypeDef *DMAn_Channelx,u8 *Buff,u16 buffsize)
{
    Usart_Init(COMx,Baud, Priority1 , Priority2 );
    /* 关闭串口接受中断*/
    USART_ITConfig ( COMn_USART[COMx], USART_IT_RXNE, DISABLE ); //关闭串口接受中断
    USART_Cmd ( COMn_USART[COMx], DISABLE );	 //关闭串口中断
    //配置DMA读取串口外设的数据  
	  if(COMx == COM1 || COMx == COM2 || COMx == COM3  )
		{
			DMAx_InitRX(DMAn_Channelx,(u32)&COMn_USART[COMx]->DR,(u32)Buff,buffsize);//DMA1通道5,外设为串口1,存储器为SendBuff,长度SEND_BUF_SIZE. 
      USART_DMACmd( COMn_USART[COMx],USART_DMAReq_Rx,ENABLE);			
		  DMA_Cmd(DMAn_Channelx,ENABLE);
		}
		USART_ITConfig(COMn_USART[COMx],USART_IT_IDLE,ENABLE); //开始空闲中断
		USART_Cmd( COMn_USART[COMx],ENABLE); //开启串口中断
}
#if 0
u8 Uart1_RXbuff[100]={0}; //接收的数据包

void USART1_IRQHandler(void)
{
	 u32 temp = 0;
	 u16 i = 0;
	 u8 tempdat = 0;
   if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET) //产生空闲中断
	 {
	    USART_ClearFlag(USART1,USART_IT_IDLE);
		 #if 1
		  temp = USART1->SR;
		  temp = USART1->DR; 					//清除空闲中断
		 #else
		   USART_ReceiveData(USART1); //清除中断
		 #endif
		  DMA_Cmd(DMA1_Channel5,DISABLE); //关闭DMA接收
		  temp = sizeof(Uart1_RXbuff) - DMA_GetCurrDataCounter(DMA1_Channel5); //得到数据长度 = 总长度 - 待传输的数目;
      for(i=0;i<temp;i++)
      {
			   Usart_SendByte(COM1,Uart1_RXbuff[i]);
			}
      //设置新的DMA传输地址,和接收缓存
      DMA_SetCurrDataCounter(DMA1_Channel5,sizeof(Uart1_RXbuff));  //重新设置剩余的数目
      DMA_Cmd(DMA1_Channel5,ENABLE);			
		   
	 }
}
#endif

//方法3:串口接收+IDLE中断取出数据
void ESP8266_Init3( COM_TypeDef COMx, u32 Baud, u8 Priority1, u8 Priority2 )
{
    Usart_Init(COMx,Baud, Priority1 , Priority2 );
		USART_ITConfig(COMn_USART[COMx],USART_IT_IDLE,ENABLE); //开始空闲中断
		USART_Cmd( COMn_USART[COMx],ENABLE); 							     //开启串口中断
}	
#if 1
u8 Uart1_RXbuff[100]={0}; //接收的数据包
u8 Usart1_ReState = 0;
void USART1_IRQHandler(void)
{
	 u32 temp = 0;
	 static u16 i = 0;
	 u8 tempdat = 0;
	if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) //串口接收
	{
		#if 1
	   Uart1_RXbuff[i++] = USART1->DR;  //保存数据
		#else
	   Uart1_RXbuff[i++] = USART_ReceiveData(USART1);  //保存数据		
    #endif		
	
	}
	
   if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET) //产生空闲中断,取出一侦数据包 
	 {
	    USART_ClearFlag(USART1,USART_IT_IDLE);
		 #if 1
		  temp = USART1->SR;
		  temp = USART1->DR; 					//清除空闲中断
		 #else
		   USART_ReceiveData(USART1); //清除中断
		 #endif
		 /*可直接复制取出一帧数据包*/
		   Usart1_ReState = 1; 
	 }
}
#endif

猜你喜欢

转载自blog.csdn.net/Wekic/article/details/84753016