DMA使用

文章详细介绍了GD32F30x单片机中DMA0Channel0、3和4的配置,涉及内存到内存传输、内存到外设发送和外设到内存接收的功能,以及中断处理和USART通信的集成。

 内存到内存(dma基础配置)

#include "gd32f30x.h" 

void DMA0_Channel0_IRQHandler(){
    if( dma_interrupt_flag_get(DMA0,DMA_CH0,DMA_INT_FLAG_FTF) ){
        dma_interrupt_flag_clear(DMA0,DMA_CH0,DMA_INT_FLAG_FTF);
    }
}
    
int main(){
    static const unsigned char data0[10] = {1,2,3,4,5,6,7,8,9,10};
    unsigned char data1[10] = {0};

    rcu_periph_clock_enable(RCU_DMA0);
    dma_deinit(DMA0,DMA_CH0);
    dma_memory_to_memory_enable(DMA0,DMA_CH0);
    
    dma_parameter_struct dmaCfg;
    dma_struct_para_init(&dmaCfg);
    dmaCfg.periph_addr  = data0;
    dmaCfg.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; 
    dmaCfg.periph_inc   = DMA_PERIPH_INCREASE_ENABLE;
    dmaCfg.memory_addr  = data1;
    dmaCfg.memory_width = DMA_PERIPHERAL_WIDTH_8BIT;
    dmaCfg.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dmaCfg.number       = 10;
    dmaCfg.direction    = DMA_PERIPHERAL_TO_MEMORY;
    dmaCfg.priority     = DMA_PRIORITY_LOW;
    dma_init(DMA0,DMA_CH0,&dmaCfg);
    
    dma_interrupt_enable(DMA0,DMA_CH0,DMA_INT_FLAG_FTF);
    nvic_irq_enable(DMA0_Channel0_IRQn,2,2);
    
    dma_circulation_enable(DMA0,DMA_CH0);
    dma_channel_enable(DMA0,DMA_CH0);
    
    while(1){
    }
    
    
}

内存到外设(发送)

#include "gd32f30x.h" 


dma_parameter_struct dmaTxCfg;

volatile int dmaSending = 0;
void DMA0_Channel3_IRQHandler(){
    if( dma_interrupt_flag_get(DMA0,DMA_CH3,DMA_INT_FLAG_FTF) ){
        dma_interrupt_flag_clear(DMA0,DMA_CH3,DMA_INT_FLAG_FTF);
        dmaSending = 0;
    }
}

void UsartDmaSend(unsigned char* pData, int nLen){
    while( dmaSending );
    dmaSending = 1;
    dma_channel_disable(DMA0,DMA_CH3);
    dmaTxCfg.memory_addr  = pData;
    dmaTxCfg.number       = nLen;
    dma_init(DMA0,DMA_CH3,&dmaTxCfg);
    dma_channel_enable(DMA0,DMA_CH3);
}


void UsartDmaCfg(){
    rcu_periph_clock_enable(RCU_AF);
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_10MHZ,GPIO_PIN_9);
    
    rcu_periph_clock_enable(RCU_USART0);
    usart_deinit(USART0);
    usart_baudrate_set(USART0,115200);
    usart_parity_config(USART0,USART_PM_NONE);
    usart_word_length_set(USART0,USART_WL_8BIT);
    usart_stop_bit_set(USART0,USART_STB_1BIT);
    usart_transmit_config(USART0,USART_TRANSMIT_ENABLE);
    usart_dma_transmit_config(USART0,USART_TRANSMIT_DMA_ENABLE);//重点
    usart_enable(USART0);
    
    rcu_periph_clock_enable(RCU_DMA0);
    dma_deinit(DMA0,DMA_CH3);

    dma_struct_para_init(&dmaTxCfg);
    dmaTxCfg.periph_addr  = USART0+0x04;
    dmaTxCfg.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; 
    dmaTxCfg.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
    dmaTxCfg.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dmaTxCfg.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dmaTxCfg.direction    = DMA_MEMORY_TO_PERIPHERAL;
    dmaTxCfg.priority     = DMA_PRIORITY_LOW;
    
    dma_interrupt_enable(DMA0,DMA_CH3,DMA_INT_FTF);
    nvic_irq_enable(DMA0_Channel3_IRQn,2,2);
    dma_init(DMA0,DMA_CH3,&dmaTxCfg);

}


int main(){

    UsartDmaCfg();
    while(1){
        UsartDmaSend("123",3);
    }
    
    
}

外设到内存(接收)

#include "gd32f30x.h" 

dma_parameter_struct dmaTxCfg;
dma_parameter_struct dmaRxCfg;

