您现在的位置是:首页 >其他 >江协科技stm32-[6-5] PWM驱动直流电机-PWM配置研究及关键代码网站首页其他

江协科技stm32-[6-5] PWM驱动直流电机-PWM配置研究及关键代码

ZL Ren 2026-04-28 00:01:04
简介江协科技stm32-[6-5] PWM驱动直流电机-PWM配置研究及关键代码

江协科技stm32-[6-5] PWM驱动直流电机-PWM配置研究及关键代码

码字不易,点个赞在看吧(如果能关注就更好了😊)
文章如有错误,更欢迎各位大佬指出,谢谢啦😘

1. 程序原理聚焦提问:

  1. 为什么PWM的产生原理叫做定时器输出比较
  2. 为什么PWM输出要用GPIO口的复用推挽输出模式?
  3. 程序中我们定义了函数void Motor_SetSpeed(int8_t Speed),并在其中用函数PWM_SetCompare3(Speed);来进行调速,那么笔者问个问题,Speed有单位吗?如果没有,那Speed的含义是什么?

2.程序原理聚焦回答:

  1. 见我的上一篇回答定时器输出比较原理及PWM配置研究
  2. AF(Alternate Function):表示该引脚不是普通 GPIO,而是 连接到片上某个外设(这里是 TIM2)。
    PP(Push-Pull):推挽输出模式,意味着该引脚可以输出 高电平(Vcc)或低电平(GND),并且内部结构带有 下拉/上拉,驱动能力较强,适用于高速信号传输(如 PWM、SPI、USART)。

如果不使用 AF_PP,而使用 GPIO_Mode_Out_PP(普通推挽输出):
该引脚不会被 TIM2 控制,而是作为普通 GPIO,由 GPIOx->ODR 控制。
这样 PWM 波形不会正确输出。

  1. 这里的Speed就是上篇文章提到过的定时器输出比较原理及PWM配置研究CCR寄存器的值啦!

3. 程序核心代码:

PWM.c

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	//TIM2是APB1总线的外设

	//初始化GPIO
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	
	
	//初始化AFIO,进行引脚(复用功能)重映射
	/*
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	*/
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		//复用推挽输出才能够将引脚控制权交给片上外设,PWM波才能够通过引脚输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;			//GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);	//定时器上电后默认使用内部时钟,不写也行
	
	//配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;		//向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;						//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1;					//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 50; 								//CCR
	
	//频率1KHz,占空比为50%
	//PA0口对应输出通道1
	TIM_OC3Init(TIM2, &TIM_OCInitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

void PWM_SetCompare3(uint16_t Compare)
{
	TIM_SetCompare3(TIM2, Compare);
	
}

Motor.c

#include "stm32f10x.h"                  // Device header
#include "PWM.h"

void Motor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5);
	
	PWM_Init();
	
}

void Motor_SetSpeed(int8_t Speed)
{
	if(Speed >= 0){
		//正转
		GPIO_SetBits(GPIOA, GPIO_Pin_4);
		GPIO_ResetBits(GPIOA, GPIO_Pin_5);
		PWM_SetCompare3(Speed);
	}else{
		//反转
		GPIO_SetBits(GPIOA, GPIO_Pin_5);
		GPIO_ResetBits(GPIOA, GPIO_Pin_4);
		PWM_SetCompare3(-Speed);	//Speed必须为正数
	}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。