GD32F450的串口DMA收发+接受完成中断
Posted schoolmate-li
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GD32F450的串口DMA收发+接受完成中断相关的知识,希望对你有一定的参考价值。
GD32的库比较糟糕当时完全是参考STM32的驱动来的,当然我也知道直接用ST的库可以,但是原因比较特殊就不多说了。
代码就不贴了,以后用GD的机会我想不会太多。
先初始化串口,使能串口,使能接受完成中断。
再初始化DMA通道。贴一段
1 int fputc(int ch, FILE *f) 2 { 3 usart_data_transmit(USART0, (uint8_t)ch); 4 while(RESET == usart_flag_get(USART0, USART_FLAG_TBE)); 5 return ch; 6 }
1 void uart0_dma_config(void) 2 { 3 dma_single_data_parameter_struct dma_init_struct; 4 /* enable DMA1 */ 5 rcu_periph_clock_enable(RCU_DMA1); 6 /* deinitialize DMA channel7(USART0 tx) */ 7 dma_deinit(DMA1, DMA_CH7); 8 dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; 9 dma_init_struct.memory0_addr = (uint32_t)tx_buffer0; 10 dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; 11 dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT; 12 dma_init_struct.number = TXBUFF_SIZE; 13 dma_init_struct.periph_addr = USART0_DATA_ADDRESS; 14 dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; 15 dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; 16 dma_single_data_mode_init(DMA1, DMA_CH7, dma_init_struct); 17 /* configure DMA mode */ 18 dma_circulation_disable(DMA1, DMA_CH7); 19 dma_channel_subperipheral_select(DMA1, DMA_CH7, DMA_SUBPERI4); 20 21 dma_deinit(DMA1, DMA_CH2); 22 dma_init_struct.direction = DMA_PERIPH_TO_MEMORY; 23 dma_init_struct.memory0_addr = (uint32_t)rx_buffer0; 24 dma_init_struct.number = RXBUFF_SIZE; 25 dma_single_data_mode_init(DMA1, DMA_CH2, dma_init_struct); 26 /* configure DMA mode */ 27 dma_circulation_disable(DMA1, DMA_CH2); 28 dma_channel_subperipheral_select(DMA1, DMA_CH2, DMA_SUBPERI4); 29 30 dma_channel_enable(DMA1, DMA_CH2);//UART0 RX 31 32 usart_dma_receive_config(USART0, USART_DENR_ENABLE); 33 34 // nvic_irq_enable(DMA1_Channel2_IRQn, 3, 0); 35 // dma_interrupt_enable(DMA1,DMA_CH2,DMA_CHXCTL_FTFIE); 36 }
#define USART0_DATA_ADDRESS ((uint32_t)0x40011004)
其实里面的USART0_DATA_ADDRESS,就是串口0 的数据寄存器地址。
先看接收。
1 void USART1_IRQHandler(void) 2 { 3 uint32_t buff_length = 0; 4 if((RESET != usart_interrupt_flag_get(USART1, USART_INT_IDLEIE)) && 5 (RESET != usart_flag_get(USART1, USART_FLAG_IDLEF))) 6 { 7 usart_data_receive(USART1); 8 buff_length = RXBUFF_SIZE - DMA_CHCNT(DMA0,DMA_CH5); 9 // UART_TRANSMIT(USART1,rx_buffer1,buff_length); 10 // UART_DMA_TRANSMIT(USART1,rx_buffer1,buff_length); 11 // while(1) 12 // if(dma_flag_get(DMA0,DMA_CH6,DMA_INTF_FTFIF)!=RESET)//µÈ´ýDMA2_Steam7´«ÊäÍê³É 13 // { 14 // dma_flag_clear(DMA0,DMA_CH6,DMA_INTF_FTFIF);//Çå³ýDMA2_Steam7´«ÊäÍê³É±êÖ¾ 15 // 16 // break; 17 // } 18 UART_DMA_TRANSMIT(UART3,rx_buffer1,buff_length); 19 while(1) 20 if(dma_flag_get(DMA0,DMA_CH4,DMA_INTF_FTFIF)!=RESET)//µÈ´ýDMA2_Steam7´«ÊäÍê³É 21 { 22 dma_flag_clear(DMA0,DMA_CH4,DMA_INTF_FTFIF);//Çå³ýDMA2_Steam7´«ÊäÍê³É±êÖ¾ 23 24 break; 25 } 26 dma_channel_disable(DMA0, DMA_CH5); 27 dma_flag_clear(DMA0,DMA_CH5,DMA_INTF_FTFIF);//Çå³ýDMA2_Steam7´«ÊäÍê³É±êÖ¾ 28 dma_channel_enable(DMA0, DMA_CH5); 29 } 30 else{ 31 uint32_t isrflags = USART_STAT0(USART1); 32 if((usart_interrupt_flag_get(USART1,USART_FLAG_PERR))!=RESET) 33 { 34 USART_DATA(USART1); 35 usart_flag_clear(USART1, USART_FLAG_PERR); 36 } 37 if((usart_interrupt_flag_get(USART1, USART_FLAG_FERR))!=RESET) 38 { 39 USART_DATA(USART1); 40 usart_flag_clear(USART1, USART_FLAG_FERR); 41 } 42 43 if((usart_interrupt_flag_get(USART1, USART_FLAG_NERR))!=RESET) 44 { 45 USART_DATA(USART1); 46 usart_flag_clear(USART1, USART_FLAG_NERR); 47 } 48 49 if((usart_interrupt_flag_get(USART1, USART_FLAG_ORERR))!=RESET) 50 { 51 USART_DATA(USART1);//ORE???,????CR 52 usart_flag_clear(USART1, USART_FLAG_ORERR); 53 } 54 } 55 }
数据当然是在DMA通道FIFO里,本次接收长度=总的FIFO长度-剩余接收长度。
然后发送这么长的数据。
清发送标志,关闭接受通道,清接收标志,再打开接收通道。
1 void UART_DMA_TRANSMIT(uint32_t usart_periph,uint8_t *DATA,uint32_t NUM) 2 { 3 if(usart_periph == USART0) 4 { 5 memcpy(tx_buffer0,DATA,NUM); 6 DMA_CHCNT(DMA1, DMA_CH7) = NUM; 7 dma_channel_enable(DMA1, DMA_CH7); 8 } 9 else if(usart_periph == USART1) 10 { 11 memcpy(tx_buffer1,DATA,NUM); 12 DMA_CHCNT(DMA0, DMA_CH6) = NUM; 13 dma_channel_enable(DMA0, DMA_CH6); 14 } 15 else if(usart_periph == USART2) 16 { 17 memcpy(tx_buffer2,DATA,NUM); 18 DMA_CHCNT(DMA0, DMA_CH3) = NUM; 19 dma_channel_enable(DMA0, DMA_CH3); 20 } 21 else if(usart_periph == UART3) 22 { 23 memcpy(tx_buffer3,DATA,NUM); 24 DMA_CHCNT(DMA0, DMA_CH4) = NUM; 25 dma_channel_enable(DMA0, DMA_CH4); 26 } 27 28 usart_dma_transmit_config(usart_periph, USART_DENT_ENABLE); 29 30 }
发送函数:把数放入通道FIFO,告诉通道数据长度,使能通道,调用一次发送。OK
以上是关于GD32F450的串口DMA收发+接受完成中断的主要内容,如果未能解决你的问题,请参考以下文章