你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
Ha~ha~ 提问时间:2024-11-5 14:58 / 已解决
单片机: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;
                }
        }
}



收藏 评论4 发布时间:2024-11-5 14:58

举报

4个回答
xmshao 回答时间:2024-11-5 17:40:02
可以肯定,STM32F4的串口在配置DMA之后,波特率支持到921600是可以的。
rrr.png


/* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 921600;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;


ols.png
我刚才模拟的应用场景做了验证测试,使用F407.


开启了TIM2的1ms中断,同时TICK的ms中断也在运行。


UART3的收发都采用DMA方式,测试是没问题的。




我觉得你的代码配置应该没啥问题,怀疑代码处理哪里有些问题,尤其当波特率较高时。具体原因还得你再找找。

Ha~ha~ 回答时间:2024-11-6 08:18:09
xmshao 发表于 2024-11-5 17:40
可以肯定,STM32F4的串口在配置DMA之后,波特率支持到921600是可以的。

       我刚刚重新检查了一下代码,一开始是把USART3对应的GPIO配置成了开漏输出,将串口对应的GPIO配置成推挽输出后,波特率就可以支持到921600了。

        DMA传输会影响到串口GPIO的驱动能力吗
xmshao 回答时间:2024-11-6 09:08:38

Ha~ha~ 发表于 2024-11-6 08:18
我刚刚重新检查了一下代码,一开始是把USART3对应的GPIO配置成了开漏输出,将串口对应的GPIO配置成 ...

DMA应该是被冤枉了。它肯定影响不到GPIO的速率的。

但你UART的复用GPIO配置成PP合理合适,配置为OD比较反常。

Ha~ha~ 回答时间:2024-11-7 10:10:04

xmshao 发表于 2024-11-6 09:08
DMA应该是被冤枉了。它肯定影响不到GPIO的速率的。</p>
<p>但你UART的复用GPIO配置成PP合理合适,配置为OD ...

这是从另外一块板子上移植的串口代码,之前哪个板子的串口3做rs485接口,外部有上拉,所以当时给配置了开漏,移植的时候忽略这问题了。😕

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版