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

猜你喜欢

转载自www.cnblogs.com/schoolmate-li/p/10876835.html