单片机: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;
}
}
}
|
|