YTM32B1M SDK解析03 - DMA数据传输系统

1. 概述

DMA(Direct Memory Access)是YTM32B1M微控制器中的高效数据传输系统,能够在不占用CPU资源的情况下,在内存与内存、内存与外设之间进行高速数据传输。本文档详细解析YTM32B1M SDK中DMA驱动的实现,包括传输配置、通道管理、中断处理等功能。

2. 文件组织结构

2.1 头文件

  • dma_driver.h: DMA驱动的主要头文件,定义了所有公共接口和数据结构

  • dma_irq.h: DMA中断处理相关头文件

  • dma_hw_access.h: DMA硬件访问层头文件

2.2 源文件

  • dma_driver.c: DMA驱动的主要实现文件

  • dma_irq.c: DMA中断服务程序实现

  • dma_hw_access.c: DMA硬件抽象层实现

2.3 架构层次

应用层
    ↓
dma_driver.h/c (高层API)
    ↓
dma_hw_access.h/c (硬件抽象层)
    ↓
DMA寄存器定义
    ↓
DMA硬件控制器

3. 核心数据结构解析

3.1 传输大小枚举

typedef enum {
    DMA_TRANSFER_SIZE_1B = 0x0U,    // 1字节传输
    DMA_TRANSFER_SIZE_2B = 0x1U,    // 2字节传输
    DMA_TRANSFER_SIZE_4B = 0x2U,    // 4字节传输
    DMA_TRANSFER_SIZE_8B = 0x3U,    // 8字节传输
    DMA_TRANSFER_SIZE_16B = 0x4U,   // 16字节传输
    DMA_TRANSFER_SIZE_32B = 0x5U,   // 32字节传输
    DMA_TRANSFER_SIZE_64B = 0x6U,   // 64字节传输
} dma_transfer_size_t;

3.2 传输类型枚举

typedef enum {
    DMA_TRANSFER_PERIPH2MEM = 0U,   // 外设到内存
    DMA_TRANSFER_MEM2PERIPH,        // 内存到外设
    DMA_TRANSFER_MEM2MEM,           // 内存到内存
    DMA_TRANSFER_PERIPH2PERIPH      // 外设到外设
} dma_transfer_type_t;

3.3 地址模运算枚举

typedef enum {
    DMA_MODULO_OFF = 0U,        // 关闭模运算
    DMA_MODULO_2B,              // 2字节模运算
    DMA_MODULO_4B,              // 4字节模运算
    DMA_MODULO_8B,              // 8字节模运算
    DMA_MODULO_16B,             // 16字节模运算
    DMA_MODULO_32B,             // 32字节模运算
    DMA_MODULO_64B,             // 64字节模运算
    // ... 更多模运算选项
    DMA_MODULO_2GB              // 2GB模运算
} dma_modulo_t;

3.4 通道中断类型

typedef enum {
    DMA_CHN_ERR_INT = 0U,           // 错误中断
    DMA_CHN_HALF_MAJOR_LOOP_INT,    // 半主循环中断
    DMA_CHN_MAJOR_LOOP_INT          // 完整主循环中断
} dma_channel_interrupt_t;

3.5 通道状态枚举

typedef enum {
    DMA_CHN_NORMAL = 0U,            // 通道正常状态
    DMA_CHN_ERROR                   // 通道错误状态
} dma_chn_status_t;

3.6 DMA用户配置结构

typedef struct {
    bool haltOnError;               // 错误时停止所有通道
} dma_user_config_t;

3.7 通道状态结构

typedef struct {
    uint8_t virtChn;                        // 虚拟通道号
    dma_callback_t callback;                // 回调函数指针
    void *parameter;                        // 回调函数参数
    volatile dma_chn_status_t status;       // 通道状态
} dma_chn_state_t;

3.8 通道配置结构

typedef struct {
    uint8_t virtChnConfig;                  // DMA虚拟通道号
    dma_request_source_t source;            // DMA请求源选择
    dma_callback_t callback;                // 通道回调函数
    void *callbackParam;                    // 回调函数参数
} dma_channel_config_t;

3.9 循环传输配置结构

