STM32F407的串口DMA收发数据----学习帖

       硬件平台: 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.重新对数据缓冲区写入数据,开启发送通道进行下一次发送

 

扫描二维码关注公众号,回复: 2119254 查看本文章

接收数据:

    当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);
  }
}
中断服务函数里面清除相关标志位


   

猜你喜欢

转载自blog.csdn.net/qq_22272261/article/details/65937928