ADC与DAC同步方案咨询:TIM2触发DAC DMA时精准采集ADC样本
问题描述
我有一个包含256个元素的数组,需通过以下代码配置DAC输出:HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)array, 256, DAC_ALIGN_12B_R);
DMA由TIM2触发,256个定时器周期约为1ms。需求为:每当DAC输出至数组的第100个元素(TIM2完成100次重载)时,在缓冲区中存储128个ADC采样值,且该过程需在每个DAC周期重复执行。
我尝试过使用从模式的两个定时器,但在while循环中读取CNT寄存器的值不稳定;也曾考虑使用中断,但无法实现同步。请问该如何实现此同步逻辑?
实现方案
方案1:TIM2比较匹配中断触发ADC DMA采样
- 配置TIM2的任意通道为定时比较模式,设置比较值为99(因为定时器从0开始计数,第100次触发对应计数值99)。
- 开启TIM2的比较匹配中断,当中断触发时,启动ADC的DMA连续采样,采样长度设为128。
- 在ADC的DMA传输完成中断中,停止ADC采样,避免持续采集,同时可标记采样完成以处理数据。
关键代码示例:
// 配置TIM2比较通道 TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_TIMING; sConfigOC.Pulse = 99; // 对应第100个定时器周期触发 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); // 开启比较匹配中断 HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_1);
TIM2比较中断回调函数:
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { // 启动ADC DMA采样128个值 HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buffer, 128); } }
ADC DMA完成回调函数:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc->Instance == ADC1) { HAL_ADC_Stop_DMA(&hadc); // 此处可处理采样完成的缓冲区数据 } }
方案2:TIM2更新中断计数触发采样
- 开启TIM2的更新中断,在中断回调中维护一个软件计数器。
- 当计数器递增到99时,触发ADC DMA采样,随后重置计数器,等待下一个DAC周期。
关键代码示例:
static uint16_t tim2_cycle_cnt = 0; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) { if(tim2_cycle_cnt == 99) { HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buffer, 128); tim2_cycle_cnt = 0; // 重置计数,进入下一轮循环 } else { tim2_cycle_cnt++; } } }
关键注意事项
- 中断优先级:TIM2的中断优先级需高于ADC相关中断,确保采样触发的及时性,避免计数混乱。
- 缓冲区管理:建议使用双缓冲或循环缓冲存储ADC采样数据,防止数据被覆盖。
- 时钟同步:确保TIM2、ADC、DAC使用同源时钟,避免长期运行后出现累积误差导致同步失效。
内容的提问来源于stack exchange,提问作者Chey
相关产品推荐
相关产品推荐

