版权声明:本文为博主原创文章,未经博主允许不得转载。 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