GD32单片机串口DMA配置教程

一:DMA串口配置步骤

1.使能三个时钟:

        GPIO时钟,串口时钟,DMA时钟

2.配置GPIO管脚状态:

        TX和RX:上拉复用推挽输出

3.配置串口基本参数:

        波特率,数据位,发送接收使能

4.配置串口空闲中断:

         空闲中断处理接收数据

5.配置DMA通道参数:

        内存地址,外设地址,自增模式,搬运方向,DMA号,通道号,优先级

6.配置DMA中断

二:定义一个缓冲区:

定义一个缓冲区,将DMA搬运地址指向该缓冲区,开启DMA搬运,开始串口数据发送。

三:串口0配置:

// USART0

#define BSP_USART0_CLK                    RCU_USART0
#define BSP_USART0_TX_PIN                 GPIO_PIN_6
#define BSP_USART0_RX_PIN                 GPIO_PIN_7
#define BSP_USART0_GPIO_CLK               RCU_GPIOB
#define BSP_USART0_GPIO_PORT              GPIOB
#define BSP_USART0_AF                     GPIO_AF_7

#define BSP_USART0_DMA_CLK								RCU_DMA1
#define BSP_USART0_DMA_PERI								DMA1
#define BSP_USART0_DMA_CH									DMA_CH2
#define BSP_USART0_DMA_PERI_NO						DMA_SUBPERI4
#define BSP_USART0_BAUD										115200
#define BSP_USART0_REV_BUFF_ADDR					(uint32_t *)&g_stUart0Buff
#define BSP_USART0_TX_DMA_EN							0
#define BSP_USART0_TX_DMA_CH							DMA_CH7
#define BSP_USART0_TX_DMA_PERI_NO					DMA_SUBPERI4
#define BSP_USART0_TX_BUFF_ADDR						(uint32_t *)&g_stUart0TxBuff

初始化代码:

