理论部分

硬件部分

直流电机属于大功率器件,GPIO口无法驱动,需要外部的驱动电路来进行驱动;TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向,通过两个电级正反接来控制电机正反转。

 VM接电机的电源5V,正常使用的话STBY直接接3.3V电源即可,不需要待机状态

 代码讲解

首先,在PWM驱动直流电机的过程中用到了GPIO口和TIM定时器所以在开始配置时钟的时候都需要进行时钟的配置,由于电机的控制模式输入端接在了PA4和PA5口,所以在配置的时候需要配置APB2的GPIOA,PWM信号输入端接在了PA2口,所以需要配置APB1的TIM2定时器。

 第二,进行GPIO的初始化,尤其注意在配置模式的时候需要进行复用功能输入模式,来自片上外设不能用开漏输出是因为对于开漏输出模式而言输出高电平是高阻态,而PWM需要高电平来驱动

 第三,进行TIM定时器的时钟模式选择和时基单元初始化,时钟模式分为:内部时钟模式,外部时钟模式1,外部时钟模式2,编码器模式。时钟源直接选择内部时钟模式即可,默认情况下也是内部时钟模式,可以不用进行滤波也就是时钟分频可不分频。计数方式分为:向上计数,向下计数,和中央对其,高级定时器和通用定时器三种模式都有,基本定时器只有向上计数的方式,最长用的计数方式是向上计数的方式,自动重装值和预分频器的值视情况而定,重复计数高级定时器配置。

注意:为了避免直流电机有蜂鸣器的叫声可把预分频的值设置成36-1(20KHZ),人耳能听到的频率为20HZ到20KHZ

第四, 输出比较通道3进行初始化,由于在初始化的过程中一些结构体成员没有用到,所以为了避免影响和麻烦在配置之前要进行结构体的初始化,选择常用的PWM模式1的向上计数方式,PWM模式2相当于PWM模式1的取反,0是不进行反转

 输出比较的模式

选通道三根据引脚定义表决定;

 第五,打开计数器,一定不能忘记,不然不会开始计数

 第六,进行占空比值的更改

 第七,进行直流电机底层的配置,GPIO口的初始化和上面一样,对4号引脚和5号引脚进行配置

 进行占空比的设置,定义speed变量,大于0是正转,小于0是反转

 

代码部分

主函数

#include "stm32f10x.h"                  // Device header
#include "Led.h"//LED专用头文件
#include "Delay.h"//延时函数专用头文件
#include "oled.h"//OLED函数专用头文件
#include "Key.h"//按键读取函数专用头文件
#include "Timer.h"//PWM专用头文件
#include "servo.h"//舵机专用头文件
#include "Moter.h"//直流电机专用头文件
uint8_t Key_Down;
int8_t speed;
int main(void)
{
	Led_Init();//LED初始化函数
	OLED_Init();//OLED初始化函数
	Key_Init();//按键初始化函数
	Timer_Init();//PWM初始化
	Moter_Init();//直流电机初始化
	OLED_ShowString(1,1,"Speed:"); 
	while(1)
	{
	Key_Down=Key_Read();
	 if(Key_Down==1)
	 {
		 speed+=20;
		 if(speed>=100)
		 {
			 speed=-100;
		 }
		 PWM_Setspeed(speed);
		OLED_ShowNum(1,7,speed,3);//显示速度
	 }
	}	
}

TIM定时器底层

#include "stm32f10x.h"                  // Device header
void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef  GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
	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_OCStructInit(&TIM_OCInitStructure);//结构体成员进行初始化
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//PWM模式1
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//不反转
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使能
	TIM_OCInitStructure.TIM_Pulse=0;//占空比CCR的初始值
	TIM_OC3Init(TIM2,&TIM_OCInitStructure);//通道3初始化
	
	TIM_Cmd(TIM2,ENABLE);//打开计数器
}
void PWM_SetCompare3(uint16_t Compare)
{	
	TIM_SetCompare3(TIM2,Compare);//设置CCR2的值
}

直流电机底层

#include "stm32f10x.h"                  // Device header
#include "Timer.h"
void Moter_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA时钟
	GPIO_InitTypeDef GPIO_InitStructure;//宏定义结构体变量
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//设置为推挽输出模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_4;//设置GPIO的第4,5号引脚
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//GPIO的速度为50MHZ
	GPIO_Init(GPIOA,&GPIO_InitStructure);	
	Timer_Init();
}
void PWM_Setspeed(uint16_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);	
	}
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