在 STM32 单片机中具体如何生成并发送脉冲信号(这是控制 J3 伺服驱动器的核心环节),我会从基础原理、代码实现、关键配置三个维度,用新手能理解的方式讲清楚 STM32 发送脉冲的完整方法。
一、STM32 发送脉冲的核心原理
STM32 发送脉冲主要依赖定时器的 PWM 输出功能或脉冲计数输出功能,本质是通过配置定时器产生固定频率、固定占空比的方波(脉冲),从 GPIO 口输出给伺服驱动器。
核心逻辑:定时器的计数频率由 “系统时钟 + 预分频” 决定,脉冲频率由 “定时器自动重装值(ARR)” 决定,占空比由 “比较值(CCR)” 决定。
常用场景:控制伺服 / 步进电机时,脉冲频率对应电机转速,脉冲数量对应电机位置。
二、完整可运行的代码实现(以 STM32F103 为例)
以下是通用的脉冲发送代码,你可以直接复制使用,我会标注关键配置项,方便你根据 J3 伺服的需求调整:
c
运行
#include "stm32f10x.h"// ************************ 核心参数配置 ************************#define PULSE_FREQ 10000 // 目标脉冲频率(Hz),可根据伺服需求修改#define PULSE_DUTY 50 // 脉冲占空比(%),伺服一般用50%即可#define SYS_CLK 72000000 // STM32系统时钟(72MHz)// *************************************************************// 定时器句柄(TIM2_CH1,对应PA0引脚)TIM_TimebaseInitTypeDef TIM_TimebaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;GPIO_InitTypeDef GPIO_InitStructure;// 计算定时器参数// 预分频值:将系统时钟分频到1MHz(便于计算)u16 prescaler = (SYS_CLK / 1000000) - 1;// 自动重装值(ARR):决定脉冲频率 = 1MHz / (ARR + 1)u16 arr = (1000000 / PULSE_FREQ) - 1;// 比较值(CCR):决定占空比 = CCR / ARR * 100%u16 ccr = (arr * PULSE_DUTY) / 100;void STM32_Pulse_Init(void){
// 1. 使能时钟
// 使能TIM2时钟(APB1总线)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 使能GPIOA时钟(APB2总线)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 2. 配置GPIO口(PA0)为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 选择PA0引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出(定时器专用)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 输出速度50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 3. 配置定时器时基参数
TIM_TimebaseStructure.TIM_Period = arr; // 自动重装值(决定频率)
TIM_TimebaseStructure.TIM_Prescaler = prescaler; // 预分频值
TIM_TimebaseStructure.TIM_ClockDivision = 0; // 时钟分割(无)
TIM_TimebaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimebaseInit(TIM2, &TIM_TimebaseStructure);
// 4. 配置PWM输出模式(生成脉冲)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1(常用)
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 使能输出
TIM_OCInitStructure.TIM_Pulse = ccr; // 比较值(决定占空比)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 高电平有效
TIM_OC1Init(TIM2, &TIM_OCInitStructure); // 配置CH1通道
// 5. 使能预装载寄存器(确保参数修改立即生效)
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM2, ENABLE);
// 6. 启动定时器(开始发送脉冲)
TIM_Cmd(TIM2, ENABLE);}void Set_Pulse_Freq(u32 freq){
// 重新计算ARR和CCR值
arr = (1000000 / freq) - 1;
ccr = (arr * PULSE_DUTY) / 100;
// 更新定时器参数
TIM_SetAutoreload(TIM2, arr); // 更新自动重装值(频率)
TIM_SetCompare1(TIM2, ccr); // 更新比较值(保持占空比)}// 主函数示例int main(void){
// 初始化脉冲输出
STM32_Pulse_Init();
while(1)
{
// 示例:动态调整脉冲频率(对应胶泵转速变化)
Set_Pulse_Freq(5000); // 发送5kHz脉冲(低速)
for(u32 i=0; i<5000000; i++); // 延时
Set_Pulse_Freq(10000); // 发送10kHz脉冲(高速)
for(u32 i=0; i<5000000; i++); // 延时
}}三、代码关键部分解释
参数配置区:
PULSE_FREQ:你可以直接修改这个值来调整脉冲频率,比如控制 J3 伺服时,5kHz 脉冲对应胶泵 500r/min(需匹配电子齿轮比)。PULSE_DUTY:伺服驱动器对占空比不敏感,固定设为 50% 即可,无需修改。GPIO 配置:
必须设置为
GPIO_Mode_AF_PP(复用推挽输出),因为这个引脚要被定时器 “占用” 来输出脉冲,不能用普通输出模式。不同定时器对应不同 GPIO 口(如 TIM2_CH1=PA0、TIM1_CH1=PA8),可根据硬件布局调整。
定时器核心参数:
预分频值:把 72MHz 系统时钟分频到 1MHz,目的是简化频率计算(1MHz 对应 1μs)。
自动重装值(ARR):公式
ARR = 1000000 / 目标频率 - 1,比如 10kHz 脉冲的 ARR=99。比较值(CCR):公式
CCR = ARR * 占空比 / 100,50% 占空比的 CCR=ARR/2。动态改频率函数:
Set_Pulse_Freq()函数是控制胶泵转速的核心,只需传入目标脉冲频率,就能自动更新定时器参数,实时调整转速。
四、硬件注意事项
电平匹配:STM32 输出的是 3.3V 脉冲,而 J3 伺服驱动器的控制信号一般是 5V,建议在中间加电平转换模块(如 TXS0104),避免信号不识别。
接线保护:脉冲信号线串一个 2KΩ 电阻,GND 要共地(STM32 的 GND 和伺服驱动器的 GND 接在一起)。
引脚选择:优先选择定时器的 CH1/CH2 通道(如 TIM2_CH1=PA0、TIM3_CH1=PB0),这些引脚默认支持 PWM 输出。
总结
STM32 发送脉冲的核心是定时器 PWM 模式,通过配置预分频值、ARR、CCR 三个参数,就能精准控制脉冲频率和占空比。
控制胶泵转速的关键是调用
Set_Pulse_Freq()函数修改脉冲频率,频率越高,胶泵转速越快(需匹配 J3 伺服的电子齿轮比)。硬件上要注意电平匹配和共地,这是脉冲信号能被伺服驱动器正确识别的前提。



