gd32定时器加dma
时间: 2024-12-31 10:44:55 浏览: 11
### GD32 定时器配合 DMA 使用方法
#### 配置 DMA 操作
DMA(直接存储器访问)允许数据在内存和外设之间高效传输而无需 CPU 干预。对于 GD32 微控制器,在配置定时器与 DMA 协同工作前,需初始化 DMA 控制器并设置相应的参数。
```c
/* 初始化 DMA */
void dma_init(void)
{
/* 使能 DMA 时钟 */
rcu_periph_clock_enable(RCU_DMA0);
/* 清除 DMA 通道的标志位 */
dma_flag_clear(DMA0, DMA_FLAG_FTF0 | DMA_FLAG_HTF0);
/* 配置 DMA 通道 */
dma_parameter_struct dma_init_struct;
dma_deinit(DMA0_CH0); // 取消初始化指定的 DMA 通道
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; // 设置传输方向
dma_init_struct.memory_addr = (uint32_t)&data_buffer[0]; // 内存地址指针
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; // 开启内存增量模式
dma_init_struct.periph_addr = (uint32_t)&(TIMERS->CCR1); // 外设地址指针
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; // 关闭外设增量模式
dma_init_struct.priority = DMA_PRIORITY_HIGH; // 设定优先级为高
dma_init_struct.number_of_data = BUFFER_SIZE; // 数据量大小设定
dma_init(DMA0_CH0, &dma_init_struct); // 根据结构体中的成员对 DMA 参数进行初始化
}
```
#### 定时器外设配置 DMA 使用
为了使定时器能够触发 DMA 请求,需要开启定时器的相关中断和服务请求。这通常涉及到修改特定寄存器来激活这些功能。
```c
/* 启用定时器 DMA 功能 */
void timer_dma_config(uint32_t timer_periph)
{
/* 使能定时器更新事件产生的 DMA 请求 */
TIMER_DMACFG(timer_periph) |= TIMER_DMACFG_DMABASE_CCR1;
/* 使能定时器捕获/比较输入输出通道上的 DMA 请求 */
TIMER_CTL0(timer_periph) |= TIMER_CTL0_CC1S_0;
/* 使能定时器 DMA 中断 */
NVIC_InitTypeDef nvic_init_struct;
nvic_init_struct.NVIC_IRQChannel = DMA0_Channel0_IRQn;
nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0x0F;
nvic_init_struct.NVIC_IRQChannelSubPriority = 0x0E;
nvic_init_struct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init_struct);
}
/* 实际启用 DMA 和中断 */
TIMER_DMAINTEN(TIM8) |= (uint32_t)(TIMER_INT_UPD | TIMER_INT_TRG | TIMER_INT_COM | TIMER_INT_ERR); // 启用多个中断源
TIMER_DMAINTEN(TIM8) |= (uint32_t)DMA_CHANNEL0_REQUEST; // 启用 DMA 请求
```
上述代码片段展示了如何针对 TIM8 进行配置[^1]。需要注意的是实际应用中应根据具体需求调整所涉及的具体定时器编号以及其他细节部分。
#### PWM 波形生成及控制逻辑
当利用定时器产生 PWM 输出的同时也希望通过 DMA 来管理其占空比变化,则可以在每次改变 CCR 寄存器值之前启动一次新的 DMA 转移过程:
```c
/* 更新 PWM 的占空比 */
void update_pwm_duty_cycle(float duty_ratio)
{
uint16_t compare_value = (uint16_t)((float)PERIOD * duty_ratio);
data_buffer[0] = compare_value;
/* 触发 DMA 发送新数值给定时器 */
dma_channel_select(DMA0, DMA_CHSEL_CH0);
dma_memory_address_set(DMA0, DMA_CH0, (uint32_t)&compare_value);
dma_transfer_number_set(DMA0, DMA_CH0, 1U);
dma_circulation_disable(DMA0, DMA_CH0);
dma_channel_enable(DMA0, DMA_CH0);
}
```
此函数接收一个表示期望占空比的比例因子作为输入,并据此计算出对应的计数器匹配值,随后通过 DMA 将该值传递至定时器的相应寄存器中完成更新操作[^2]。
阅读全文