typedef struct {
    uint32_t triggerLoopIterationCount;     // 触发循环迭代次数
    bool srcOffsetEnable;                   // 源地址偏移使能
    bool dstOffsetEnable;                   // 目标地址偏移使能
    int32_t triggerLoopOffset;              // 触发循环偏移量
    bool transferLoopChnLinkEnable;         // 传输循环通道链接使能
    uint8_t transferLoopChnLinkNumber;      // 传输循环链接通道号
    bool triggerLoopChnLinkEnable;          // 触发循环通道链接使能
    uint8_t triggerLoopChnLinkNumber;       // 触发循环链接通道号
} dma_loop_transfer_config_t;

3.10 传输配置结构

typedef struct {
    uint32_t srcAddr;                       // 源地址
    uint32_t destAddr;                      // 目标地址
    dma_transfer_size_t srcTransferSize;    // 源传输大小
    dma_transfer_size_t destTransferSize;   // 目标传输大小
    int16_t srcOffset;                      // 源地址偏移
    int16_t destOffset;                     // 目标地址偏移
    int32_t srcLastAddrAdjust;              // 源地址最后调整
    int32_t destLastAddrAdjust;             // 目标地址最后调整
    dma_modulo_t srcModulo;                 // 源地址模运算
    dma_modulo_t destModulo;                // 目标地址模运算
    uint32_t transferLoopByteCount;         // 传输循环字节数
    bool ramReloadEnable;                   // RAM重载使能
    uint32_t ramReloadNextDescAddr;         // 下一个描述符地址
    bool interruptEnable;                   // 中断使能
    dma_loop_transfer_config_t *loopTransferConfig; // 循环传输配置指针
} dma_transfer_config_t;

3.11 软件CTS结构

typedef struct {
    uint32_t SADDR;             // 源地址
    int16_t SOFF;               // 源偏移
    uint16_t ATTR;              // 传输属性
    uint32_t BCNT;              // 单次循环传输字节数
    int32_t STO;                // 源触发循环偏移
    uint32_t DADDR;             // 目标地址
    int16_t DOFF;               // 目标偏移
    uint16_t TCNT;              // 触发循环传输计数
    int32_t RAM_LOAD_ADDR;      // RAM加载地址
    uint16_t CSR;               // 控制/状态寄存器
    uint16_t TCNTRV;            // 触发循环计数器值
} dma_software_cts_t;

3.12 DMA状态结构

typedef struct {
    dma_chn_state_t *volatile virtChnState[FEATURE_DMA_VIRTUAL_CHANNELS]; // 通道状态指针数组
} dma_state_t;

4. DMA系统架构图

DMA请求源                    DMA控制器                    目标
┌─────────────┐             ┌─────────────┐             ┌─────────────┐
│   外设A     │────────────→│   通道0     │────────────→│    内存     │
│   (UART)    │             │             │             │             │
└─────────────┘             └─────────────┘             └─────────────┘

┌─────────────┐             ┌─────────────┐             ┌─────────────┐
│    内存     │────────────→│   通道1     │────────────→│   外设B     │
│             │             │             │             │   (SPI)     │
└─────────────┘             └─────────────┘             └─────────────┘

┌─────────────┐             ┌─────────────┐             ┌─────────────┐
│    内存A    │────────────→│   通道2     │────────────→│    内存B    │
│             │             │             │             │             │
└─────────────┘             └─────────────┘             └─────────────┘

                            ┌─────────────┐
                            │  中断控制   │
                            │             │
                            └─────────────┘
                                   │
                            ┌─────────────┐
                            │    CPU      │
                            │             │
                            └─────────────┘

5. 核心API接口详解

5.1 DMA模块初始化

status_t DMA_DRV_Init(dma_state_t *dmaState,
                      const dma_user_config_t *userConfig,
                      dma_chn_state_t *const chnStateArray[],
                      const dma_channel_config_t *const chnConfigArray[],
                      uint32_t chnCount);

功能: 初始化DMA模块和指定的通道 参数:

  • dmaState: DMA状态结构指针

  • userConfig: 用户配置结构指针

  • chnStateArray[]: 通道状态结构数组

  • chnConfigArray[]: 通道配置结构数组

  • chnCount: 要初始化的通道数量

