硬件平台: stm32f407
库文件:STM32F4xx_DSP_StdPeriph_Lib_V1.6.1
串口: USART6 TX & RX
STM32F4有两个DMA控制器,挂载在AHB总线上,每一个DMA控制器有八个stream,每一个stream有八个channel。
一个channel可以不同时使用多个stream,一个stream不能同时使用多个channel。
发送数据:
1. 当DMA发送使能,且数据缓冲区有数据则一直发送数据
2.DMA发送完成后产生发送完成中断,需要清除发送完成标志位,如不需要再次发送数据则需要关闭发送通道
3.重新对数据缓冲区写入数据,开启发送通道进行下一次发送
接收数据:
当DMA配置好之后,一直在等待接收数据,外设数据进入接收数据缓冲区。当数据流断流之后产生串口空闲中断。此时需要关闭相关接收通道,清除接收标志位,读取接收到的数据。开启通道等待下一次接收(请求一次DMA接收)
GPIO初始化:
//USART6 PC6 PC7
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_OType = GPIO_OType_OD;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpio.GPIO_Speed = GPIO_Speed_25MHz;
gpio.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_Init(GPIOC,&gpio);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_USART6);
串口初始化:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
usart.USART_BaudRate = 115200;
usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usart.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
usart.USART_Parity = USART_Parity_No;
usart.USART_StopBits = USART_StopBits_1;
usart.USART_WordLength = USART_WordLength_8b;
USART_Init(USART6,&usart);
USART_Cmd(USART6,ENABLE);
USART_ITConfig(USART6, USART_IT_IDLE, ENABLE);
DMA初始化:
DMA_DeInit(DMA2_Stream1);
DMA_DeInit(DMA2_Stream6);//将stream设置为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART6->DR);
DMA_InitStructure.DMA_BufferSize = 8;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOStatus_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//USART6 DMA收
DMA_InitStructure.DMA_Channel = DMA_Channel_5;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&(bspdata.usart_rxbuffer);
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,ENABLE);
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
//USART6 DMA发
DMA_InitStructure.DMA_Channel = DMA_Channel_5;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&(bspdata.usart_txbuffer);
DMA_ITConfig(DMA2_Stream6, DMA_IT_TC,ENABLE);
DMA_Init(DMA2_Stream6, &DMA_InitStructure);
串口DMA接收和发送初始化
NVIC初始化:
nvic.NVIC_IRQChannel = DMA2_Stream1_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority =0;
nvic.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init(&nvic);
nvic.NVIC_IRQChannel = DMA2_Stream6_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority =1;
nvic.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init(&nvic);
中断管理器里面设置DMA中断优先级
中断服务函数:
void DMA2_Stream1_IRQHandler(void)
{
if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1) != RESET)
{
PDout(8) = 1;
PDout(9) = 1;
PDout(10) = 1;
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
for(i=0;i<8;i++)
{
bspdata.usart_txbuffer[i] = bspdata.usart_rxbuffer[i];
//bspdata.usart_rxbuffer[i] = 0;
}
flag=1;
}
DMA_ClearFlag(DMA2_Stream1,DMA_IT_TCIF1);
}
void DMA2_Stream6_IRQHandler(void)
{
if(DMA_GetITStatus(DMA2_Stream6, DMA_IT_TCIF6) != RESET)
{
PDout(8) = 0;
PDout(9) = 0;
PDout(10) = 0;
DMA_ClearITPendingBit(DMA2_Stream6, DMA_IT_TCIF6);
}
}
中断服务函数里面清除相关标志位