打印
[STM32F4]

STM32F429串口uart使用DMA收发数据发送正常接收乱码

[复制链接]
6166|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
plingx|  楼主 | 2017-12-8 22:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 plingx 于 2017-12-11 10:55 编辑

    正在调试STM32F429使用DMA来收发串口USART的数据,目前USART1使用DMA收发是正常的,波特率为256000,但是使用相同的串口配置及DMA配置,单独开usart2或者usart3的DMA收发,当只收不发数据时,串口DMA接收数据正确;但当同时进行DMA收发时,接收到的数据就是错误的,通过PC串口向MCU发送固定的数据,在仿真下查看DMA接收buffer里的数据是乱的,查看USART2->DR寄存器的值发现接收的数据就是错误的。很费解,有哪位高手能帮忙看一下,感激不尽!
详细的相关配置及代码如下:

1.基本信息
USART2:256000,8,1,no parity,
DMA_TX:DMA1_Stream6,Direct mode,normal mode...
DMA_RX:DMA1_Stream5,Double buffer,circular mode...

2.详细代码
(1)串口usart2及DMA初始化
void Usart2DmaInit(void)
{   
    NVIC_InitTypeDef NVIC_InitStructure ;  
    GPIO_InitTypeDef GPIO_InitStructure;  
    USART_InitTypeDef USART_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;  
        
    //设置IO口及时钟        
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
/////////////////////////////////////////////////////////////////////////
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);        
/////////////////////////////////////////////////////////////////////////
    //串口收DMA配置           
    DMA_DeInit(DMA1_Stream5);  
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;      
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(USART2)->DR);     
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(UART2_DMA_RX0);
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;   
    DMA_InitStructure.DMA_BufferSize = UART_RX_BUFFER_SIZE;      
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;   
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;   
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;   
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;      
      
    DMA_Init(DMA1_Stream5, &DMA_InitStructure);    //配置DMA1的通道  
    DMA_MemoryTargetConfig(DMA1_Stream5,(uint32_t)UART2_DMA_RX1,DMA_Memory_1);        
    DMA_Cmd(DMA1_Stream5,ENABLE);                    //使能DMA接收通道

    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;    //通道设置为串口中断   
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;       //中断占先等级  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                 //中断响应优先级   
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断   
    NVIC_Init(&NVIC_InitStructure);   
//////////////////////////////////////////////////////////////////////////////////
    //串口发DMA配置        
    DMA_DeInit(DMA1_Stream6);                                                           //DMA通道配置        
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;                            //DMA发送通道
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(USART2)->DR); //外设地址         
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)UART2_DMA_TX;     //内存地址               
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                  //dma传输方向        
    DMA_InitStructure.DMA_BufferSize = 100;                                    //设置DMA在传输时缓冲区的长度        
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;         //设置DMA的外设递增模式,一个外设        
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    //设置DMA的内存递增模式  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //外设数据字长
    DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;     //内存数据字长
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                    //设置DMA的传输模式        
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                     //设置DMA的优先级别  
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                     //指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式        
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;         //指定了FIFO阈值水平                         DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                  //指定的Burst转移配置内存传输        
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  //指定的Burst转移配置外围转移 //        
    DMA_Init(DMA1_Stream6, &DMA_InitStructure);                          //配置DMAx的通道        
    DMA_ITConfig(DMA1_Stream6,DMA_IT_TC,ENABLE);                 //使能中断     

    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    NVIC_Init(&NVIC_InitStructure);         
///////////////////////////////////////////////////////////////////////////////
    //串口参数配置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;   
    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_InitStructure.USART_BaudRate = 256000;   
    USART_Init(USART2,&USART_InitStructure);  
  
    //配置中断
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;               //通道设置为串口中断   
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;       //中断占先等级  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                  //中断响应优先级   
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断   
    NVIC_Init(&NVIC_InitStructure);     
      
    USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);
    USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);  
  
    //中断配置
    USART_ITConfig(USART2,USART_IT_TC,DISABLE);  
    USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);  
    USART_ITConfig(USART2,USART_IT_TXE,DISABLE);  
    USART_ITConfig(USART2,USART_IT_IDLE,DISABLE);

    USART_Cmd(USART2, ENABLE);      
}

(2)DMA接收中断
void DMA1_Stream5_IRQHandler(void)                    // uart2 rx
{
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5) != RESET)
    {
        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TCIF5);
    }

    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TEIF5) != RESET)
    {
        DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_TEIF5);
    }
}

(3)DMA发送中断
void DMA1_Stream6_IRQHandler(void)                     //com6 uart2 tx
{
        if (DMA_GetITStatus(DMA1_Stream6, DMA_IT_TCIF6) != RESET)  //transfer complete interrupt flag
        {               
                DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);               
               
                DMA_Cmd(DMA1_Stream6,DISABLE);                                // stop DMA transmit

                Tmpbsy = 0;
               
                USART_ITConfig(USART1,USART_IT_TC,ENABLE);        //open usart transfer complete interrupt,to send the last 2 bytes.
        }                        
                                                
        if (DMA_GetITStatus(DMA1_Stream6, DMA_IT_HTIF6) != RESET)   //half transfer interrupt flag
        {
                DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_HTIF6);
        }                                
}

(4)主循环
void main(void)
{
    //Initilized functions
    //...
    //...


    while(1)
    {
        if(Tmpbsy==0)
        {
            Tmpbsy = 1;
            DMA_SetCurrDataCounter(DMA1_Stream6,100);
            DMA_Cmd(DMA1_Stream6,ENABLE);
        }   
    }
}





沙发
plingx|  楼主 | 2018-1-2 17:11 | 只看该作者
问题早已解决,此上DMA的配置是正确的,并无问题。问题出在别处。

使用特权

评论回复
板凳
biechedan| | 2018-1-2 21:55 | 只看该作者
plingx 发表于 2018-1-2 17:11
问题早已解决,此上DMA的配置是正确的,并无问题。问题出在别处。

使用特权

评论回复
地板
wangdezhi| | 2018-1-2 21:55 | 只看该作者
有可能是硬件的问题

使用特权

评论回复
5
isseed| | 2018-1-2 21:56 | 只看该作者
plingx 发表于 2018-1-2 17:11
问题早已解决,此上DMA的配置是正确的,并无问题。问题出在别处。

串口的波特率有问题,可能是硬件问题

使用特权

评论回复
6
biechedan| | 2018-1-2 22:00 | 只看该作者
plingx 发表于 2018-1-2 17:11
问题早已解决,此上DMA的配置是正确的,并无问题。问题出在别处。

怎么配置的问题?

使用特权

评论回复
7
wangdezhi| | 2018-1-2 22:00 | 只看该作者
共地了吗?

使用特权

评论回复
8
isseed| | 2018-1-2 22:00 | 只看该作者
plingx 发表于 2018-1-2 17:11
问题早已解决,此上DMA的配置是正确的,并无问题。问题出在别处。

正常的都是需要电源的地连接在一起。

使用特权

评论回复
9
lby| | 2019-3-21 22:42 | 只看该作者
楼主发帖不结贴,不好吧!
发帖求助于人,别人知道会帮助。但解决了问题,也要说出原因。认遇到同样问题的人参考。
估计是缓冲区在编译后冲突了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

1

粉丝