CUBEMX使用定时器触发ADC采样DMA
时间: 2025-03-05 18:25:58 浏览: 78
### STM32 CubeMX 中配置定时器触发 ADC 采样并使用 DMA 传输数据
#### 配置步骤概述
在 STM32CubeMX 工具中设置定时器触发 ADC 并通过 DMA 进行数据传输涉及几个关键组件的初始化和配置。这些组件包括 ADC、TIM 和 DMA 控制器。
#### 初始化 ADC 模块
为了使能 ADC 功能,在项目创建阶段需勾选相应的外设选项。进入 Pinout & Configuration 页面,找到 Analog 外设部分下的 `ADC` 节点展开它,并启用所需的模拟输入通道[^1]。
对于 ADC 的具体参数设定如下:
- **Mode**: 设置为 Single-ended mode 单端模式;
- **Resolution**: 可根据需求选择分辨率,默认情况下可能是 12-bit 或者其他值;
- **Sampling Time**: 对于不同应用场合可以调整采样时间长短来平衡精度与速度之间的关系;
- **Scan Conversion Mode**: 如果只用到单一通道则关闭此功能;若有多个通道参与转换,则开启扫描模式以便依次处理各个信道的数据;
- **Continuous Conv. Mode**: 关闭连续转换模式,因为这里采用的是由外部事件(即定时器溢出)驱动的方式启动一次性的测量过程而不是周期性地自动运行;
- **DMA Settings**: 启动 Direct Memory Access (DMA),指定好缓冲区地址以及每次完成一组完整的序列之后应该采取的动作——比如发出中断请求通知 CPU 去获取最新一批的结果。
```c
static void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
hadc.Instance = ADC1;
hadc.Init.ScanConvMode = DISABLE; // Disable scan to work on single channel only.
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_TRGO;
hadc.Init.DMAContinuousRequests = ENABLE;
hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
```
上述代码片段展示了如何利用 HAL 库函数对 ADC 实施基本配置,其中特别指定了 TRIGGER SOURCE 来源为 TIM1 的更新事件作为同步信号用于发起 A/D 转换操作。
#### 定时器 TIM 设定
接下来要做的就是建立一个合适的计数器实例用来定期激活前述已经准备好的模数变换电路。同样是在图形界面里定位至对应的 Timer 组件处做进一步编辑:
- **Prescaler**:预分频系数决定了实际工作频率相对于 APBx 总线速率的比例因子;
- **Counter Period** :最大计数值也即是说当达到该极限后会重新回到零点从而形成脉冲输出;
- **Clock Division** : 分配给定时单元内部使用的时钟除法比例;
- **Repetition Counter** : 若涉及到 PWM 输出等功能才需要用到重复次数属性;
- **Output Compare/PWM Channel(s)**: 不必理会除非计划实现更复杂的功能像产生方波形之类;
- **Master/Slave Mode** : 当存在多片级联情况时考虑主从架构设计;
- **Synchronization Input Selection** : 此项关联到了前面提到过的 ADC 触发条件的选择上,应指向所期望的硬件资源例如 T1_TRGO 表明是从 TIM1 发射过来的同步脉冲[^2]。
```c
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 79;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 999;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
void StartTimerForADCTrigger()
{
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,PeriodValue);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
}
```
以上给出了一段简单的例子说明怎样构建起基于定时机制的时间基底结构,注意这里的 Prescaler 参数应当依据系统核心振荡频率合理计算得出以确保最终得到恰当的工作节拍。
#### DMA 流程控制
最后一步便是安排好直接存储访问路径使得经过量化后的数字量能够被高效地搬移到内存空间内等待后续分析处理。这通常意味着要在软件层面预先分配一块足够大小的数组区域供存放即将流入的信息流,并且告诉 DMA 控制寄存器有关目标位置的具体坐标以及其他必要的细节描述如传输方向等。
```c
uint16_t aADCxConvertedData[BUFFER_SIZE];
/* Enable DMA Stream */
hdma_adc.Instance = DMA1_Stream0;
hdma_adc.Init.Channel = DMA_CHANNEL_0;
hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc.Init.Mode = DMA_CIRCULAR;
hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_adc) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(&hadc,DMA_Handle,&hdma_adc);
// 开启DMA循环模式下的一次性传输请求
HAL_ADC_Start_DMA(&hadc,(uint32_t*)aADCxConvertedData,BUFFER_SIZE);
```
这段程序实现了将来自 ADC 接口的数据经由 DMA
阅读全文
相关推荐



















