实验三:STM32平台-------小车前后左右综合实验
1、实验前准备
图1-1 STM32主控板
图1-2 4个直流减速电机
2、实验目的
STM32单片机上电之后,实验效果小车前进1s,后退1s, 左转1s, 右转1s, 原地左旋1s, 原地右旋1s, 停止4s,然后循环以上步骤。
3、实验原理
对于4路直流减速电机的控制我们采用的是TB6612FNG驱动芯片来驱动电机。通过控制驱动芯片的AIN1,AIN2,BIN1,BIN2,PWMA,PWMB的电平高低来控制电机的正转,反转,停止。本次实验主要是控制AIN1为高电平,AIN2为低电平,BIN1为高电平,BIN2为低电平,进而通过控制PWMA,PWMB在0-255之间控制小车的速度。一路PWM控制小车一侧电机的速度。
脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路 PWM 输出!如下图3-1所示这里我们利用 TIM4的 CH1 产生一路 PWM 输出给右电机,利用TIM4的CH2产生一路PWM给左电机。如果要产生多路输出,大家可以根据我们的代码稍作修改即可。
图3-1 STM32硬件手册20页 GPIO说明
同样,我们首先通过对 PWM 相关的寄存器进行讲解,大家了解了定时器 TIM4 的 PWM原理之后,我们再讲解怎么使用库函数产生 PWM 输出。要使 STM32 的通用定时器 TIMx 产生 PWM 输出,我们还会用到 3 个寄存器 ,来控制 PWM 的 。这三个寄存器分别是 :捕获 /比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4)。接下来我们简单介绍一下这三个寄存器。具体寄存器请查看《STM32 中文参考手册 V10》。这里只讲下库函数的使用方法。
首先要提到的是, PWM 相关的函数设置在库函数文件 stm32f10x_tim.h 和 stm32f10x_tim.c文件中。
1) 开启 TIM4 时钟以及复用功能时钟,配置 PB6(PB7同理) 为复用输出。要使用 TIM4,我们必须先开启 TIM4 的时钟,这点相信大家看了这么多代码,应该明白了。这里我们还要配置 PB6 为复用输出,这是因为 TIM4_CH1 通道将重映射到 PB6 上,此时, PB6属于复用功能输出。 库函数使能 TIM4 时钟的方法是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器 4 时钟
这在前面一章已经提到过。 库函数设置 AFIO 时钟的方法是:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //复用时钟使能
这两行代码很容易组织,这里不做过多重复的讲解。 设置 PB6 为复用功能输出,这里简单列出 GPIO 初始化的一行代码即可:
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
2) 初始化 TIM4,设置 TIM4 的 ARR 和 PSC。
在开启了 TIM4 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的周期。当 PWM 周期太慢(低于 50Hz)的时候,我们就会明显感觉到闪烁了。因此, PWM 周期在这里不宜设置的太小。 这在库函数是通过 TIM_TimeBaseInit 函数实现的,调用的格式为:
TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的
3) 设置 TIM4_CH1 的 PWM 模式,使能 TIM4 的 CH1 输出。接下来,我们要设置 TIM4_CH1 为 PWM 模式(默认是冻结的),而我们希望当 CCR2 的值小的时候,电机变慢, CCR2 值大的时候,电机就快,所以我们要通过配置 TIM3_CCMR1 的相关位来控制 TIM3_CH2 的模式。在库函数中,PWM 通道设置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样, 这里我们使用的是通道 1,所以使用的函数是
TIM_OC1Init();
如果是通道2则是
TIM_OC2Init()。
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
这种初始化格式大家学到这里应该也熟悉了,所以我们直接来看看结构体 TIM_OCInitTypeDef
的定义:
typedef struct
{
uint16_t TIM_OCMode;
uint16_t TIM_OutputState;
uint16_t TIM_OutputNState;
uint16_t TIM_Pulse;
uint16_t TIM_OCPolarity;
uint16_t TIM_OCNPolarity;
uint16_t TIM_OCIdleState;
uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef;
这里我们讲解一下与我们要求相关的几个成员变量:
参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。
参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
参数 TIM_OCPolarity 用来设置极性是高还是低。
其他的参数 TIM_OutputNState, TIM_OCNPolarity, TIM_OCIdleState 和 TIM_OCNIdleState 是
高级定时器 TIM1 和 TIM8 才用到的。
要实现我们上面提到的场景, 方法是:
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择 PWM 模式 1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OC1Init(TIM4, &TIM_OCInitStructure); //初始化 TIM3 OC2
4) 使能 TIM4。
在完成以上设置了之后,我们需要使能 TIM4。
TIM_Cmd(TIM4, ENABLE); //使能 TIM4
5) 修改 TIM4_CCR1 来控制占空比。
最后,在经过以上设置之后, PWM 其实已经开始输出了,只是其占空比和频率都是固定的,而我们通过修改 TIM4_CCR1 则可以控制 CH1的输出占空比。继而控制电机的速度,在库函数中,修改 TIM4_CCR1 占空比的函数是:
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare2);
理所当然,对于其他通道,分别有一个函数名字, 函数格式为 TIM_SetComparex(x=1,2,3,4)。
通过以上 6 个步骤,我们就可以控制 TIM4 的 CH1 输出 PWM 波了,另一个电机如下TIM4的CH2。
#define LeftMotorPWM(Speed) TIM_SetCompare2(TIM4, Speed);
#define RightMotorPWM(Speed) TIM_SetCompare1(TIM4, Speed);
4、实验步骤
4-1.看懂原理图
图4-1 STM32主控板电路图
图4-2 电机驱动芯片TB6612FNG
4-2.理解原理图
由图4-1和4-2 由电路原理图可知AIN1,AIN2,PWMA,BIN1,BIN2,PWMB分别接在STM32主控板上的PB8,PB9,PB7 ,PB5,PB4,PB6。
图4-3 引脚控制逻辑表
4-3 核心程序代码如下
电机PWM初始化
电机GPIO初始化
小车运动函数
初始化函数:
主函数: