做一份笔记,大佬勿喷。
注意:本博客是以《2018年华北五省(市、自治区)大学生机器人大赛竞赛规则》为基础而写的
光电开关初始化:
#define up_for_lift GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define up_for_right GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
#define up_back_left GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4)
#define up_back_right GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)
#define for_1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)
#define for_2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)
#define for_3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)
#define back_1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)
#define back_2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)
#define left_1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)
#define left_2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
#define right_1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)
#define right_2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)
#define for_lift GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0)
#define for_right GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)
#define back_lift GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)
#define back_right GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3)
#define down_1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4)
#define down_2 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)
#define down_3 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6)
//光电开关初始化
void optoelect_switch()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能A端口时钟
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;
GPIO_Init(GPIOC, &GPIO_InitStructure); //浮空输入 ,IO口速度为50MHz
}
测试主函数:
void GD_oled(void)
{
int a;
//铲子
a=up_for_lift;
OLED_ShowNum( 0,0,a,1,12);
a=up_for_right;
OLED_ShowNum(18,0,a,1,12);
up_back_left;
OLED_ShowNum(36,0,a,1,12);
a=up_back_right;
OLED_ShowNum(54,0,a,1,12);
//前
a=for_1 ;
OLED_ShowNum( 0,2,a,1,12);
a=for_3;
OLED_ShowNum(18,2,a,1,12);
a=for_lift ;
OLED_ShowNum(36,2,a,1,12);
a=for_right;
OLED_ShowNum(54,2,a,1,12);
//中
a=left_1;
OLED_ShowNum( 0,4,a,1,12);
a=left_2;
OLED_ShowNum(18,4,a,1,12);
a=right_1;
OLED_ShowNum(36,4,a,1,12);
a=right_2;
OLED_ShowNum(54,4,a,1,12);
//后
a=back_1;
OLED_ShowNum( 0,6,a,1,12);
a= back_2 ;
OLED_ShowNum(18,6,a,1,12);
a=back_lift;
OLED_ShowNum(36,6,a,1,12);
a= back_right;
OLED_ShowNum(54,6,a,1,12);
delay_ms(800);//刷新时间
OLED_Clear();//清屏
}
电机和电机驱动我们均使用的是得科技术(淘宝店铺)
☆☆☆☆☆使用直流电机驱动正转过程中,应该先0(0%PWM)速100ms以上,等物流二极管续流后,再反转。这样可以避免瞬间反转导致的高压高流,击穿mos管。。。。(可不加)
☆☆☆☆☆PWM频率必须高于1K以上,4K-20K都可以。(一定保证)
☆☆☆☆☆因为驱动半桥需要自举生压,PWM占空比必须小于98%。最好在95%以下。(一定保证)
1、电机电源接通,中间一定要通过开关来上电,不能直接电池插入,容易产生火花产生高压,击穿板子。5V和GND各引出2路,方便2块板子组成四驱时接线。普通接一个就行。注意:如果单片机供电为3.3v,那么使能端也将为3.3v
2、上电顺序:可以驱动电源和右边8P接口的5V一起上电。如果测试,而且不同时上电,那么先上电+5V和GND,再上电电机电源。
3、5V和GND是控制器板子给驱动板供电,一定要接入。不要只接了IN1-4,没有接5V和GND。IN1和IN2控制左边的驱动,IN3和IN4控制右边的驱动。当IN1给PWM,IN2给0,即正转,当IN1给0,IN2给PWM,即反转。二边都给0,或者给反方向速度就刹车。
4、驱动普通功率电机,一个电机驱动端子可以并联接2个电机,这样一块驱动板可以驱动4个电机。如果接大功率擂台电机,那么尽量用2块驱动板,驱动4个电机,组成四驱。
5、驱动板的电源GND 和5V接口的GND 为同一个地。接线时候务必小心确认这2个GND为同一个GND。以免发生GND短路。
void speed_Configuration(void)
{
//**********电机驱动设置************//
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟
TIM_DeInit(TIM3);//初始化TIM1寄存器
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //Timer1完全重映射 TIM1_CH1->PE9 CH2->PE11 CH1->PE13 CH1->PE14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; //TIM1_CH1 //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIOE.9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO
//**************************************************************************
// 定时器1设置: 72分频,频率10KHz,向上计数,105是为了速度为100时,PWM占空比不会到100,方便电机驱动自举生压。一般PWM频率大于1K,4-10K比较好。
//**************************************************************************
TIM_TimeBaseStructure.TIM_Period = 105-1;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// 主定时器T4为 PWM1 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器
TIM_ARRPreloadConfig(TIM3, ENABLE); //使能定时器1
TIM_Cmd(TIM3, ENABLE);
}
//2个PWM口控制一路电机。IN1给PWM,IN2给0,正转;IN1给0,IN2给PWM,反转。
void Motor(u8 port, s8 speed)
{
if(speed >= 0)
{
if(speed>100) speed=100;
switch(port)
{
case 1:
TIM3->CCR1 = speed;
TIM3->CCR2 = 0;
break;
case 2:
TIM3->CCR3 = speed;
TIM3->CCR4 = 0;
break;
}
}
else
{
if(speed<-100) speed=-100;
switch(port)
{
case 1:
TIM3->CCR1 = 0;
TIM3->CCR2 = -speed;
break;
case 2:
TIM3->CCR3 = 0;
TIM3->CCR4 = -speed;
break;
}
}
}