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

1. 重点

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

2. 主要内容

2.1 需求

uint8_t data = 0x01;
串口发送(data);

实现串口的发送数据, 要求采用dma的方式

2.2 数据交互流程

  • CPU配置好DMA
  • CPU通知DMA干活
  • DMA请求源数据
  • DMA获取源数据
  • DMA将获取的源数据交给目标

2.3 开发流程

2.3.1 依赖引入

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

2.3.2 DMA初始化
/***************** DMA m2p *******************/
// 时钟
rcu_periph_clock_enable(RCU_DMA1);
// 重置dma
dma_deinit(DMA1, DMA_CH7);

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

 配置 dma 子连接
dma_channel_subperipheral_select(DMA1, DMA_CH7, DMA_SUBPERI4);
  • 配置时钟
  • 初始化dma通道
  • 配置dma与外设间的子链接
2.3.3 DMA传输请求
// 数据来源 和 长度
dma_memory_address_config(DMA1, DMA_CH7, DMA_MEMORY_0, (uint32_t)(&data));
dma_transfer_number_config(DMA1, DMA_CH7, len);

// 触发传输
dma_channel_enable(DMA1, DMA_CH7);

// 等待DMA传输完成
while(RESET == dma_flag_get(DMA1, DMA_CH7, DMA_FLAG_FTF));
// 清理标记
dma_flag_clear(DMA1, DMA_CH7, DMA_FLAG_FTF);
  • dma_channel_enable: 请求dma数据传输
  • DMA_FLAG_FTF:为传输完成标记
2.3.4 串口外设DMA开启
// DMA发送功能配置
usart_dma_transmit_config(usartx, USART_TRANSMIT_DMA_ENABLE);
  • 需要开启dma发送配置,才可以打开dam的功能
2.3.5 发送功能
static void dma_send_byte(uint8_t data) {
    // 数据来源 和 长度
    dma_memory_address_config(DMA1, DMA_CH7, DMA_MEMORY_0, (uint32_t)(&data));
    dma_transfer_number_config(DMA1, DMA_CH7, 1);

    // 触发传输
    dma_channel_enable(DMA1, DMA_CH7);

    // 等待DMA传输完成
    while(RESET == dma_flag_get(DMA1, DMA_CH7, DMA_FLAG_FTF));
    // 清理标记
    dma_flag_clear(DMA1, DMA_CH7, DMA_FLAG_FTF);
}
static void dma_send(uint8_t* data, uint32_t len) {
    // 数据来源 和 长度
    dma_memory_address_config(DMA1, DMA_CH7, DMA_MEMORY_0, (uint32_t)(&data));
    dma_transfer_number_config(DMA1, DMA_CH7, len);

    // 触发传输
    dma_channel_enable(DMA1, DMA_CH7);

    // 等待DMA传输完成
    while(RESET == dma_flag_get(DMA1, DMA_CH7, DMA_FLAG_FTF));
    // 清理标记
    dma_flag_clear(DMA1, DMA_CH7, DMA_FLAG_FTF);
}
static void dma_send_string(const char* str) {
    dma_send((uint8_t*)str, strlen(str));
}

3. 串口发送理解

3.1 源地址和目标地址

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

3.2 自增长

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

串口中,寄存器地址不变,大小不变,我们只是向这个里面放数据,所以不需要增长。

3.3 数据宽度

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

3.4 数据长度

传输了多少个数据宽度的数据。

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值