5.2 DMA模块去初始化

status_t DMA_DRV_Deinit(void);

功能: 去初始化DMA模块,释放所有资源

5.3 通道管理接口

// 初始化DMA通道
status_t DMA_DRV_ChannelInit(dma_chn_state_t *dmaChannelState,
                             const dma_channel_config_t *dmaChannelConfig);

// 释放DMA通道
status_t DMA_DRV_ReleaseChannel(uint8_t virtualChannel);

// 启动DMA通道
status_t DMA_DRV_StartChannel(uint8_t virtualChannel);

// 停止DMA通道
status_t DMA_DRV_StopChannel(uint8_t virtualChannel);

5.4 传输配置接口

// 配置单块传输
status_t DMA_DRV_ConfigSingleBlockTransfer(uint8_t virtualChannel,
                                           dma_transfer_type_t type,
                                           uint32_t srcAddr,
                                           uint32_t destAddr,
                                           dma_transfer_size_t transferSize,
                                           uint32_t dataBufferSize);

// 配置多块传输
status_t DMA_DRV_ConfigMultiBlockTransfer(uint8_t virtualChannel,
                                          dma_transfer_type_t type,
                                          uint32_t srcAddr,
                                          uint32_t destAddr,
                                          dma_transfer_size_t transferSize,
                                          uint32_t blockSize,
                                          uint32_t blockCount,
                                          bool disableReqOnCompletion);

// 配置循环传输
status_t DMA_DRV_ConfigLoopTransfer(uint8_t virtualChannel,
                                    const dma_transfer_config_t *transferConfig);

// 配置RAM重载传输
status_t DMA_DRV_ConfigRamReloadTransfer(uint8_t virtualChannel,
                                         dma_software_cts_t *scts,
                                         dma_transfer_size_t transferSize,
                                         uint32_t bytesOnEachRequest,
                                         const dma_ram_reload_list_t *srcList,
                                         const dma_ram_reload_list_t *destList,
                                         uint8_t ctsCount);

5.5 地址和参数配置接口

// 设置源地址
void DMA_DRV_SetSrcAddr(uint8_t virtualChannel, uint32_t address);

// 设置源地址偏移
void DMA_DRV_SetSrcOffset(uint8_t virtualChannel, int16_t offset);

// 设置目标地址
void DMA_DRV_SetDestAddr(uint8_t virtualChannel, uint32_t address);

// 设置目标地址偏移
void DMA_DRV_SetDestOffset(uint8_t virtualChannel, int16_t offset);

// 设置传输大小
void DMA_DRV_SetSrcReadChunkSize(uint8_t virtualChannel, dma_transfer_size_t size);
void DMA_DRV_SetDestWriteChunkSize(uint8_t virtualChannel, dma_transfer_size_t size);

5.6 状态查询接口

// 获取通道状态
dma_chn_status_t DMA_DRV_GetChannelStatus(uint8_t virtualChannel);

// 获取剩余字节数
uint32_t DMA_DRV_GetRemainingMajorIterationsCount(uint8_t virtualChannel);

// 检查通道是否完成
bool DMA_DRV_ChannelIsDone(uint8_t virtualChannel);

6. 外设应用描述

6.1 DMA的主要应用场景

  1. 串口数据传输: UART接收/发送大量数据时使用DMA减少CPU负担

  2. SPI/I2C通信: 高速串行通信中的数据缓冲传输

  3. ADC数据采集: 连续采样数据的自动存储

  4. 内存拷贝: 大块内存数据的高效复制

  5. 外设间数据传输: 不经过CPU的外设间直接数据传输

6.2 典型应用示例

6.2.1 UART接收DMA配置
// DMA状态和配置
dma_state_t dmaState;
dma_chn_state_t dmaChannelState;
uint8_t rxBuffer[256];

// DMA用户配置
dma_user_config_t dmaUserConfig = {
    .haltOnError = false
};

// DMA通道配置
dma_channel_config_t dmaChannelConfig = {
    .virtChnConfig = 0,                     // 使用通道0
    .source = DMA_REQ_UART0_RX,            // UART0接收请求
    .callback = uartRxDmaCallback,          // 完成回调
    .callbackParam = NULL
};

