c 控制代码
? 由于本项目电机负载较小,步进电机的开环控制已经可以满足性能要求,下面以开环步进电机控制进行说明。
电机驱动器根据PWM波脉冲频率控制步进电机转速,根据脉冲数控制转角度数,根据方向电平控制电机转向,根据使能电平控制电机的启停,这就要求控制器能够提供频率和脉冲数可变的PWM波,高低电平可控的方向电平和使能电平。下图为单片机产生PWM波和高低电平的方法分类:
? 控制系统要求:四路脉冲数频率可控的PWM输出、四路方向电平、接收到控制信号后输出指定脉冲数后停止
? 比较各种方法优缺点后,最后选择双定时器生成PWM波,基本IO口输出模式生成方向电平。双定时器方法原理:定时器a产生PWM输出(可输出频率相同的多路PWM),定时器b控制时间,定时器a输出打开(占空比设为50%)同时定时器b开始计时,定时器b溢出中断时关闭定时器a的PWM输出(占空比设为0%),脉冲数计算公式如下:
脉
冲
数
=
P
W
M
频
率
(
k
H
Z
)
?
时
间
基
准
(
m
s
)
脉冲数 = PWM频率(kHZ)*时间基准(ms)
脉冲数=PWM频率(kHZ)?时间基准(ms) 如果我们需要1s输出10000个脉冲,那就应该设置PWM频率为10kHZ,时间基准为1000ms。
? 具体方案:采用高级定时器TIM8产生4路PWM波,TIM7和TIM3提供时间基准,四个基本IO口配置为输出模式作为方向电平的输出。STM32F407ZGT6芯片引脚复用情况如下表:
TIM8 CH1 | TIM8 CH2 | TIM8 CH3 | TIM8 CH4 | motorA dir | motorB dir | motorC dir | motorD dir |
---|
GPIOC_Pin_6(PC6) | PC7 | PC8 | PC9 | PC2 | PC3 | PB12 | PB13 |
? .h代码如下:
#ifndef STEP_MOTOR_H_
#define STEP_MOTOR_H_
#include "sys.h"
#define TIM3_set_arr 6400-1
#define TIM3_set_psc 8400-1
#define TIM7_set_arr 9216-1
#define TIM7_set_psc 8400-1
#define TIM8_set_arr 2100-1
#define TIM8_set_psc 8-1
#define Moter_A_1 PCout(2)
#define Moter_B_1 PCout(3)
#define Moter_C_1 PBout(12)
#define Moter_D_1 PBout(13)
#define Step_Motor_duty 500
void Motor_Pamar_Init(void);
void Set_Target_Angle_A0(void);
void Set_Target_Angle_A1(void);
void Set_Target_Angle_B0(void);
void Set_Target_Angle_B1(void);
void Set_Target_Angle_C0(void);
void Set_Target_Angle_C1(void);
void Set_Target_Angle_D0(void);
void Set_Target_Angle_D1(void);
void TIM3_Int_Init(u16 arr,u16 psc);
void TIM7_Int_Init(u16 arr,u16 psc);
void TIM8_PWM_Init(u16 arr,u16 psc);
void Moter_IOs_Init(void);
void Moter_Init(void);
#endif
? .c代码如下:
#include "Step_Motor.h"
#include "usart.h"
#include "delay.h"
int Moter_Count[4];
void Moter_Init(void)
{
Moter_IOs_Init();
TIM8_PWM_Init(TIM8_set_arr,TIM8_set_psc);
TIM3_Int_Init(TIM3_set_arr,TIM3_set_psc);
TIM7_Int_Init(TIM7_set_arr,TIM7_set_psc);
Motor_Pamar_Init();
}
void Motor_Pamar_Init(void)
{
Moter_Count[0] = 0;
Moter_Count[1] = 0;
Moter_Count[2] = 0;
Moter_Count[3] = 0;
}
void Set_Target_Angle_A0(void)
{
Moter_Count[0]--;
if (Moter_Count[0] <= 5 && Moter_Count[0] >= -5)
{
Moter_A_1 = 0;
TIM_Cmd(TIM7,ENABLE);
TIM_SetCompare1(TIM8,Step_Motor_duty);
}
}
void Set_Target_Angle_A1(void)
{
Moter_Count[0]++;
if (Moter_Count[0] <= 5 && Moter_Count[0] >= -5)
{
Moter_A_1 = 1;
TIM_Cmd(TIM7,ENABLE);
TIM_SetCompare1(TIM8,Step_Motor_duty);
}
}
void Set_Target_Angle_B0(void)
{
Moter_Count[1]--;
if (Moter_Count[1] <= 5 && Moter_Count[1] >= -5)
{
Moter_B_1 = 0;
TIM_Cmd(TIM7,ENABLE);
TIM_SetCompare2(TIM8,Step_Motor_duty);;
}
}
void Set_Target_Angle_B1(void)
{
Moter_Count[1]++;
if (Moter_Count[1] <= 5 && Moter_Count[1] >= -5)
{
Moter_B_1 = 1;
TIM_Cmd(TIM7,ENABLE);
TIM_SetCompare2(TIM8,Step_Motor_duty);
}
}
void Set_Target_Angle_C0(void)
{
Moter_Count[2]--;
if (Moter_Count[2] <= 5 && Moter_Count[2] >= -5)
{
Moter_C_1 = 0;
TIM_Cmd(TIM7,ENABLE);
TIM_SetCompare3(TIM8,Step_Motor_duty);
}
}
void Set_Target_Angle_C1(void)
{
Moter_Count[2]++;
if (Moter_Count[2] <= 5 && Moter_Count[2] >= -5)
{
Moter_C_1 = 1;
TIM_Cmd(TIM7,ENABLE);
TIM_SetCompare3(TIM8,Step_Motor_duty);
}
}
void Set_Target_Angle_D0(void)
{
Moter_Count[3]--;
if (Moter_Count[3] <= 5 && Moter_Count[3] >= -5)
{
Moter_D_1 = 0;
TIM_Cmd(TIM3,ENABLE);
TIM_SetCompare4(TIM8,Step_Motor_duty);
}
}
void Set_Target_Angle_D1(void)
{
Moter_Count[3]++;
if (Moter_Count[3] <= 5 && Moter_Count[3] >= -5)
{
Moter_D_1 = 1;
TIM_Cmd(TIM3,ENABLE);
TIM_SetCompare4(TIM8,Step_Motor_duty);
}
}
void Moter_IOs_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_12;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void TIM8_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7| GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6 ,GPIO_AF_TIM8);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM8);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_TIM8);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_TIM8);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInitStructure.TIM_Period = arr;
TIM_TimeBaseInit(TIM8,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OC1Init(TIM8,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC2Init(TIM8,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC3Init(TIM8,&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC4Init(TIM8,&TIM_OCInitStructure);
TIM_Cmd(TIM8,ENABLE);
TIM_CtrlPWMOutputs(TIM8,ENABLE);
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseInitStructure.TIM_Period = arr;
TIM_TimeBaseInitStructure.TIM_Prescaler=psc;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
TIM_SetCompare4(TIM8,0);
}
TIM_Cmd(TIM3,DISABLE);
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
void TIM7_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
TIM_TimeBaseInitStructure.TIM_Period = arr;
TIM_TimeBaseInitStructure.TIM_Prescaler=psc;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM7,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=TIM7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x03;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM7_IRQHandler(void)
{
if(TIM_GetITStatus(TIM7,TIM_IT_Update)==SET)
{
TIM_SetCompare1(TIM8,0);
TIM_SetCompare2(TIM8,0);
TIM_SetCompare3(TIM8,0);
}
TIM_Cmd(TIM7,DISABLE);
TIM_ClearITPendingBit(TIM7,TIM_IT_Update);
}
|