STM32/STM8技术william hill官网
直播中

王兵

7年用户 203经验值
私信 关注
[问答]

STM32F407ZG串口4配置为DMA收发但无法发送数据

大家好!
首次使用STM32f407芯片,在串口使用过程中,发现如下问题,请各位告诉帮忙解决,谢谢!
目的:串口4使用DMA收发数据
IO口:接收PC11, 发送PC10
问题:使用下列串口初始化,接收和发送的中断都可以正常产生,串口4可以接收数据,但无法发送数据,PC10端口示波器上无法捕捉到数据(发送0xaa数据)
串口配置如下所示:
初始化:
void UART4_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
DMA_InitTypeDef  DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the UART4 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream2_IRQn;   // UART4接收
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;   // UART4发送
NVIC_Init(&NVIC_InitStructure);
// 串口缓冲区初始化
memset(UART4_DMA_Rx, 0xaa, sizeof(UART4_DMA_Rx));
memset(UART4_DMA_Tx, 0xaa, sizeof(UART4_DMA_Tx));

// 时钟配置
/* Peripheral Clock Enable -------------------------------------------------*/
/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC , ENABLE);
/* Enable USART clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
/* Enable the DMA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

// 串口IO口配置
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10 | GPIO_PinSource11, GPIO_AF_UART4);
// 串口设置
USART_InitStructure.USART_BaudRate = 115200;
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_Tx | USART_Mode_Rx;
USART_Init(UART4, &USART_InitStructure);

DMA_DeInit(DMA1_Stream2);
DMA_DeInit(DMA1_Stream4);
DMA_StructInit(&DMA_InitStructure);
// DMA设置
/* Configure DMA Initialization Structure */
DMA_InitStructure.DMA_BufferSize = UART_DMA_BUF_NUM ;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralBaseAddr =(UINT32) (&(UART4->DR)) ;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/* Configure TX DMA */
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 发送DMA设计为正常模式,需要发送时再开启
DMA_InitStructure.DMA_Channel = DMA_Channel_4 ;
DMA_InitStructure.DMA_DIR =  DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = (UINT32)UART4_DMA_Tx;
DMA_Init(DMA1_Stream4, &DMA_InitStructure);
/* Configure RX DMA */
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 接收DMA设计为循环收,否则接收一次后,无法正常接收到数据
DMA_InitStructure.DMA_Channel = DMA_Channel_4 ;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;
DMA_InitStructure.DMA_Memory0BaseAddr =(UINT32)UART4_DMA_Rx;
DMA_Init(DMA1_Stream2,&DMA_InitStructure);
// 使能串口
USART_Cmd(UART4, ENABLE);

/* Enable DMA USART TX Stream */
DMA_Cmd(DMA1_Stream2, ENABLE);  // RX
DMA_Cmd(DMA1_Stream4, ENABLE);  // TX

USART_DMACmd(UART4,USART_DMAReq_Tx,ENABLE);
USART_DMACmd(UART4,USART_DMAReq_Rx,ENABLE);
// 使能DMA中断
DMA_ITConfig(DMA1_Stream2, DMA_IT_TC, ENABLE);       //使能DMA1通道2发送完成中断
DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);       //使能DMA1通道4传输完成中断
}

中断函数:
// UART4的DMA接收中断入口
void DMA1_Stream2_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_Stream2, DMA_IT_TCIF2) == SET )
{
   //DMA_ClearFlag(DMA1_Stream2, DMA_FLAG_TCIF2);
   DMA_ClearITPendingBit(DMA1_Stream2, DMA_IT_TCIF2);
   DMA_Cmd(DMA1_Stream2, ENABLE);
  // 将数据放入缓冲区队列中
  // ....  
}
}

// UART4的DMA发送中断入口
void DMA1_Stream4_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_Stream4, DMA_IT_TCIF4) == SET )
{
  //DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
  DMA_Cmd(DMA1_Stream4, ENABLE);
  DMA_ClearITPendingBit(DMA1_Stream4, DMA_IT_TCIF4);
  TestIO();  
  DMA_Cmd(DMA1_Stream4, ENABLE);
}
}

回帖(5)

王兵

2018-10-26 08:56:35
将上述初始化功能复用到USART1,USART1可以实现数据的接收与发送。
莫非UART4不能使用DMA发送?
举报

王兵

2018-10-26 09:02:54
本帖最后由 mariawin 于 2014-12-4 16:54 编辑

已解决。
该问题是由于IO口初始化造成的,将IO口初始变更为如下情况,就可以解决:

// 串口IO口配置
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
GPIO_Init(GPIOC, &GPIO_InitStructure);
        
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;
GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_UART4);        
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_UART4);

F103 上合起来初始化也是可以的,F407的USART1合起来也可以,但不知道为什么这个不行。
为了防止类似情况发生,以后还是一步步来吧。
举报

陈嘉宁

2018-10-26 09:19:30
解决了就好
举报

孙婷婷

2018-10-26 09:36:22
楼主把发送和接收的IO设置一样了。IO接收的要设置为输入,发送的要设置为输出。
举报

张永强

2018-10-26 09:50:36
引用: TOPCB 发表于 2018-10-26 13:42
楼主把发送和接收的IO设置一样了。IO接收的要设置为输入,发送的要设置为输出。

楼主用的407的,设置方法和103的有点区别,你可以试试407
举报

更多回帖

发帖
×
20
完善资料,
赚取积分