打印
[STM32F4]

STM32F4的串口在配置DMA之后,不能使用高波特率吗?

[复制链接]
357|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
两只袜子|  楼主 | 2024-11-6 16:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单片机:STM32F407ZGT6
环境:标准库
        使用USART3 在不使用 DMA 传输的情况下,USART3 的波特率可以设置为 921600 甚至更高;但是在添加了DMA 传输之后,波特率只能设置到 230400 了,在往上就会出现乱码了。
        整个程序只运行了 USART1 USART3 和 TIM2 外设,没有其他的功能,其中只有 USART3 配置了DMA;请问是USART和DMA的存在问题,还是有其他的原因。

usart.h

#ifndef __USART_H__
#define __USART_H__

#include "stm32f4xx.h"

/******************************USART3******************************/
#define USART3_DMA_TxBufMaxSize 1024
#define USART3_DMA_RxBufMaxSize 1024

extern uint16_t USART3_RxLen;
extern uint8_t USART3_DMA_RxBuf[USART3_DMA_RxBufMaxSize];

static void USART3_DMA_Tx_Init(void);
static void USART3_DMA_Rx_Init(void);

void USART3_Init(uint32_t bound);
void USART3_DMA_SendDatas(uint8_t *data, uint16_t size);
/*****************************************************************/

#endif


usart.c

/**************************************************************
*函数:串口3初始化,带DMA传输 TXB10  RXB11
*参数:
*        @bound:串口波特率
*备注:!!!最高波特率230400
**************************************************************/
void USART3_Init(uint32_t bound)
{
        GPIO_InitTypeDef GPIO_InitStructure;      // GPIO配置结构体
        USART_InitTypeDef USART_InitStructure;  // 串口配置结构体
        NVIC_InitTypeDef NVIC_InitStructure;             // 中断向量控制器结构体
         
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);         // GPIOB时钟使能
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);        // USART3时钟使能      
      
        /* 引脚复用配置 */
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_USART3);
        GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3);
      
          /* GPIO配置 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                // 配置为复用模式
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        // GPIO速率50MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;                 // 开漏输出
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;         // 禁用上下拉
        GPIO_Init(GPIOB,&GPIO_InitStructure);                                 // 初始化GPIO
      
        /* 串口配置 */
        USART_InitStructure.USART_BaudRate = bound;                                   // 波特率
        USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位数据位
        USART_InitStructure.USART_StopBits = USART_StopBits_1;                  // 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(USART3, &USART_InitStructure);   // 串口初始化
               
        USART_ClearFlag(USART3, USART_FLAG_TC);
        USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);// 使能串口空闲中断
      
        /* NVIC配置 */
          NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;                 // USART1中断同道
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2 ;         // 抢占优先级 2
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                 // 响应优先级 2
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 // 中断通道使能
        NVIC_Init(&NVIC_InitStructure);                                                 // NVIC初始化
      
        USART_Cmd(USART3, ENABLE); // 开启串口        
      
        USART3_DMA_Tx_Init();
        USART3_DMA_Rx_Init();
}


/* DMA 发送缓冲区 */
static uint8_t USART3_DMA_TxBuf[USART3_DMA_TxBufMaxSize] = {0};
/**************************************************************
*函数:串口3 DMA 发送初始化
*参数:无
*备注:!!!最高波特率230400
**************************************************************/
static void USART3_DMA_Tx_Init(void)
{
        DMA_InitTypeDef DMA_InitStructure;         // DMA 初始化结构体
        NVIC_InitTypeDef NVIC_InitStructure; // NVIC 初始化结构体,发送完成中断
        /* 使能 DMA1 时钟 */
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
        /*  */
        DMA_DeInit(DMA1_Stream3);
        while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE);
      
        DMA_InitStructure.DMA_Channel = DMA_Channel_4;                                                // DMA1 的通道4
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;         // 外设的地址
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART3_DMA_TxBuf; // 内存地址
        DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                // 数据方向,内存到外设
        DMA_InitStructure.DMA_BufferSize = USART3_DMA_TxBufMaxSize;                        // 发送缓冲区大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外设地址不自增
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                // 内存地址自增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据长度1字节
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                 // 内存数据长度1字节
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                // 正常模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                        // 高优先级
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;                                // 不使能管道
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; // 管道大小
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                 //
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //
      
        DMA_Init(DMA1_Stream3, &DMA_InitStructure);
        DMA_ITConfig(DMA1_Stream3, DMA_IT_TC, ENABLE);
      
        USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
      
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      
        NVIC_Init(&NVIC_InitStructure);
      
        while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE);
        DMA_Cmd(DMA1_Stream3, DISABLE);
}