// 初始化DMA
DMA_DRV_Init(&dmaState, &dmaUserConfig, &dmaChannelStatePtr, &dmaChannelConfigPtr, 1);

// 配置UART接收传输
DMA_DRV_ConfigSingleBlockTransfer(
    0,                                      // 通道0
    DMA_TRANSFER_PERIPH2MEM,               // 外设到内存
    (uint32_t)&UART0->DATA,                // 源地址:UART数据寄存器
    (uint32_t)rxBuffer,                    // 目标地址:接收缓冲区
    DMA_TRANSFER_SIZE_1B,                  // 1字节传输
    sizeof(rxBuffer)                       // 缓冲区大小
);

// 启动DMA传输
DMA_DRV_StartChannel(0);
6.2.2 内存到内存传输
uint32_t srcData[1024];
uint32_t destData[1024];

// 配置内存到内存传输
DMA_DRV_ConfigSingleBlockTransfer(
    1,                                      // 通道1
    DMA_TRANSFER_MEM2MEM,                  // 内存到内存
    (uint32_t)srcData,                     // 源地址
    (uint32_t)destData,                    // 目标地址
    DMA_TRANSFER_SIZE_4B,                  // 4字节传输
    sizeof(srcData)                        // 数据大小
);

// 启动传输
DMA_DRV_StartChannel(1);
6.2.3 循环缓冲区传输
// 循环传输配置
dma_loop_transfer_config_t loopConfig = {
    .triggerLoopIterationCount = 10,        // 10次触发循环
    .srcOffsetEnable = true,               // 源地址偏移使能
    .dstOffsetEnable = false,              // 目标地址偏移禁用
    .triggerLoopOffset = 0,                // 循环完成后偏移量
    .transferLoopChnLinkEnable = false,    // 传输循环链接禁用
    .triggerLoopChnLinkEnable = false      // 触发循环链接禁用
};

// 传输配置
dma_transfer_config_t transferConfig = {
    .srcAddr = (uint32_t)circularBuffer,
    .destAddr = (uint32_t)&ADC0->DATA,
    .srcTransferSize = DMA_TRANSFER_SIZE_2B,
    .destTransferSize = DMA_TRANSFER_SIZE_2B,
    .srcOffset = 2,                        // 每次传输后源地址+2
    .destOffset = 0,                       // 目标地址不变
    .transferLoopByteCount = 2,            // 每次传输2字节
    .interruptEnable = true,               // 使能中断
    .loopTransferConfig = &loopConfig
};

// 配置循环传输
DMA_DRV_ConfigLoopTransfer(2, &transferConfig);
6.2.4 DMA中断处理
void uartRxDmaCallback(void *parameter, dma_chn_status_t status)
{
    if (status == DMA_CHN_NORMAL) {
        // 传输完成,处理接收到的数据
        processReceivedData(rxBuffer, sizeof(rxBuffer));
        
        // 重新启动DMA传输
        DMA_DRV_StartChannel(0);
    } else {
        // 传输错误处理
        handleDmaError();
    }
}

7. 与数据手册的对应关系

根据YTM32B1ME0数据手册中的DMA章节:

  • DMA控制器: 支持多通道并行传输,每个通道独立配置

  • 传输控制结构(CTS): 对应SDK中的dma_software_cts_t结构

  • 请求路由: 通过DMAMUX模块将外设请求路由到DMA通道

  • 中断系统: 支持传输完成、半完成和错误中断

  • 地址生成: 支持线性地址、模运算地址等多种寻址模式

8. 最佳实践建议

  1. 内存对齐: 确保传输数据按照传输大小正确对齐

  2. 缓存一致性: 在有缓存的系统中注意数据一致性问题

  3. 中断优先级: 合理设置DMA中断优先级,避免影响实时性

  4. 错误处理: 实现完善的错误处理机制,包括超时和重试

  5. 资源管理: 及时释放不用的DMA通道,避免资源浪费

  6. 性能优化: 选择合适的传输大小和模式以获得最佳性能

