由于tb6612缺货,价格太高。以后需要改造电路。使用双重。PWM控制电机。 PWM口分配 P1–定时器1的两个通道CH1-E9 --CH2-E11 P2–定时器1的两个通道CH3-E13 -CH4-E14
P3–定时器9的两个通道CH1 E5 --CH2-E6 P4 定时器12的两个通道CH1(PB14)CH2-PB15
舵机 定时器8 (舵机1)CH1-C6 (舵机2)CH2-C7 (舵机3)CH3-C8 CH4-C9(注意,
分配到这里MPU6050的中断) (舵机4)定时器10–PB8 (舵机5)定时器11–PB9 (舵机6)定时器13–PA6 (舵机7)定时器14–PA7
定时器2、定时器3、定时器4、定时器5均用作编码器
定时器6作为心跳
定时器7是另一种心跳。
这样,大多数驱动器都可以适应。以后我会自己做一个小驱动器。更新实验室的学习板。
更新的电机函数是 dcmotor2.h
/* 明确目的:控制四路直流电机 利用双PWM控制电机。 P1-定时器1的两个通道CH1-E9 --CH2-E11 P2-定时器1的两个通道CH3-E13 -CH4-E14 P3-定时器9的两个通道CH1 E5 --CH2-E6 P4 定时器12的两个通道CH1(PB14)CH2-PB15 舵机 定时器8 (舵机1)CH1-C6 (舵机2)CH2-C7 (舵机3)CH3-C8 CH4-C9(注意,分配到这里MPU6050的中断) (舵机4)定时器10--PB8 (舵机5)定时器11--PB9 (舵机6)定时器13--PA6 (舵机7)定时器14--PA7 定时器2、定时器3、定时器4、定时器5均用作编码器 定时器6作为心跳 定时器7是另一种心跳。 */ #ifndef __DCMOTOR2_H #define __DCMOTOR2_H #include "sys.h" ////定义直流电机端口 //是定时器1的设置,用定时器1生成PWM,控制直流电机 //设置说明:设置定时器的计时滴答为1us,由于是控制直流电机,可以设置PWM频率是10K左右; //PWM2模式(注意,如果是,PWM如果1模式从1电平转到0电平,PMW2.0电平翻转到1电平) ///测试后,调到PWM2模式,否则是相反的状态,用逻辑分析仪观察波形 ///按原理图使用GPIO引脚 //PE9--T1CH1---P3接线端口---D2/D3 //PE11-T1CH2---P4接线端口---D0/D1 //PE13-T1CH3---P1接线端口---D11/D10 //PE14-T1CH4---P2接线端口---B14/B15 //e13 pwm-tim1-ch3-----------接口端子的P1口,M-5V-B7-B6-GND-M--tim4 //d11 //d10...正交编码使用定时器4 //P1-定时器1的两个通道CH1-E9 --CH2-E11 //*******************************************以下是定时器1的配置************************************* //***************** //是定时器1的设置,用定时器1生成PWM,控制直流电机 //设置说明:设置定时器的计时滴答为1us,由于是控制直流电机,可以设置PWM频率是10K左右; //PWM2模式(注意,如果是,PWM如果1模式从1电平转到0电平,PMW2.0电平翻转到1电平) ///测试后,调到PWM2模式,否则是相反的状态,用逻辑分析仪观察波形 ///按原理图使用GPIO引脚 //PE9--T1CH1---P3接线端口---D2/D3 //PE11-T1CH2---P4接线端口---D0/D1 //PE13-T1CH3---P1接线端口---D11/D10 //PE14-T1CH4---P2接线端口---B14/B15 #define HTimer1Clk RCC_APB2Periph_TIM1 #define HTimer1CH1Port GPIOE #define HTimer1CH1Pin GPIO_Pin_9 #define HTimer1CH1PinSource GPIO_PinSource9 #define HTimer1CH1GPIOClk RCC_AHB1Periph_GPIOE #define
HTimer1CH2Port
GPIOE
#define HTimer1CH2Pin GPIO_Pin_11
#define HTimer1CH2PinSource GPIO_PinSource11
#define HTimer1CH2GPIOClk RCC_AHB1Periph_GPIOE
#define HTimer1CH3Port GPIOE
#define HTimer1CH3Pin GPIO_Pin_13
#define HTimer1CH3PinSource GPIO_PinSource13
#define HTimer1CH3GPIOClk RCC_AHB1Periph_GPIOE
#define HTimer1CH4Port GPIOE
#define HTimer1CH4Pin GPIO_Pin_14
#define HTimer1CH4PinSource GPIO_PinSource14
#define HTimer1CH4GPIOClk RCC_AHB1Periph_GPIOE
#define HTim1AddTimeTick 1
//这里是微s单位,1,因为高级定时器8是168Mhz总线,采用168分频,就是1Mhz,1微妙频率,
#define HTim1_Prescaler (168-1) //预分频系数168*HTim1AddTimeTick - 1
void HTim1_Init(u32 arr,u32 psc);//168主频
void TIM9_PWM_Init(u32 arr,u32 psc);//168主频
void TIM12_PWM_Init(u32 arr,u32 psc);//84主频
void Motor1Pwm(int DutyTemp);
void Motor2Pwm(int DutyTemp);
void Motor3Pwm(int DutyTemp);
void Motor4Pwm(int DutyTemp);
#endif
demotor2.c
#include "dcmotor2.h"
void HTim1_Init(u32 arr,u32 psc)
{
/* 定义一个 GPIO_InitTypeDef 类型的结构体 */
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* 开启定时器相关的 GPIO 外设时钟 */
RCC_AHB1PeriphClockCmd(HTimer1CH1GPIOClk, ENABLE);//
RCC_AHB1PeriphClockCmd(HTimer1CH2GPIOClk, ENABLE);//
RCC_AHB1PeriphClockCmd(HTimer1CH3GPIOClk, ENABLE);//
RCC_AHB1PeriphClockCmd(HTimer1CH4GPIOClk, ENABLE);//
GPIO_PinAFConfig(HTimer1CH1Port,HTimer1CH1PinSource,GPIO_AF_TIM1);
GPIO_PinAFConfig(HTimer1CH2Port,HTimer1CH2PinSource,GPIO_AF_TIM1);
GPIO_PinAFConfig(HTimer1CH3Port,HTimer1CH3PinSource,GPIO_AF_TIM1);
GPIO_PinAFConfig(HTimer1CH4Port,HTimer1CH4PinSource,GPIO_AF_TIM1);
/* 定时器功能引脚初始化 */
GPIO_InitStructure.GPIO_Pin = HTimer1CH1Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(HTimer1CH1Port, &GPIO_InitStructure);
/* 定时器功能引脚初始化 */
GPIO_InitStructure.GPIO_Pin = HTimer1CH2Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(HTimer1CH2Port, &GPIO_InitStructure);
/* 定时器功能引脚初始化 */
GPIO_InitStructure.GPIO_Pin = HTimer1CH3Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(HTimer1CH3Port, &GPIO_InitStructure);
/* 定时器功能引脚初始化 */
GPIO_InitStructure.GPIO_Pin = HTimer1CH4Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(HTimer1CH4Port, &GPIO_InitStructure);
// 开启 TIMx_CLK
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* 累计 TIM_Period 个后产生一个更新或者中断 */
//10khz =0.1ms=100us
TIM_TimeBaseStructure.TIM_Period = arr;
//定时器时钟源 TIMxCLK =168MHz
// 设定定时器频率为 =TIMxCLK/(TIM_Prescaler+1)=168/(168-1+1)=1MHz
TIM_TimeBaseStructure.TIM_Prescaler = psc;//1us加一次
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器 TIMx
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* ================== 输出结构体初始化 =================== */
// 配置为 PWM 模式 1,先输出高电平,达到比较值的时候再改变电平
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
// 主输出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
// 互补输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
// 配置比较值
TIM_OCInitStructure.TIM_Pulse = 500;
// 主输出高电平有效
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 互补输出高电平有效
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
// 主输出在被禁止时为高电平
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
// 互补输出在被禁止时为低电平
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
// 通道初始化
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
// 使能通道重装载
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
//定时1第二通道的设置和第一通道CH1一样;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
// 使能通道重装载
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
// 使能通道重装载
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
//定时8第二通道的设置和第一通道CH1一样;
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
// 使能通道重装载
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
// /* ================ 断路和死区结构体初始化 ================ */
// // 自动输出使能,断路、死区时间和锁定配置
// TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
// TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
// TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
// // 配置死区时间
// TIM_BDTRInitStructure.TIM_DeadTime = 11;
// TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
// // 配置刹车引脚电平,当引脚为配置的电平时,主和互补输出都被禁止
// TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
// TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
// TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);
// 能定时器
// 主动输出使能
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, DISABLE);
}
//TIM9 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM9_PWM_Init(u32 arr,u32 psc)
{
//此部分需手动修改IO口设置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//注意,定时器9用APB2时钟线168M
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE); //TIM9时钟使能
//在那个引脚产生PWM?设定对应PWM口的时钟打开,这里用E5,E6
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //使能PORTF时钟
//引脚复用
GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_TIM9); //GPIOE5复用为定时器14
GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_TIM9);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6; //GPIOE5 E6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOE,&GPIO_InitStructure); //初始化PF9
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM9,&TIM_TimeBaseStructure);//初始化定时器14
//初始化TIM9 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
TIM_OC1Init(TIM9, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OCInitStructure.TIM_Pulse = 2; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //OC1 高电平有效
TIM_OC1Init(TIM9, &TIM_OCInitStructure); //根据指定的参数初始化外设 TIMx
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable); //CH1 预装载使能
TIM_OCInitStructure.TIM_Pulse = 2; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //OC1 高电平有效
TIM_OC2Init(TIM9, &TIM_OCInitStructure); //根据指定的参数初始化外设 TIMx
TIM_OC2PreloadConfig(TIM9, TIM_OCPreload_Enable); //CH1 预装载使能
TIM_ARRPreloadConfig(TIM9,ENABLE);//ARPE使能
TIM_Cmd(TIM9, DISABLE); //使能TIM14
}
//TIM12 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
//B14--B15
void TIM12_PWM_Init(u32 arr,u32 psc)
{
//此部分需手动修改IO口设置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//注意,定时器12用APB1时钟线
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12,ENABLE); //TIM9时钟使能
//在那个引脚产生PWM?设定对应PWM口的时钟打开,这里用B14--B15
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能PORTF时钟
//引脚复用
GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_TIM12);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_TIM12);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15; //GPIOE5 E6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化PF9
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM12,&TIM_TimeBaseStructure);//初始化定时器14
//初始化TIM9 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
TIM_OC1Init(TIM12, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OCInitStructure.TIM_Pulse = 2; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //OC1 高电平有效
TIM_OC1Init(TIM12, &TIM_OCInitStructure); //根据指定的参数初始化外设 TIMx
TIM_OC1PreloadConfig(TIM12, TIM_OCPreload_Enable); //CH1 预装载使能
TIM_OCInitStructure.TIM_Pulse = 2; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //OC1 高电平有效
TIM_OC2Init(TIM12, &TIM_OCInitStructure); //根据指定的参数初始化外设 TIMx
TIM_OC2PreloadConfig(TIM12, TIM_OCPreload_Enable); //CH1 预装载使能
TIM_ARRPreloadConfig(TIM12,ENABLE);//ARPE使能
TIM_Cmd(TIM12, DISABLE);
}
//P1--定时器1的两个通道CH1-E9 --CH2-E11
void Motor1Pwm(int DutyTemp)
{
if(DutyTemp==0)
{
TIM_SetCompare1(TIM1,0);
TIM_SetCompare2(TIM1,0);
return;
}
if(DutyTemp>4000) DutyTemp = 4000; //输出PWM限幅
if(DutyTemp<-4000)DutyTemp = -4000;
if(DutyTemp>0)
{
TIM_SetCompare1(TIM1,DutyTemp);
TIM_SetCompare2(TIM1,0);
}
else
{
TIM_SetCompare1(TIM1,0);
TIM_SetCompare2(TIM1,-DutyTemp);
}
}
//P2--定时器1的两个通道CH3-E13 -CH4-E14
void Motor2Pwm(int DutyTemp)
{
if(DutyTemp==0)
{
TIM_SetCompare3(TIM1,0);
TIM_SetCompare4(TIM1,0);
return;
}
if(DutyTemp>4000) DutyTemp = 4000; //输出PWM限幅
if(DutyTemp<-4000)DutyTemp = -4000;
if(DutyTemp>0)
{
TIM_SetCompare3(TIM1,DutyTemp);
TIM_SetCompare4(TIM1,0);
}
else
{
TIM_SetCompare3(TIM1,0);
TIM_SetCompare4(TIM1,-DutyTemp);
}
}
//P3--定时器9的两个通道CH1 E5 --CH2-E6
void Motor3Pwm(int DutyTemp)
{
if(DutyTemp==0)
{
TIM_SetCompare1(TIM9,0);
TIM_SetCompare2(TIM9,0);
return;
}
if(DutyTemp>4000) DutyTemp = 4000; //输出PWM限幅
if(DutyTemp<-4000)DutyTemp = -4000;
if(DutyTemp>0)
{
TIM_SetCompare1(TIM9,DutyTemp);
TIM_SetCompare2(TIM9,0);
}
else
{
TIM_SetCompare1(TIM9,0);
TIM_SetCompare2(TIM9,-DutyTemp);
}
}
//P4 定时器12的两个通道CH1(PB14)CH2-PB15
void Motor4Pwm(int DutyTemp)
{
if(DutyTemp==0)
{
TIM_SetCompare1(TIM12,0);
TIM_SetCompare2(TIM12,0);
return;
}
if(DutyTemp>4000) DutyTemp = 4000; //输出PWM限幅
if(DutyTemp<-4000)DutyTemp = -4000;
if(DutyTemp>0)
{
TIM_SetCompare1(TIM12,DutyTemp);
TIM_SetCompare2(TIM12,0);
}
else
{
TIM_SetCompare1(TIM12,0);
TIM_SetCompare2(TIM12,-DutyTemp);
}
}
main.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "oled.h"
#include "extizd.h"
#include "BaseTimX.h"
#include "htimx.h"
#include "dcmotor2.h"
//第一步,包含这两个头文件
#include "IOI2C.h"
#include "MPU6050.h"
int int1=10;
int int2=12;
float float1=1.5;
float float2=10.25;
//关于陀螺仪的学习https://www.bilibili.com/video/BV15g411N7SM/?spm_id_from=333.788 ,第15讲1小时10分开始,看20分钟,获取陀螺仪的角速度
void oledPage0()
{
OLED_ShowChar(0,0,'Z');
OLED_ShowChar(1*8,0,'P');
OLED_ShowChar(2*8,0,'0');
OLED_S