本帖最后由 michael91 于 2017-8-19 19:26 编辑  
 
@正点原子  原子哥,各位大神帮忙看一下 USATR1串口用DMA接收, 数据错误,网上的方法都试过了,也请教了别人,但是还是无法解决 
左边是循环发送8字节数据帧,右边是接收的数据帧,前两个字节FF, FE和后两个字节FF,FE是我自己加的帧头和帧尾,右边第1行是复位后的第一次正确接收,从第2行开始出现错误,第3行往后错误相同,都是第8个字节跑到了第1个字节的位置。 DMA配置的正常模式,不是循环模式。循环模式好像会出现这样的问题  
 
 
 
#include "delay.h" 
#include "RS232_DMA_RX.h"  
#include "RS232_DMA_TX.h"  
u8 USART1_Rec_Cnt=0; 
u8 DMA2_Rece_Buf[12]; 
// 
void USART1_Init(u32 bound) 
{ 
    // 
    GPIO_InitTypeDef GPIO_InitStructure; 
    USART_InitTypeDef USART_InitStructure; 
    NVIC_InitTypeDef NVIC_InitStructure; 
    DMA_InitTypeDef DMA_InitStructure; 
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);  //使能GPIOA时钟 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能USART1时钟 
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
  //串口1引脚复用映射 
 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);   //GPIOA9复用为USART1 
 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1 
  
 //USART1     
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz 
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 
 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9 10 
  
 //USART1 初始化设置 
 USART_InitStructure.USART_BaudRate = bound;//波特率设置 
 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 
 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 
 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 
 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 
 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 
 USART_Init(USART1, &USART_InitStructure); //初始化串口1 
  
  
 //USART1 NVIC 配置 
 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级2 
 NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;  //响应优先级2 
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能 
 NVIC_Init(&NVIC_InitStructure);         //根据指定的参数初始化NVIC寄存器 
  
  
 USART_ITConfig(USART1,USART_IT_IDLE, ENABLE); //开启空闲中断 
    //相应的DMA配置 
 while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE){};  //等待DMA可配置  
 DMA_DeInit(DMA2_Stream5);   //将DMA2的通道5寄存器重设为缺省值,对应的串口1接收 
  
 DMA_InitStructure.DMA_BufferSize= DMA2_Rec_Len;  //长度8字节 
    DMA_InitStructure.DMA_Channel=DMA_Channel_4;     //对应串口1接收 
 DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralToMemory;   //外设到存储器 
 DMA_InitStructure.DMA_FIFOMode=DMA_FIFOMode_Disable;    //非FIFO模式 
 DMA_InitStructure.DMA_FIFOThreshold=DMA_FIFOThreshold_1QuarterFull;  
 DMA_InitStructure.DMA_Memory0BaseAddr=(u32)&DMA2_Rece_Buf[2];  //数据存储地址 
 DMA_InitStructure.DMA_MemoryBurst=DMA_MemoryBurst_Single;     //单次模式 
 DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;  //宽度8位 
 DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;     //存储器地址递增 
 DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;             //正常模式 
 DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&USART1->DR;   //外设地址,串口1 
 DMA_InitStructure.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;   //单次模式 
 DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; //宽度8位 
 DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;     //外设地址不增 
 DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;       //优先级中 
 DMA_Init(DMA2_Stream5,&DMA_InitStructure);    
// DMA_ITConfig(DMA2_Stream5,DMA_IT_TC,ENABLE);    //没用DMA传输完成中断,用了USART_IT_IDLE总线空闲中断   
// DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5); 
    DMA_Cmd(DMA2_Stream5, ENABLE);  
 USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);    //使能串口1 DMA接收  
  
 USART_Cmd(USART1, ENABLE);  //使能串口1 
} 
void USART1_IRQHandler(void)         //串口中断        
{ 
 if(USART_GetITStatus(USART1,USART_IT_IDLE)!= RESET)   //总线空闲中断 
 { 
  USART_Cmd(USART1, DISABLE);    //关闭串口接收 
  USART1->SR; 
  USART1->DR;  //先读这两个才能清除标志位 
  USART_ClearITPendingBit(USART1,USART_IT_IDLE); //清除标志位 
  DMA_Cmd(DMA2_Stream5, DISABLE);  //关闭DMA传输 
  DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5); //清除标志位 
   
  USART1_Rec_Cnt=DMA2_Rec_Len-DMA_GetCurrDataCounter(DMA2_Stream5);  //DMA2_Rec_Len=8,接受完8字节 
  if(USART1_Rec_Cnt==8) 
  { 
   USART1_Rec_Cnt=0; 
   DMA2_Rece_Buf[0]=0xFF;  DMA2_Rece_Buf[1]=0xFE;   //收到的数据加上两个字节的帧头 
   DMA2_Rece_Buf[10]=0xFF; DMA2_Rece_Buf[11]=0xFE;  //收到的数据加上两个字节的帧尾 
   USART3_SendData(DMA2_Rece_Buf,12);       //将数据发送到串口3 
  } 
   
  while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE); //确保DMA可以被设置    
  DMA_SetCurrDataCounter(DMA2_Stream5,DMA2_Rec_Len);  //数据传输量 DMA2_Rec_Len =8 
  DMA_Cmd(DMA2_Stream5,ENABLE);   //开启DMA传输  
  USART_Cmd(USART1, ENABLE);         //开启串口1接收 
 }  
} 
 
 |