利用硬件机制实现无中断依赖的连续传输,适用于固定模式或周期性更新的场景:
c
运行
// STM32 DMA循环模式配置
void dma_circular_mode_init() {
// 配置DMA为循环模式
DMA_InitTypeDef DMA_InitStruct;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // 循环模式
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&TIM2->CCR1;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)pwm_buffer;
DMA_InitStruct.DMA_BufferSize = BUFFER_SIZE;
// 其他配置...
HAL_DMA_Init(&hdma_tim2_ch1, &DMA_InitStruct);
// 配置定时器触发DMA
TIM_SelectDMAOutput(TIM2, TIM_DMABase_CCR1);
TIM_DMACmd(TIM2, TIM_DMA_CC1, ENABLE);
// 启动定时器和DMA
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
HAL_DMA_Start(&hdma_tim2_ch1, (uint32_t)pwm_buffer,
(uint32_t)&TIM2->CCR1, BUFFER_SIZE);
}
// 后台更新循环缓冲区(非中断方式)
void update_circular_buffer() {
// 计算安全更新位置(避开当前DMA正在访问的地址)
uint32_t current_pos = BUFFER_SIZE - DMA_GetCurrDataCounter(hdma_tim2_ch1.Instance);
uint32_t safe_pos = (current_pos + BUFFER_SIZE/2) % BUFFER_SIZE;
// 安全更新缓冲区后半部分
generate_pwm_data(&pwm_buffer[safe_pos], BUFFER_SIZE/2);
}
适用场景:
电机控制等需要连续稳定 PWM 输出的场景
对实时性要求极高,不允许任何中断延迟的应用
数据变化周期长于缓冲区传输周期的情况
|
|