|
配置是抄串口1DMA中断例程的,只是把串口1配置成串口4,目前串口能够正常收发,但是用DMA就一点反应都没,每次收发时while ((DMA_GetCmdStatus(USARTx_TX_DMA_STREAM) != ENABLE) && ( Timeout > 0))这句话都是超时的,请版主帮忙看下会是啥原因引起的
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* 串口4 TX = PA0 RX = PA1 */
/* 第1步: 配置GPIO */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); /* 打开 GPIO 时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); /* 打开 UART 时钟 */
RCC_APB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); /* 打开 DMA1 时钟 */
//此为打开AF复用时钟,与m3有区别,只配置复用的引脚,且只能一个引脚一个引脚配置
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_UART4); /* 将 PA0 映射为 USART4_TX */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_UART4); /* 将 PA1 映射为 USART4_RX */
/* 配置 USART Tx 为复用功能 */
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_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置 USART Rx 为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第2步: 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = 115200;//460800; /* 波特率 */
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_Init(UART4, &USART_InitStructure);
/* Enable the USARTx Interrupt */
USART_Cmd(UART4, ENABLE); /* 使能串口 */
/* 使能 USART DMA RX 请求 */
USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);
/* 使能 USART DMA TX 请求 */
USART_DMACmd(UART4, USART_DMAReq_Tx, ENABLE);
/* 使能发送传输完成中断 */
DMA_ITConfig(USARTx_TX_DMA_STREAM, DMA_IT_TC, ENABLE);
/* 使能接收传输完成中断 */
DMA_ITConfig(USARTx_RX_DMA_STREAM, DMA_IT_TC, ENABLE);
/* 使能 DMA Stream 中断通道 */
NVIC_InitStructure.NVIC_IRQChannel = USARTx_DMA_TX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 使能 DMA Stream 中断通道 */
NVIC_InitStructure.NVIC_IRQChannel = USARTx_DMA_RX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
void USART_DMA_RxConfig(unsigned int *BufferDST, unsigned int BufferSize)
{
DMA_InitTypeDef DMA_InitStructure;
__IO uint32_t Timeout = TIMEOUT_MAX;
/*
使能前检测DMA是否被禁止。
请注意,在使用相同数据流的多次传输时,这一步很有用:使能,然后禁止,然后使能
..... 在这种情况下,只有在数据传输结束的时候,DMA的禁止才有效,在确保使能位被
硬件清除之前做确认是不可能的,如果DMA传输只做一次,这一步可以忽略。
*/
DMA_Cmd(USARTx_RX_DMA_STREAM, DISABLE);
while (DMA_GetCmdStatus(USARTx_RX_DMA_STREAM) != DISABLE)
{
}
DMA_InitStructure.DMA_BufferSize = BufferSize; /* 配置DMA大小 */
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; /* 在这个程序里面使能或者禁止都可以的 */
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; /* 设置阀值 */
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ; /* 设置内存为单字节突发模式 */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;/* 设置内存数据的位宽是字节 */
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /* 使能地址自增 */
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; /* 设置DMA是正常模式 */
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(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; /* 设置优先级 */
/* 配置 RX DMA */
DMA_InitStructure.DMA_Channel = USARTx_RX_DMA_CHANNEL ; /* 配置接收通道 */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ; /* 设置从外设到内存 */
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)BufferDST ; /* 设置内存地址 */
DMA_Init(USARTx_RX_DMA_STREAM,&DMA_InitStructure);
/* 使能 DMA USART TX Stream */
DMA_Cmd(USARTx_RX_DMA_STREAM, ENABLE);
/*
检测DMA Stream 是否被正确的使能.如果DMA的参数配置错误了,那么DMA Stream
的使能位会被硬件清除掉,从而使得传输停止比如FIFO的阀值配置错误
*/
Timeout = TIMEOUT_MAX;
while ((DMA_GetCmdStatus(USARTx_RX_DMA_STREAM) != ENABLE) && (Timeout > 0))
{
Timeout--;
}
/* 检测是否超时 */
if (Timeout == 0)
{
/* 处理错误 */
//TimeOut_UserCallback();
}
}
void USART_DMA_TxConfig(unsigned int *BufferSRC, unsigned int BufferSize)
{
DMA_InitTypeDef DMA_InitStructure;
__IO uint32_t Timeout = TIMEOUT_MAX;
/* 复位 DMA Stream 寄存器 (用于调试目的) */
/* DMA_DeInit(USARTx_TX_DMA_STREAM); */
/*
使能前检测DMA是否被禁止。
请注意,在使用相同数据流的多次传输时,这一步很有用:使能,然后禁止,然后使能
..... 在这种情况下,只有在数据传输结束的时候,DMA的禁止才有效,在确保使能位被
硬件清除之前做确认是不可能的,如果DMA传输只做一次,这一步可以忽略。
*/
DMA_Cmd(USARTx_TX_DMA_STREAM, DISABLE);
while (DMA_GetCmdStatus(USARTx_TX_DMA_STREAM) != DISABLE)
{
}
DMA_InitStructure.DMA_BufferSize = BufferSize;/* 配置DMA大小 */
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; /* 在这个程序里面使能或者禁止都可以的 */
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; /* 设置阀值 */
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ; /* 设置内存为单字节突发模式 */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; /* 设置内存数据的位宽是字节 */
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /* 使能地址自增 */
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; /* 设置DMA是正常模式 */
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(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; /* 设置优先级 */
/* 配置 TX DMA */
DMA_InitStructure.DMA_Channel = USARTx_TX_DMA_CHANNEL ; /* 配置发送通道 */
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral ; /* 设置从内存到外设 */
DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)BufferSRC ; /* 设置内存地址 */
DMA_Init(USARTx_TX_DMA_STREAM,&DMA_InitStructure);
/* 使能 DMA USART TX Stream */
DMA_Cmd(USARTx_TX_DMA_STREAM, ENABLE);
/*
检测DMA Stream 是否被正确的使能.如果DMA的参数配置错误了,那么DMA Stream
的使能位会被硬件清除掉,从而使得传输停止比如FIFO的阀值配置错误
*/
Timeout = TIMEOUT_MAX;
while ((DMA_GetCmdStatus(USARTx_TX_DMA_STREAM) != ENABLE) && ( Timeout > 0))
{
Timeout--;
}
/* 检测是否超时 */
if (Timeout == 0)
{
/* 处理错误 */
//TimeOut_UserCallback();
}
}
通道宏定义
#define USARTx_DMA DMA1
#define USARTx_DMAx_CLK RCC_AHB1Periph_DMA1
#define USARTx_TX_DMA_CHANNEL DMA_Channel_4
#define USARTx_TX_DMA_STREAM DMA1_Stream4
#define USARTx_TX_DMA_FLAG_FEIF DMA_FLAG_FEIF4
#define USARTx_TX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF4
#define USARTx_TX_DMA_FLAG_TEIF DMA_FLAG_TEIF4
#define USARTx_TX_DMA_FLAG_HTIF DMA_FLAG_HTIF4
#define USARTx_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF4
#define USARTx_RX_DMA_CHANNEL DMA_Channel_4
#define USARTx_RX_DMA_STREAM DMA1_Stream2
#define USARTx_RX_DMA_FLAG_FEIF DMA_FLAG_FEIF2
#define USARTx_RX_DMA_FLAG_DMEIF DMA_FLAG_DMEIF2
#define USARTx_RX_DMA_FLAG_TEIF DMA_FLAG_TEIF2
#define USARTx_RX_DMA_FLAG_HTIF DMA_FLAG_HTIF2
#define USARTx_RX_DMA_FLAG_TCIF DMA_FLAG_TCIF2
#define USARTx_DMA_TX_IRQn DMA1_Stream4_IRQn
#define USARTx_DMA_RX_IRQn DMA1_Stream2_IRQn
#define USARTx_DMA_TX_IRQHandler DMA1_Stream4_IRQHandler
#define USARTx_DMA_RX_IRQHandler DMA1_Stream2_IRQHandler
操作方式
USART_DMA_RxConfig((u32*)uc_ReadBuf, 1);
USART_DMA_TxConfig((u32*)uc_ReadBuf, 1); |
|