定时器输出PWM信号同步控制传感器开关与 ADC 采样

设计目标:

使用同一个定时器,同时控制两个车辆检测传感器的开关,并精确触发 ADC 采样。

整体时序要求如下:

  • 系统以 10 ms 为一个检测周期;
  • 每个检测周期内,仅在 前 100 µs 打开传感器;
  • 在传感器打开时段触发 ADC 完成一次采样;

所有CubeMX配置以及代码示例均基于STM32G0系列MCU。

STM32CubeMX 配置

定时器配置

1. 定时器模式配置:

  • Channel 2:PWM输出,控制车辆检测传感器 1
  • Channel 3:PWM输出,控制车辆检测传感器 2
  • Channel 4:PWM 模式(无输出引脚),不输出信号到引脚,仅用于触发ADC转换

2. 定时器计数配置:

  • Prescaler:3(将 16 MHz 定时器输入时钟分频为 4 MHz, 一个脉冲对应0.25 µs的时间)

  • Counter Mode: Up (递增计数)

  • Counter Period(ARR):39999(对应周期计算)

    复制代码
    (39999 + 1) × 0.25 µs = 10 ms

3. 定时器通道配置

  • PWM Generation Channel 2: Pulse=400(对应100us的高电平时间,传感器1使能)
  • PWM Generation Channel 3: Pulse=400(对应100us的高电平时间,传感器2使能)
  • PWM Generation Channel 4: Pulse=100(对应25us的高电平时间,ADC 配置为 在 CH4 的下降沿触发转换)

三个通道的输出波形如下图所示:

  • CH2 / CH3:在周期开始后立即启动传感器,100 µs 后关闭
  • ADC 配置为 在 CH4 的下降沿触发转换,这样可以确保 ADC 采样发生在传感器已经稳定开启之后

ADC配置

1. ADC触发源配置:

  • Scan Conversion Mode:Enable(顺序采样两个通道)
  • Continuous Conversion Mode:Disable(外部触发一次,仅采样转换一次序列)
  • DMA Continous Request:Enable(表示每次完成一个通道数据的转换都发起DMA请求)
  • Number Of Conversion: 2(对应两个传感器通道)
  • External Trigger Conversion Source: Timer 1 Capture Compare 4 event
  • External Trigger Conversion Edge: Trigger detection on the falling edge(在下降沿触发)

2. ADC配置DMA搬运数据

  • Direction: Peripheral To Memory
  • Mode: Circular(DMA 写满数组后自动回到起始地址)
  • Data Width: Half Word(ADC 为 12bit 精度,使用 16bit 数据宽度即可)

启动定时器与DMA

生成代码后,在初始化完成后添加如下代码:

复制代码
  HAL_TIM_Base_Start(&htim1); // 启动定时器
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); // 启动通道2的PWM输出,控制传感器1开关
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3); // 启动通道3的PWM输出,控制传感器2开关
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4); // 启动通道4的PWM输出,驱动ADC采样
  HAL_ADC_Start_DMA(&hadc1, adc_values,   sizeof(adc_values)/sizeof(uint16_t)); // 启动ADC

ADC 结果缓冲区定义如下:

复制代码
static uint16_t adc_values[2]; // 数组大小为2,分别对应两个传感器采样结果

当 DMA 完成一次传输后,会触发 ADC 转换完成回调函数。此时,两个 ADC 通道的采样与转换均已完成,数据已全部搬运到内存缓冲区。

复制代码
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	if(hadc == &hadc1)
	{
		adc_value_flag = 1;
	}
}

主循环处理逻辑

复制代码
while(!adc_value_flag)
{
    __WFI(); // 低功耗等待中断
}

adc_value_flag = 0;


bool vehicle_detected = (adc_values[0] < VEHICLE_ADC_THRESHOLD || adc_values[1] < VEHICLE_ADC_THRESHOLD);
相关推荐
BackCatK Chen16 小时前
第 8 篇:TMC2240 电机正反转实现|DIR 引脚控制 + 代码优化(稳定不抖动)
stm32·单片机·嵌入式硬件·保姆级教程·电机正反转·tmc2240·dir引脚控制
Hello_Embed21 小时前
libmodbus 移植 STM32(USB 串口后端篇)
笔记·stm32·单片机·嵌入式·freertos·libmodbus
羽获飞1 天前
从零开始学嵌入式之STM32——9.STM32的时钟系统
stm32·单片机·嵌入式硬件
wotaifuzao1 天前
STM32 + FreeRTOS 的订阅通知组件架构
stm32·嵌入式硬件·架构·freertos·事件驱动·嵌入式架构
小龙报1 天前
【51单片机】深度解析 51 串口 UART:原理、配置、收发实现与工程化应用全总结
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·51单片机
Lester_11012 天前
STM32 高级定时器PWM互补输出模式--如果没有死区,突然关闭PWM有产生瞬间导通的可能吗
stm32·单片机·嵌入式硬件·嵌入式软件
小李独爱秋2 天前
“bootmgr is compressed”错误:根源、笔记本与台式机差异化解决方案深度指南
运维·stm32·单片机·嵌入式硬件·文件系统·电脑故障
宵时待雨2 天前
STM32笔记归纳8:时钟
笔记·stm32·单片机·嵌入式硬件
JJRainbow2 天前
SN75176 芯片设计RS-232 转 RS-485 通信模块设计原理图
stm32·单片机·嵌入式硬件·fpga开发·硬件工程
不做无法实现的梦~2 天前
PX4编译环境配置和qgc配置安装教程(2)
linux·stm32