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;
}