STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

06-01 1117阅读

STM32单片机的PWM(脉冲宽度调制)电机控制

作者:公子易平

时间:2023/6/6

前段时间做一个智能小车的相关项目时,发现很少有人能够将STM32的PWM控制讲清楚,故而书此文,希望对后来的学习者有所帮助。

文章目录

  • STM32单片机的PWM(脉冲宽度调制)电机控制
    • 1.硬件介绍
    • 2.PWM控制原理
      • 2.1PWM控制的三个关键参数
      • 2.2定时器关键参数
      • 2.3PWM参数联系定时器参数
      • 3.软件设计
        • 3.1定时器配置
        • 3.2电机端口初始化
        • 3.3小车运动封装

          1.硬件介绍

          • STM32F103C8T6最小系统板

            STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

            • 直流TT电机

              STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

            • 电机驱动芯片(TB6612)

            • STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

            • 杜邦线若干

              STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

              接线情况:

              TB6612引脚说明:

              STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

              STM32主控芯片与TB6612接线:

              STM32F103C8T6TB6612
              PA6PWMA
              PA7PWMB
              PB12AIN1
              PB13AIN2
              PB14BIN1
              PB15BIN2

              TB6612其余接口:

              TB6612接口
              VM7.4V
              VCC3.3V
              GNDGND
              AO1&AO2A路电机正负极
              BO1&BO2B路电机正负极
              STBY3.3V

              电路原理图如下,仅供参考:

              STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

              2.PWM控制原理

              PWM即脉冲宽度调制(Pulse Width Modulation),常用PWM实现LED呼吸灯、直流电机调速以及舵机控制,本文重点介绍如何使用STM32单片机对直流电机进行调速控制。

              2.1PWM控制的三个关键参数

              PWM控制的三个关键参数为频率(Freq)、占空比(Duty)以及分辨率(Reso),其相关定义如下式所示。

              STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

              式中,Freq、Duty以及Reso分别表示PWM的频率、占空比和分辨率。Ts为一个PWM控制周期的总时间,Ton为一个PWM控制周期中高电平时间。式中分辨率和频率的定义一样但是单位不同,频率的单位是Hz,分辨率的单位是%。

              需要重点关注的是占空比和分辨率两个参数。

              • 占空比:

                高电平的工作时间占一个周期的比例,可以理解高电平时间越长则电机转速越快,反之越慢。

                (理想的认为占空比和电机的转速成正比例关系)

                eg:

                Duty=0% 电机不转

                Duty=100% (在供电电压满足电机的额定电压时)电机达到最大转速

                Duty=50%的电机转速大于Duty=30%的电机转速

                • 分辨率:

                  表征PWM控制的精度的一个参数,即可以电机速度调节的步距(Step)的大小,分辨率越大,能够控制的占空比也就精度越高。

                  eg:

                  Reso=1%(1/100) 则电机的占空比可以为1% 2% 3%…100%,但是不能为3.5%;

                  Reso=0.1% (1/1000)则电机的占空比可以为0.1%、8.9%…,但是不能是90.678%。

                  2.2定时器关键参数

                  使用STM32单片机实现PWM控制时需要用到单片机上的TIM定时器外设,使用定时器的输出比较功能。

                  需要配置的定时器的关键参数亦有三个:预分频值PSC(Prescalar)、自动重装值ARR(AutoReload Register)以及输出比较值CCR(Capture /Compare Register)。

                  • PSC

                    ​ 对输入到定时器中的时钟进行分频,如果默认的输入时钟信号为72MHz,则PSC=0时,时钟信号不分频,定时器输入时钟信号为72MHz;PSC=1时,系统分频,定时器输入时钟信号为36MHz…

                    ​ 定时器的输入时钟信号=默认的输入时钟信号➗(PSC+1)

                    • ARR

                      ​ 当使用定时器时,每经过单位时间(时基单元决定),定时器中CNT计数单元就会加1,其上限值由寄存器的位数决定,为防止其无限增加,需要配置ARR值。ARR的作用是在CNT计数单元增加到ARR值时,CNT的值自动停止增加并返回到初始值。

                      ​ 实际上可以将这个过程看作给多个杯子加水的过程,每过一段时间就给一个杯子加固定体积的水,当一个杯子中的水装满之后,就给另一个新的杯子加水,而ARR自动重装值就相当于每个杯子的高度。

                      • CCR

                        ​ 其实CCR输出比较值可以简单的理解为一个分界线。

                        ​ 依旧是上面的例子,这次我们将杯子更具CCR分界线分成了上下两部分。下部分空间在遇到水之后会变成绿色,而上部分空间在遇到水之后会变成红色。

                        ​ 在单片机中将绿色想象成高电平,红色为低电平。则在一个计数的周期内,如果定时器的计数值CNT未到达CCR分界线,则水是绿色的,输出高电平给电机;当计数值CNT到达分界线CCR,则此时再向水杯中加水,颜色就会变成红色,即输出低电平给电机,而当水杯装满后,又需要给下一个水杯进行加水重复上述过程。

                        STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

                        2.3PWM参数联系定时器参数

                        上文中已然描述了定时器的三个参数以及PWM控制的三个参数,最终的目的是将定时器的三个参数的配置和PWM控制的三个参数的控制联系起来。

                        其相互之间的联系的公式可以由下述公式进行描述:

                        STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

                        其中ARR值和CCR的值决定了PWM控制的占空比和分辨率。

                        下图所示为其原理图,PWM控制的工作过程为:

                        1. 定时器工作,计数器值增加。
                        2. 当计数器值N小于CCR时,输出电平V为高电平1。
                        3. 当计数器值到达CCR时,输出电平V翻转为低电平0。
                        4. 当计数器值大于CCR小于ARR时,输出电平持续为低电平0,计数值N继续增加。
                        5. 当计数器值达到ARR时,计数值N回到初始状态,同时电平翻转,一个周期结束。

                          STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

                        所以,PWM控制实际上就是通过不断的改变定时器的CCR值来改变占空比,从而实现对电机的调速。

                        3.软件设计

                        TB6612电机驱动芯片可以驱动两路电机,本次使用单片机定时器3的两个通道产生两路PWM波实现对电机的调速控制。以下是代码部分,使用Keil软件进行编写。

                        3.1定时器配置

                        #include "stm32f10x.h"//头文件
                        //初始化定时器TIM3 并配置PWM初始化参数
                        void PWM12_Init(void)
                        {	//开启TIM3和GPIOA的时钟
                        	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
                        	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
                        	//初始化GPIO口 PA6 PA7 用于产生PWM信号
                        	GPIO_InitTypeDef GPIO_InitStructure;
                        	//复用推挽输出模式因为复用了TIM3外设
                        	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
                        	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
                        	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                        	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO A6 A7 
                        	//使用内部时钟
                        	TIM_InternalClockConfig(TIM3);
                        	//配置时基单元参数
                        	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;//到达ARR触发一次中断 停止计数
                        	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);//初始化单元
                        	//输出比较结构体配置
                        	TIM_OCInitTypeDef TIM_OCInitStructure;
                        	TIM_OCStructInit(&TIM_OCInitStructure);//补全结构体中未配置参数
                        	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;	
                        	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择PWM模式1
                        	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较极性选择
                        	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
                        	TIM_OC1Init(TIM3, &TIM_OCInitStructure);//初始化 TIM3 OC1
                        	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能CCR1自动重装
                        	TIM_OC2Init(TIM3, &TIM_OCInitStructure);//初始化 TIM3 OC2	
                        	TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能CCR2自动重装
                        	
                        	TIM_ARRPreloadConfig(TIM3,ENABLE);//开启预装载
                        	TIM_Cmd(TIM3, ENABLE);//开启定时器3
                        	TIM3->CCR1 = 0;//设置输出比较值
                        	TIM3->CCR2 = 0;
                        }
                        //设置PWM1比较值 为Compare 即输出比较值
                        void PWM12_SetCompare1(uint16_t Compare)
                        {
                        	TIM_SetCompare1(TIM3, Compare);
                        }
                        //设置PWM2比较值 为Compare
                        void PWM12_SetCompare2(uint16_t Compare)
                        {
                        	TIM_SetCompare2(TIM3, Compare);
                        }
                        

                        3.2电机端口初始化

                        /******************************Motor电机模块**************************
                        电机初始化设置 以及电机PWM设置
                        *********************************************************************/
                        #include "stm32f10x.h"                  // Device header
                        #include "Timer.h"
                        void MotorAll_Init(void)
                        {
                        	//开启电机驱动口的四个GPIO
                        	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
                        	GPIO_InitTypeDef GPIO_InitStructure;
                        	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
                        	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13|GPIO_Pin_14 | GPIO_Pin_15;
                        	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                        	GPIO_Init(GPIOB, &GPIO_InitStructure);
                        	PWM12_Init();//开启定时器
                        }
                        //设置右路电机速度 PWM
                        void MotorR_SetSpeed(int8_t Speed)
                        {
                        	if (Speed >= 0)//Speed值为正
                        	{
                        		GPIO_SetBits(GPIOB, GPIO_Pin_12);//电机正转
                        		GPIO_ResetBits(GPIOB, GPIO_Pin_13);
                        		PWM12_SetCompare1(Speed);//设置Speed转速
                        	}
                        	else//Speed值为负
                        	{
                        		GPIO_ResetBits(GPIOB, GPIO_Pin_12);//电机反转
                        		GPIO_SetBits(GPIOB, GPIO_Pin_13);
                        		PWM12_SetCompare1(-Speed);//设为-Speed转速
                        	}
                        }
                        //设置左路电机PWM 速度
                        void MotorL_SetSpeed(int8_t Speed)
                        {
                        	if (Speed >= 0)
                        	{
                        		GPIO_SetBits(GPIOB, GPIO_Pin_14);
                        		GPIO_ResetBits(GPIOB, GPIO_Pin_15);
                        		PWM12_SetCompare2(Speed);
                        	}
                        	else
                        	{
                        		GPIO_ResetBits(GPIOB, GPIO_Pin_14);
                        		GPIO_SetBits(GPIOB, GPIO_Pin_15);
                        		PWM12_SetCompare2(-Speed);
                        	}
                        }
                        

                        3.3小车运动封装

                        /******************************模块简介*******************************
                        模块功能:小车运动 模块函数封装 
                        *********************************************************************/
                        #include "stm32f10x.h"                  // Device header
                        #include "Motor.h" 
                        #include "Delay.h"  
                        void Car_Stop()//小车停止
                        {
                        	MotorR_SetSpeed(0);
                        	MotorL_SetSpeed(0);
                        }
                        void Car_Up()//小车前进
                        {
                        	MotorR_SetSpeed(80);
                        	MotorL_SetSpeed(80);	
                        }
                        void Car_Down()//小车后退
                        {
                        	MotorR_SetSpeed(-80);
                        	MotorL_SetSpeed(-80);
                        }
                        void Car_TurnRight()//小车右转
                        {
                        	MotorR_SetSpeed(-50);
                        	MotorL_SetSpeed(100);
                        }
                        void Car_TurnLeft()//小车左转
                        {
                        	MotorR_SetSpeed(100);
                        	MotorL_SetSpeed(-50);
                        }
                        void Car_Spin()//小车旋转
                        {
                        	MotorR_SetSpeed(-100);
                        	MotorL_SetSpeed(100);
                        }
                        

                        在主函数中分别调用上述封装函数,即可实现电机的调速运动。


                        上述内容仅为作者个人看法,受限于水平和经验原因,部分描述可能存在问题。希望读者可以指出错误的地方,一起交流学习。毕竟读他人的东西只有做到双眼自将秋水洗,才能一生不受古人欺。


                        更新日期 :2023/6/8

                        作 者:公子易平

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]