volatile int dmaSending = 0;
void DMA0_Channel3_IRQHandler(){
    if( dma_interrupt_flag_get(DMA0,DMA_CH3,DMA_INT_FLAG_FTF) ){
        dma_interrupt_flag_clear(DMA0,DMA_CH3,DMA_INT_FLAG_FTF);
        dmaSending = 0;
    }
}
void UsartDmaSend(unsigned char* pData, int nLen){
    dmaSending = 1;    
    dma_channel_disable(DMA0,DMA_CH3);
    dmaTxCfg.memory_addr  = pData;
    dmaTxCfg.number       = nLen;
    dma_init(DMA0,DMA_CH3,&dmaTxCfg);
    dma_channel_enable(DMA0,DMA_CH3);
    while( dmaSending );
}
#define RECV_BUF_LEN  128
unsigned char UsartReceiveBuffer[RECV_BUF_LEN]={0};
void DMA0_Channel4_IRQHandler(){
    if( dma_interrupt_flag_get(DMA0,DMA_CH4,DMA_INT_FLAG_FTF) ){
        dma_interrupt_flag_clear(DMA0,DMA_CH4,DMA_INT_FLAG_FTF);
        
        dma_channel_disable(DMA0,DMA_CH4);
        dma_init(DMA0,DMA_CH4,&dmaRxCfg);
        dma_channel_enable(DMA0,DMA_CH4);//关掉再开启,达到循环接收(或使用循环模式(不推荐))
        
        UsartDmaSend(UsartReceiveBuffer,RECV_BUF_LEN);//收满128个再发
    }
}
void USART0_IRQHandler(){
    if( usart_interrupt_flag_get(USART0,USART_INT_FLAG_IDLE) ){
        usart_interrupt_flag_clear(USART0,USART_INT_FLAG_IDLE);//不再有数据进来会触发空闲中断
        usart_data_receive(USART0);//触发空闲中断后读一下,否则会一直触发空闲中断
        
        int n = RECV_BUF_LEN - dma_transfer_number_get(DMA0,DMA_CH4);//从number向下计数
        
        dma_channel_disable(DMA0,DMA_CH4);
        dma_init(DMA0,DMA_CH4,&dmaRxCfg);
        dma_channel_enable(DMA0,DMA_CH4);
        
        UsartDmaSend(UsartReceiveBuffer,n);
    }
}
void UsartDmaCfg(){
    rcu_periph_clock_enable(RCU_AF);
    rcu_periph_clock_enable(RCU_GPIOB);
    gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_10MHZ,GPIO_PIN_6);
    gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_10MHZ,GPIO_PIN_7);
    gpio_pin_remap_config(GPIO_USART0_REMAP,ENABLE);
    
    rcu_periph_clock_enable(RCU_USART0);
    usart_deinit(USART0);
    usart_baudrate_set(USART0,115200);
    usart_parity_config(USART0,USART_PM_NONE);
    usart_word_length_set(USART0,USART_WL_8BIT);
    usart_stop_bit_set(USART0,USART_STB_1BIT);
    usart_transmit_config(USART0,USART_TRANSMIT_ENABLE);
    usart_receive_config(USART0,USART_RECEIVE_ENABLE);
    usart_dma_transmit_config(USART0,USART_TRANSMIT_DMA_ENABLE);
    usart_dma_receive_config(USART0,USART_RECEIVE_DMA_ENABLE);
    usart_interrupt_enable(USART0,USART_INT_IDLE);//使能空闲中断
    nvic_irq_enable(USART0_IRQn,2,2);
    usart_enable(USART0);
    
    rcu_periph_clock_enable(RCU_DMA0);
    dma_deinit(DMA0,DMA_CH3);
    dma_struct_para_init(&dmaTxCfg);
    dmaTxCfg.periph_addr  = USART0+0x04;
    dmaTxCfg.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; 
    dmaTxCfg.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
    dmaTxCfg.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dmaTxCfg.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dmaTxCfg.direction    = DMA_MEMORY_TO_PERIPHERAL;
    dmaTxCfg.priority     = DMA_PRIORITY_LOW;
    dma_interrupt_enable(DMA0,DMA_CH3,DMA_INT_FTF);
    nvic_irq_enable(DMA0_Channel3_IRQn,0,2);
//由于发送相关的中断服务函数中包含发送函数,会导致发送相关的函数中断无法执行,需将其抢断优先级调高
    dma_init(DMA0,DMA_CH3,&dmaTxCfg);
    
    dma_deinit(DMA0,DMA_CH4);
    dma_struct_para_init(&dmaRxCfg);
    dmaRxCfg.periph_addr  = USART0+0x04;
    dmaRxCfg.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; 
    dmaRxCfg.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
    dmaRxCfg.memory_addr  = UsartReceiveBuffer;
    dmaRxCfg.memory_width = DMA_MEMORY_WIDTH_8BIT;
    dmaRxCfg.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dmaRxCfg.number       = RECV_BUF_LEN;
    dmaRxCfg.direction    = DMA_PERIPHERAL_TO_MEMORY;
    dmaRxCfg.priority     = DMA_PRIORITY_LOW;
    dma_interrupt_enable(DMA0,DMA_CH4,DMA_INT_FTF);
    nvic_irq_enable(DMA0_Channel4_IRQn,2,2);
    dma_init(DMA0,DMA_CH4,&dmaRxCfg);
    dma_channel_enable(DMA0,DMA_CH4);//接收时一开始就要开启使能
}


int main(){

    UsartDmaCfg();
    while(1){
        //UsartDmaSend("123",3);
    }
    
    
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值