int BSP_USARTx_DMA_Init(uint8_t index)
{

	ST_UART_BUFF *pUartRevBuf = (ST_UART_BUFF *)g_stBsp_USARTx_Param[index].pUSARTx_Rev_Buff_Addr;			//串口DMA接收缓冲区
	ST_UART_TX_BUFF *pUartTxBuf = (ST_UART_TX_BUFF *)g_stBsp_USARTx_Param[index].pUSARTx_Send_Buff_Addr;	//DMA串口数据发送缓冲区

	if(s_szUartInitTab[index] == 0x5A)		//串口初始化标志位
	{
		return -1;
	}
	s_szUartInitTab[index] = 0x5A;
	
	memset(pUartRevBuf,0,sizeof(ST_UART_BUFF));
	
  /* 时钟使能 */
  rcu_periph_clock_enable( g_stBsp_USARTx_Param[index].USARTx_Gpio_Clk );	//串口管脚时钟使能
  rcu_periph_clock_enable(g_stBsp_USARTx_Param[index].USARTx_Clk);			//串口时钟使能
  rcu_periph_clock_enable(g_stBsp_USARTx_Param[index].USARTx_Dma_Clk); 		//DMA时钟使能

  /* 管脚配置 */
  gpio_af_set(g_stBsp_USARTx_Param[index].USARTx_Gpio_Port, g_stBsp_USARTx_Param[index].USARTx_Func_No, g_stBsp_USARTx_Param[index].USARTx_Tx_Pin);	//串口输入输出管脚配置
  gpio_af_set(g_stBsp_USARTx_Param[index].USARTx_Gpio_Port, g_stBsp_USARTx_Param[index].USARTx_Func_No, g_stBsp_USARTx_Param[index].USARTx_Rx_Pin);//复用
  gpio_mode_set(g_stBsp_USARTx_Param[index].USARTx_Gpio_Port, GPIO_MODE_AF, GPIO_PUPD_PULLUP,g_stBsp_USARTx_Param[index].USARTx_Tx_Pin);//模式
  gpio_output_options_set(g_stBsp_USARTx_Param[index].USARTx_Gpio_Port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,g_stBsp_USARTx_Param[index].USARTx_Tx_Pin);//输出选择
  gpio_mode_set(g_stBsp_USARTx_Param[index].USARTx_Gpio_Port, GPIO_MODE_AF, GPIO_PUPD_PULLUP,g_stBsp_USARTx_Param[index].USARTx_Rx_Pin);
  gpio_output_options_set(g_stBsp_USARTx_Param[index].USARTx_Gpio_Port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,g_stBsp_USARTx_Param[index].USARTx_Rx_Pin);

  /* 串口基本配置 */
  usart_deinit(g_stBsp_USARTx_Param[index].USARTx_Periph);//去初始化
  usart_baudrate_set(g_stBsp_USARTx_Param[index].USARTx_Periph,g_stBsp_USARTx_Param[index].USARTx_Baud);//波特率
  usart_receive_config(g_stBsp_USARTx_Param[index].USARTx_Periph, USART_RECEIVE_ENABLE);//使能接收
  usart_transmit_config(g_stBsp_USARTx_Param[index].USARTx_Periph, USART_TRANSMIT_ENABLE);//使能发送
  
  /* 中断配置 */
  nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);//中断优先级分组
  nvic_irq_enable(g_stBsp_USARTx_Param[index].USARTx_Nvic_Irq, 0, 0);//串口中断优先级配置
  usart_interrupt_enable(g_stBsp_USARTx_Param[index].USARTx_Periph, USART_INTEN_IDLEIE);//串口中断使能

	usart_enable(g_stBsp_USARTx_Param[index].USARTx_Periph);//串口使能
	
	dma_interrupt_flag_clear(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Dma_Channel, DMA_INTC_FEEIFC|DMA_INTC_SDEIFC|DMA_INTC_TAEIFC|DMA_INTC_HTFIFC|DMA_INTC_FTFIFC);//中断标志位清除	

  /* DMA配置 */
	dma_single_data_parameter_struct dma_init_struct;				//DMA通道配置
  dma_deinit(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Dma_Channel);//去初始化
	
  dma_init_struct.direction            = DMA_PERIPH_TO_MEMORY;
  dma_init_struct.memory0_addr         = (uint32_t)(pUartRevBuf->DataBuf);  
  dma_init_struct.memory_inc           = DMA_MEMORY_INCREASE_ENABLE;
  dma_init_struct.periph_memory_width  = DMA_PERIPH_WIDTH_8BIT;
  dma_init_struct.number               = MAX_SIZE_OF_USART_BUFFER;
  dma_init_struct.periph_addr          = (g_stBsp_USARTx_Param[index].USARTx_Periph+0x04);
  dma_init_struct.circular_mode        = DMA_CIRCULAR_MODE_ENABLE;
  dma_init_struct.periph_inc           = DMA_PERIPH_INCREASE_DISABLE;
  dma_init_struct.priority             = DMA_PRIORITY_ULTRA_HIGH;		//通道优先级
  
  dma_single_data_mode_init(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Dma_Channel, dma_init_struct);//初始化DMA通道
  dma_circulation_enable(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Dma_Channel);
  dma_channel_subperipheral_select(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Dma_Channel, g_stBsp_USARTx_Param[index].USARTx_Dma_Sub_Periph);
  nvic_irq_enable(g_stBsp_USARTx_Param[index].DMAx_Chx_Nvic_Irq, 0, 0);//DMA中断优先级配置
  dma_interrupt_enable(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Dma_Channel,DMA_CHXCTL_FTFIE);//DMA中断使能
  dma_channel_enable(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Dma_Channel);//DMA通道使能		 
  usart_dma_receive_config(g_stBsp_USARTx_Param[index].USARTx_Periph, USART_DENR_ENABLE);//串口DMA接收使能

	if(1 == g_stBsp_USARTx_Param[index].USARTx_DMA_Send_En)		//串口DMA发送使能
	{

		printf("Uart Index %u Tx Dma Init\r\n", index);
		dma_interrupt_flag_clear(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Channel, DMA_INTC_FEEIFC|DMA_INTC_SDEIFC|DMA_INTC_TAEIFC|DMA_INTC_HTFIFC|DMA_INTC_FTFIFC);	

	  dma_deinit(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Channel);//串口DMA去初始化

		dma_init_struct.direction           = DMA_MEMORY_TO_PERIPH;				//DMA方向
	  dma_init_struct.memory0_addr        = (uint32_t)(pUartTxBuf->DataBuf);  	//内存地址
	  dma_init_struct.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;			//内存自增模式
	  dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;				//数据位宽
	  dma_init_struct.number              = C_LO_BUFFER_SIZE;					//数据长度
	  dma_init_struct.periph_addr         = (g_stBsp_USARTx_Param[index].USARTx_Periph+0x04);	//外设地址
		dma_init_struct.circular_mode       = DMA_CIRCULAR_MODE_DISABLE;		//循环搬运模式
	  dma_init_struct.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;		//外设自增模式
	  dma_init_struct.priority            = DMA_PRIORITY_ULTRA_HIGH;			//DMA通道优先级

		dma_single_data_mode_init(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Channel, dma_init_struct);//初始化DMA通道
	  dma_circulation_disable(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Channel);
	  dma_channel_subperipheral_select(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Channel, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Sub_Periph);


	  nvic_irq_enable(g_stBsp_USARTx_Param[index].DMAx_Chx_Tx_Nvic_Irq, 0, 0);//串口DMA发送中断优先级配置
		dma_interrupt_enable(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Channel,DMA_CHXCTL_FTFIE);//DMA中断使能
		
		/* enable USARTx DMA channel reception */
	  dma_channel_disable(g_stBsp_USARTx_Param[index].USARTx_Dma_Periph, g_stBsp_USARTx_Param[index].USARTx_Tx_Dma_Channel);		 
	  usart_dma_transmit_config(g_stBsp_USARTx_Param[index].USARTx_Periph, USART_DENT_DISABLE);//串口DMA发送使能
	}

	return 0;
}

物联沃分享整理
物联沃-IOTWORD物联网 » GD32单片机串口DMA配置教程

发表评论