ARM32开发——(十七)DMA外设到内存

1. 重点

  • 加强理解DMA数据传输过程
  • 加强掌握DMA的初始化流程
  • 掌握DMA数据表查询
  • 理解源和目标的配置
  • 理解数据传输特点
  • 能够动态配置源数据

2. 主要内容

2.1 需求

uint8_t data;
串口接收(&data);

data有数据了

实现串口的数据接收,要求采用dma的方式。

2.2 数据交互流程

  • CPU配置好DMA
  • 外部数据发送给串口外设
  • 串口外设触发中断
  • CPU处理中断逻辑,通知DMA干活
  • DMA请求源数据
  • DMA获取源数据
  • DMA将获取的源数据交给目标

3. 开发流程

3.1 依赖引入

添加标准库中的gd32f4xx_dma.c文件

3.2 DMA初始化
/**************** DMA p2m *******************/
// 时钟
rcu_periph_clock_enable(RCU_DMA1);
// 重置dma
dma_deinit(DMA1, DMA_CH5);

 dma 配置
dma_single_data_parameter_struct dsdps;
dma_single_data_para_struct_init(&dsdps);
// 方向
dsdps.direction = DMA_PERIPH_TO_MEMORY;
// 内存: dst
dsdps.memory0_addr = (uint32_t)(g_recv_buff);
dsdps.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
// 外设: src
dsdps.periph_addr = (uint32_t)(&USART_DATA(USART0));
dsdps.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
// 数据长度
dsdps.number = USART_RECEIVE_LENGTH;
// dst数据宽度
dsdps.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
// 传输优先级
dsdps.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_single_data_mode_init(DMA1, DMA_CH5, &dsdps);

 配置 dma 子连接
dma_channel_subperipheral_select(DMA1, DMA_CH5, DMA_SUBPERI4);


// 默认开启接收
dma_flag_clear(DMA1, DMA_CH5, DMA_FLAG_FTF);
dma_channel_enable(DMA1, DMA_CH5);
  • 配置时钟
  • 初始化dma通道
  • 配置dma与外设间的子链接
  • 开启dma接收功能
3.3 接收中断
if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE) == SET) {
    //读取缓冲区,清空缓冲区
    usart_data_receive(USART0);

    // 停止DMA传输,防止数据污染
    dma_channel_disable(DMA1, DMA_CH5);

    // 计算接收的数据长度
    g_recv_length = USART_RECEIVE_LENGTH - dma_transfer_number_get(DMA1, DMA_CH5);
    if(g_recv_length) {
        g_recv_buff[g_recv_length] = '\0';
        // TODO: g_recv_buff为接收的数据,g_recv_length为接收的长度
        printf("rcv: %s\r\n", g_recv_buff);
    }

    g_recv_length = 0;
    dma_flag_clear(DMA1, DMA_CH5, DMA_FLAG_FTF);
    dma_channel_enable(DMA1, DMA_CH5);
}
  • dma_channel_enable: 请求dma数据传输
  • DMA_FLAG_FTF:为传输完成标记
3.4 串口外设DMA开启
// DMA接收功能配置
usart_dma_receive_config(usartx, USART_RECEIVE_DMA_ENABLE);
  • 需要开启dma接收配置,才可以打开dam的功能

4. 串口接收理解

4.1 地址和目标地址

源地址和目标地址都是提前配置好的,当传输时,就会从源地址将数据传递给目标地址。

4.2 自增长

每传输一个字节数据,地址是否需要增长。这里包含了源地址是否需要增长,也包含了目标地址是否需要增长。

  • 串口为数据源:寄存器地址不变,大小不变,我们只是从这里取数据,所以不需要增长。
  • 内存为目标:每一个字节都要放在独立的索引里,需要自增长。
4.3 数据宽度

数据宽度表示一次传递多上个bit。

4.4 数据长度

最大的传输字节数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值