9. 调试技巧

  1. 状态监控: 使用DMA_DRV_GetChannelStatus()监控通道状态

  2. 进度跟踪: 通过剩余计数器跟踪传输进度

  3. 寄存器检查: 在调试时检查DMA寄存器配置是否正确

  4. 中断调试: 确认中断服务程序正确注册和执行

  5. 时序分析: 使用逻辑分析仪分析DMA请求和响应时序

10. 总结

YTM32B1M的DMA系统提供了强大而灵活的数据传输能力,支持多种传输模式和丰富的配置选项。通过合理使用DMA,可以显著提高系统的数据处理效率,降低CPU负载,实现更好的实时性能。掌握DMA的配置和使用方法对于开发高性能嵌入式应用至关重要。


本文档基于YTM32B1M SDK v1.0,如有更新请参考最新版本文档。

<think>好的,用户需要查找YTM32B1MD1芯片的PWM配置资料或教程。首先,我应该检查提供的引用内容,看看是否有直接相关的信息。引用[1]提到了I2C配置,引用[2]和[3]涉及Flash存储和boot swap,这些都不直接涉及PWM。但可能需要参考类似模块的配置方法。 考虑到YTM32系列可能有统一的配置风格,比如使用寄存器配置,用户可能需要查阅该芯片的数据手册,特别是PWM模块相关的章节。由于现有引用中没有PWM的具体信息,建议用户参考官方文档,并参考类似模块如I2C或EFM的配置流程。 另外,用户可能需要了解如何设置PWM的时钟源、占空比、周期等参数,以及相关的寄存器地址和功能描述。同时,可能存在示例代码或应用笔记,但需要官方资料支持。需要提示用户检查数据手册中的PWM章节,或者联系技术支持获取更多资源。</think>### YTM32B1MD1芯片PWM配置指南 YTM32B1MD1微控制器的PWM(脉宽调制)功能通常通过其定时器模块(如GPT或PWM专用模块)实现,具体配置需参考芯片数据手册中的**Timer/PWM模块章节**。以下是配置PWM的关键步骤和要点: 1. **时钟源配置** 需为PWM模块选择合适的时钟源(如内部系统时钟或外部时钟),并设置预分频器(Prescaler)以调整PWM频率。例如: ```c GPT->CR |= GPT_CR_CLKSRC_INTERNAL; // 选择内部时钟 GPT->PR = 79; // 预分频值设为80分频(PR寄存器值为N-1) ``` 2. **PWM模式设置** 在定时器控制寄存器中启用PWM模式,并配置计数模式(如边沿对齐或中心对齐)。例如: ```c GPT->CR |= GPT_CR_MODE_PWM | GPT_CR_CNTMODE_EDGE; // 边沿对齐PWM模式 ``` 3. **占空比与周期设置** - **周期值**:通过设置`GPT->ARR`(自动重载寄存器)定义PWM周期。 - **占空比**:通过`GPT->CCR`(比较捕获寄存器)控制高电平时间。 示例代码: ```c GPT->ARR = 999; // PWM周期 = (ARR+1) * 时钟周期 GPT->CCR = 300; // 占空比 = (CCR / (ARR+1)) * 100% = 30% ``` 4. **引脚复用与输出使能** 需通过GPIO复用功能将特定引脚映射到PWM输出通道,并配置为推挽输出模式。例如: ```c GPIO->AFRL |= (2 << 4); // 将PA1引脚复用为GPT_CH1 GPIO->MODER |= GPIO_MODER_OUTPUT; // 配置为输出模式 ``` 5. **中断与触发配置(可选)** 若需PWM触发ADC或DMA,需配置相关触发信号和中断使能位。 **注意事项**: - 具体寄存器名称和位定义需以数据手册为准,不同型号可能存在差异[^2]。 - 配置写保护寄存器时,需参考EFM模块的操作流程[^3]。 ### 相关资料建议 1. 查阅**YTM32B1MD1数据手册**中“Timer/PWM模块”章节,获取寄存器映射和功能描述。 2. 参考官方提供的**PWM应用笔记**或示例代码(如I2C Demo的工程结构[^1])。 3. 联系芯片供应商获取技术支持或培训材料。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值