uint8_t USART3_DMA_RxBuf[USART3_DMA_RxBufMaxSize] = {0};
static void USART3_DMA_Rx_Init(void)
{
        DMA_InitTypeDef DMA_InitStructure;
      
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
      
        DMA_DeInit(DMA1_Stream1);
        while (DMA_GetCmdStatus(DMA1_Stream1) != DISABLE);
      
        DMA_InitStructure.DMA_Channel = DMA_Channel_4;
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART3_DMA_RxBuf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
        DMA_InitStructure.DMA_BufferSize = USART3_DMA_RxBufMaxSize;
        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_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
      
        DMA_Init(DMA1_Stream1, &DMA_InitStructure);
      
        USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
      
        while (DMA_GetCmdStatus(DMA1_Stream1) != DISABLE);
        DMA_Cmd(DMA1_Stream1, ENABLE);
}
      
      
/**************************************************************
*函数:串口3接收中断处理函数、接收中断,空闲中断
**************************************************************/
uint16_t USART3_RxLen = 0;
void USART3_IRQHandler(void)
{
        if(USART_GetITStatus(USART3, USART_IT_IDLE) == SET)
        {
                USART3->DR;
                USART3->SR;
               
                DMA_Cmd(DMA1_Stream1, DISABLE);
               
                USART3_RxLen = USART3_DMA_RxBufMaxSize - DMA_GetCurrDataCounter(DMA1_Stream1);
                DMA_ClearFlag(DMA1_Stream1, DMA_FLAG_TCIF1 | DMA_FLAG_FEIF1 | DMA_FLAG_DMEIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_HTIF1);
               
                DMA_SetCurrDataCounter(DMA1_Stream1, USART3_DMA_RxBufMaxSize);
                DMA_Cmd(DMA1_Stream1, ENABLE);
        }
      
        if(USART_GetFlagStatus(USART3, USART_IT_TXE) == RESET)
        {
                USART_ITConfig(USART3, USART_IT_TC, DISABLE);
        }
}

void DMA1_Stream3_IRQHandler(void)
{
        if(DMA_GetFlagStatus(DMA1_Stream3, DMA_FLAG_TCIF3) != RESET)
        {
                DMA_ClearFlag(DMA1_Stream3, DMA_FLAG_TCIF3);
                DMA_Cmd(DMA1_Stream3, DISABLE);
                USART_ITConfig(USART3, USART_IT_TC, ENABLE);
        }
}

void USART3_DMA_SendDatas(uint8_t *data, uint16_t size)
{
        memcpy(USART3_DMA_TxBuf, data, size);
        while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE);
      
        DMA_SetCurrDataCounter(DMA1_Stream3, size);
      
        DMA_Cmd(DMA1_Stream3, ENABLE);
}



主函数:

int main()
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        led_init();
        TIM2_delay_init();
        USART1_Init(921600);
        USART3_Init(230400);
        while(1)
        {
                TIM2_delay_ms(300);
                led_ctrl(LED0, LED_OFF);
                USART3_DMA_SendDatas((uint8_t *)"DMA_Test\n", 9);
                TIM2_delay_ms(300);
                led_ctrl(LED0, LED_ON);
                if(USART3_RxLen > 0)
                {
                        printf("USART3_DMA_Recv %d :%s\n", USART3_RxLen, USART3_DMA_RxBuf);
                        memset(USART3_DMA_RxBuf, '\0', USART3_RxLen);
                        USART3_RxLen = 0;
                }
        }
}

使用特权

评论回复
沙发
yellow555| | 2024-11-8 21:02 | 只看该作者
波特率只能设置到 230400 了,在往上就会出现乱码了

使用特权

评论回复
板凳
laocuo1142| | 2024-11-9 11:18 | 只看该作者
在使用STM32F4的USART3时,不配置DMA传输的情况下,波特率可以设置为921600甚至更高;但在添加了DMA传输后,波特率只能设置到230400,再往上设置则会出现乱码。

使用特权

评论回复
地板
powerantone| | 2024-11-9 11:20 | 只看该作者
看硬件能不能支持

使用特权

评论回复
5
flycamelaaa| | 2024-11-9 12:00 | 只看该作者
STM32F4系列微控制器具有高度灵活的配置选项,可以支持不同的波特率。其UART接口(如UART4)支持多种波特率配置,可以根据需求进行设置,以适应不同的通信速率。
同时,利用DMA进行数据传输可以显著减轻CPU的负担,提高数据传输效率。理论上,这并不应该直接限制串口波特率的设置。

使用特权

评论回复
6
stormwind123| | 2024-11-9 14:00 | 只看该作者
在高波特率下,信号的稳定性变得更加重要。需要确保电路设计中考虑了信号完整性,包括布线、阻抗匹配等因素。

使用特权

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

本版积分规则

2038

主题

7364

帖子

10

粉丝