YouSuanZhi/Core/Src/StepMotor.c
2025-12-30 15:21:11 +08:00

660 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "APPDEF.H"
enum enumPumpSelect PumpSelect[pumpMax];
/******************************** 功能说明 *************************************
*
*******************************************************************************/
void Motor_IECMD( enum enumPumpSelect Select, _Bool CMD )
{
switch( Select )
{
case M1:
TIM4_IECMD( CMD );
break;
case M2:
TIM3_IECMD( CMD );
break;
default:
break;
}
}
/********************************** 功能说明 *************************************
* 机械臂运行速度设置
*********************************************************************************/
/********************************** 功能说明 *************************************
* 机械臂运行速度设置
*********************************************************************************/
void Motor_PWM( enum enumPumpSelect Select, uint16_t Value )
{
switch( Select )
{
case M1:
TIM4_CH1_CTRL( Value, Value / 2 );
break;
case M2:
TIM3_CH2_CTRL( Value, Value / 2 );
break;
default:
break;
}
}
/********************************** 功能说明 *************************************
* 机械臂PWM开关
*********************************************************************************/
void Motor_PWMCmd( enum enumPumpSelect Select, _Bool State )
{
switch( Select )
{
case M1:
TIM4_CH1_CMD( State );
break;
case M2:
TIM3_CH2_CMD( State );
break;
default:
break;
}
}
/********************************** 功能说明 *************************************
* 机械臂运行方向设置
*********************************************************************************/
void Motor_Dir( enum enumPumpSelect Select, _Bool State )
{
switch( Select )
{
case M1:
// TIM4_CH1_DIR( State);
break;
default:
break;
}
}
/********************************** 功能说明 *************************************
* 机械臂控制器使能
*********************************************************************************/
void Motor_En( enum enumPumpSelect Select, _Bool State )
{
switch( Select )
{
case M1:
break;
default:
break;
}
}
/******************************** 功能说明 *************************************
* TIMx 中断处理函数
*******************************************************************************/
volatile uint32_t SetPluseCount[7u]; // 设置运行脉冲数
volatile uint32_t PluseCount[7u]; // 实际运行脉冲数
volatile _Bool CountOver[7u] = {false}; // 计数器溢出标志
volatile uint32_t SamplePumpSetPluseCount[7u]; // 设置运行脉冲数
volatile uint32_t SamplePumpPluseCount[7u]; // 实际运行脉冲数
volatile _Bool SamplePumpCountOver[7u] = {false}; // 计数器溢出标志
/********************************** 功能说明 *************************************
* 机械臂运行任务
*********************************************************************************/
const uint32_t FullCoordinate[pumpMax] = { 20500u, 65000u,65000u };
int32_t CoordinateSet[pumpMax]; // 目标位置
int32_t CoordinatePosition[pumpMax]; // 实时更新实时位置
uint32_t Position[pumpMax]; // 本次运行起始位置
_Bool TaskisRunning[pumpMax] = {0}; // 防止重入标志
_Bool IdelEn[pumpMax] = { false,false,false}; // 电机空闲使能
int32_t DCMotorSpeed[pumpMax]; // 直流电机速度
uint32_t CoordinateSetOld[pumpMax]; // 上次所在位置
int32_t Differ[pumpMax]; // 本次所需运行脉冲数
float SpeedSet[pumpMax]={ 100.0f, 1000.0f, 5000.0f }; // 最高速度p/s
uint32_t period[pumpMax] = { 20000u, 2000u, 2000u }; // PWM实时周期
float Velocity[pumpMax] = { 0.0f, 20.0f, 20.0f }; // 实时速度
uint32_t Shifting[pumpMax] = { 500u, 500u, 500u }; // 加速过程脉冲数
float Speeda[pumpMax] ={ 10000.0f, 10000.0f, 10000.0f }; // 加速度 p/(s*s)
float VelocityH[pumpMax]={ 10000.0f, 5000.0f, 5000.0f }; // 最高速度p/s
float VelocityL[pumpMax]={ 10.0f, 1000.0f, 1000.0f }; // 最低速度p/s
float ShiftPluse[pumpMax]={ 100.0f, 1500.0f, 1500.0f }; // 标准最大加速过程脉冲数
float VelocityMax[pumpMax] = { 10000.0f, 20.0f, 20.0f }; // 最大速度
_Bool Direction[pumpMax] = { false,false,false}; // 运行方向
/******************************** 功能说明 *************************************
* 速度加速度转换
*******************************************************************************/
static uint16_t SpeedOld[pumpMax];
_Bool PumpShutDown[pumpMax] = {false, false}; // 急停标志
_Bool DirectionSet[pumpMax]; // 目标方向
_Bool ENSet[pumpMax] = {false,false,false}; // 是否使能电机
void SamplePumpSpeed_AcceleratedConver( enum enumPumpSelect Select, uint16_t Speed )
{
if( Speed != SpeedOld[Select] )
{
Speeda[Select] = (Speed * Speed) / (2u * ShiftPluse[Select]);
SpeedOld[Select] = Speed;
}
}
/******************************** 功能说明 *************************************
*
*******************************************************************************/
_Bool SpeedMode[pumpMax];
_Bool PositionMode[pumpMax];
_Bool FindZero[pumpMax];
_Bool FindedZero[pumpMax];
void SamplePumpCtrl( enum enumPumpSelect Select )
{
// for(;;)
{
if((CoordinateSet[Select] != 0u) && (!TaskisRunning[Select]))
{
SamplePumpSpeed_AcceleratedConver(Select,SpeedSet[Select]);
TaskisRunning[Select] = true; // 置位 防重入标志
VelocityMax[Select] = 0;
period [Select] = 2000u;
Velocity[Select] = 6.0f;
Shifting[Select] = 100u;
PluseCount[Select] = 0u; // 清零计数脉冲
CountOver[Select] = false; // 清除计数器溢出
SetPluseCount[Select] = CoordinateSet[Select]; // 设置泵运行脉冲
Motor_IECMD( Select, true);
Motor_Dir ( Select, DirectionSet[Select] ); // 选择方向
Motor_PWM ( Select, 100000.0f / VelocityL[Select] ); // 重置pwm为最低输出
osDelay( 50u );
Motor_En ( Select, true ); // 步进电机控制器控制使能
Shifting[Select] = SetPluseCount[Select] / 2u;
if( Shifting[Select] > ShiftPluse[Select] )
Shifting[Select] = ShiftPluse[Select];
Motor_PWMCmd( Select, true ); // 开启脉冲输出
while( !CountOver[Select] ) // 计数器没有溢出
{
if(PumpShutDown[Select])
{
PumpShutDown[Select] = false;
break;
}
if( PluseCount[Select] < Shifting[Select] ) // 前Shifting[Select]脉冲加速
{
Velocity[Select] = sqrt( 2* PluseCount[Select] * (Speeda[Select]/* / 2u*/));
if( VelocityMax[Select] < Velocity[Select] )
VelocityMax[Select] = Velocity[Select];
if(Velocity[Select] > VelocityH[Select])
Velocity[Select] = VelocityH[Select];
if(Velocity[Select] < VelocityL[Select] )
Velocity[Select] = VelocityL[Select];
if( Velocity[Select] > SpeedOld[Select])
Velocity[Select] = SpeedOld[Select];
period[Select] = 100000.0f / Velocity[Select];
Motor_PWM( Select, period[Select] );
}
else // 中间匀速
if( PluseCount[Select] <= (SetPluseCount[Select] - Shifting[Select]) )
{
period[Select] = 100000.0f / SpeedOld[Select];
Motor_PWM( Select, period[Select] );
while(CoordinateSet[Select] == 65535u)
{
PluseCount[Select] = 0;
osDelay( 5u );
}
if(CoordinateSet[Select] == 0u)
{
SetPluseCount[Select] = Shifting[Select]*2;
PluseCount[Select] = Shifting[Select]+1;
}
}
else // 后Shifting[Select]脉冲减速
// if( PluseCount[Select] >= (SetPluseCount[Select] - Shifting[Select]) )
{
Velocity[Select] = sqrt( 2* (SetPluseCount[Select] - (float)PluseCount[Select]) * (Speeda[Select] / 2u));
if(Velocity[Select] > VelocityH[Select])
Velocity[Select] = VelocityH[Select];
if(Velocity[Select] < VelocityL[Select] )
Velocity[Select] = VelocityL[Select];
period[Select] = 100000.0f / Velocity[Select];
Motor_PWM( Select, period[Select] );
}
osDelay( 5u );
}
// usRegHoldingBuf[20u+Select*5u] = 0u;
osDelay( 15u );
CoordinateSet[Select] = 0u;
Motor_En( Select, ENSet[Select] ); // 步进电机控制器控制使能
TaskisRunning[Select] = false; // 清除防重入标志
CountOver[Select] = false; // 清除计数器溢出
osDelay( 15u );
}
else
{
osDelay(15);
}
}
}
static bool ArmInitIsRuning[pumpMax] = { false,false,false};
/********************************** 功能说明 *************************************
* 机械臂运行任务
*********************************************************************************/
void ArmSoftCtrl( enum enumPumpSelect Select )
{
/*Vmin = 50p/s Vmax = 20000p/s At = 0.2s a = 100000p/s2 △s = 2000p △t = 0.001s P = 0.000001s */
//#define LowSpeed 40.0f
// for(;;)
{
if(
(CoordinateSet[Select] != CoordinateSetOld[Select]) // 如果目标位置与当前位置不同
&& !TaskisRunning[Select] // 如果此任务没有正在运行
&&!( ArmInitIsRuning[M3] // 且所有的任务没有正在初始化
)
)
{
TaskisRunning[Select] = true; // 置位 防重入标志
VelocityMax[Select] = 0;
if( CoordinateSet[Select] > FullCoordinate[Select])
{
/*usRegHoldingBuf[7] = */CoordinateSet[Select] = CoordinateSetOld[Select];
osDelay(15); // 极限位置保护
}
period [Select] = 20000u; //周期
Velocity[Select] = 500.0f; //实时速度
Shifting[Select] = 1500u; //加速脉冲
CoordinateSetOld[Select] = CoordinateSet[Select]; //
PluseCount[Select] = 0u; // 清零计数脉冲
CountOver[Select] = false; // 清除计数器溢出
Differ[Select] = CoordinateSet[Select] - CoordinatePosition[Select]; // 计算设置位置与当前位置的偏差和方向
if(Differ[Select] != 0)
{
if( Differ[Select] > 0 )
Direction[Select] = true;
if( Differ[Select] < 0 )
Direction[Select] = false;
SetPluseCount[Select] = abs( Differ[Select]); // 设置泵运行脉冲
Position[Select] = CoordinatePosition[Select];
Motor_IECMD( Select, true);
Motor_Dir ( Select, ( Differ[Select] >= 0 ) ? false : true ); // 选择方向
Motor_PWM ( Select, period[Select] ); // 重置pwm为最低输出
osDelay( 50u );
Shifting[Select] = abs(Differ[Select]) / 2u;
if( Shifting[Select] > ShiftPluse[Select] )
Shifting[Select] = ShiftPluse[Select];
Motor_PWMCmd( Select, true ); // 开启脉冲输出
Motor_En ( Select, true ); // 步进电机控制器控制使能
while( !CountOver[Select] ) // 计数器没有溢出
{
// 前Shifting[Select]脉冲加速至匀速并匀速运行
if( PluseCount[Select] <= (abs(Differ[Select]) - Shifting[Select]) )
{
if( Velocity[Select] < SpeedOld[Select])
{
Velocity[Select] = sqrt( 2* PluseCount[Select] * (Speeda[Select] / 2u));
if( Velocity[Select] > SpeedOld[Select])
Velocity[Select] = SpeedOld[Select];
if( VelocityMax[Select] < Velocity[Select] )
VelocityMax[Select] = Velocity[Select];
if(Velocity[Select] > VelocityH[Select])
Velocity[Select] = VelocityH[Select];
if(Velocity[Select] < VelocityL[Select] )
Velocity[Select] = VelocityL[Select];
period[Select] = 1000000.0f / Velocity[Select];
Motor_PWM( Select, period[Select] );
}
}
else//if( PluseCount[Select] >= (abs(Differ) - Shifting[Select]) ) // 后Shifting[Select]脉冲减速
{
Velocity[Select] = sqrt( 2* (abs(Differ[Select]) - (float)PluseCount[Select]) * (Speeda[Select] / 2u));
if( VelocityMax[Select] < Velocity[Select] )
VelocityMax[Select] = Velocity[Select];
if(Velocity[Select] > VelocityH[Select])
Velocity[Select] = VelocityH[Select];
if(Velocity[Select] < VelocityL[Select] )
Velocity[Select] = VelocityL[Select];
period[Select] = 1000000.0f / Velocity[Select];
Motor_PWM( Select, period[Select] );
}
osDelay( 1u );
if( Differ[Select] >= 0 ) // 根据方向偏差来计算当前位置
{
CoordinatePosition[Select] = Position[Select] + PluseCount[Select];
}
else
{
CoordinatePosition[Select] = Position[Select] - PluseCount[Select];
}
}
if( Differ[Select] >= 0 ) // 根据最终计数来计算最终位置
{
CoordinatePosition[Select] = Position[Select] + PluseCount[Select];
}
else
{
CoordinatePosition[Select] = Position[Select] - PluseCount[Select];
}
}
Velocity[Select] = 0;
TaskisRunning[Select] = false; // 清除防重入标志
CountOver[Select] = false; // 清除计数器溢出
osDelay( 5u );
}
else
{
osDelay(15);
}
}
}
//_Bool SpeedMode[pumpMax];
//_Bool PositionMode[pumpMax];
void MotorCtrl(enum enumPumpSelect Select)
{
// static _Bool SpeedModeOld[pumpMax];
// static _Bool PositionModeOld[pumpMax];
for(;;)
{
// if( SpeedModeOld[Select] != SpeedMode[Select])
// {
// SpeedModeOld[Select] = SpeedMode[Select];
// Motor_IECMD( Select, SpeedModeOld[Select]);
// }
// if( PositionModeOld[Select] != PositionMode[Select])
// {
// PositionModeOld[Select] = PositionMode[Select];
// }
// if( PositionMode[Select] )
// {
// SamplePumpCtrl(Select);
// }
switch(Select)
{
case M1:
case M2:
SamplePumpCtrl(Select);
break;
case M3:
ArmSoftCtrl(Select);
break;
default:
break;
}
}
}
#include "stm32f10x.h"
/******************************** 功能说明 *************************************
* 中断端口初始化使能
*******************************************************************************/
void BIOS_EXTI_Init( void )
{
// // 浮空输入模式
SET_BIT( RCC->APB2ENR, RCC_APB2ENR_IOPBEN );
GPIOB->BSRR |= 0x0002u; // 端口输出为1
// GPIOF->BSRR |= 0x3800u; // 端口输出为1
// GPIOE->BSRR |= 0x0040u; // 端口输出为1
// SET_BIT( GPIOC->PUPDR, GPIO_PUPDR_PUPD0_0|GPIO_PUPDR_PUPD1_0|GPIO_PUPDR_PUPD2_0|GPIO_PUPDR_PUPD3_0 ); // IO口配置 上拉
// SET_BIT( GPIOF->PUPDR, GPIO_PUPDR_PUPD11_0|GPIO_PUPDR_PUPD12_0|GPIO_PUPDR_PUPD13_0 ); // IO口配置 上拉
CLEAR_BIT( GPIOB->CRL, GPIO_CRL_CNF1_0 );
SET_BIT( GPIOB->CRL, GPIO_CRL_CNF1_1 );
SET_BIT( GPIOB->ODR, GPIO_ODR_ODR1 ); // IO口配置 上拉
// MODIFY_REG( GPIOC->MODER, GPIO_MODER_MODE0, GPIO_MODER_MODE0_1 ); // IO口配置 复用输出
// MODIFY_REG( GPIOC->MODER, GPIO_MODER_MODE1, GPIO_MODER_MODE1_1 ); // IO口配置 复用输出
// MODIFY_REG( GPIOC->MODER, GPIO_MODER_MODE2, GPIO_MODER_MODE2_1 ); // IO口配置 复用输出
// MODIFY_REG( GPIOC->MODER, GPIO_MODER_MODE3, GPIO_MODER_MODE3_1 ); // IO口配置 复用输出
// MODIFY_REG( GPIOF->MODER, GPIO_MODER_MODE11, GPIO_MODER_MODE11_1 ); // IO口配置 复用输出
// MODIFY_REG( GPIOF->MODER, GPIO_MODER_MODE12, GPIO_MODER_MODE12_1 ); // IO口配置 复用输出
// MODIFY_REG( GPIOF->MODER, GPIO_MODER_MODE13, GPIO_MODER_MODE13_1 ); // IO口配置 复用输出
// SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);
// // 开启中断复用
// SYSCFG->EXTICR[0] =
// SYSCFG_EXTICR1_EXTI1_PC
// |SYSCFG_EXTICR1_EXTI1_PC
// |SYSCFG_EXTICR1_EXTI2_PC
// |SYSCFG_EXTICR1_EXTI3_PC
;
// SYSCFG->EXTICR[1] =
// SYSCFG_EXTICR2_EXTI6_PF;
// SYSCFG->EXTICR[2] =
// SYSCFG_EXTICR3_EXTI11_PF;
// SYSCFG->EXTICR[3] =
// SYSCFG_EXTICR4_EXTI12_PF
// |SYSCFG_EXTICR4_EXTI13_PF
// ;
SET_BIT( RCC->APB2ENR, RCC_APB2ENR_AFIOEN );
AFIO->EXTICR[0] = AFIO_EXTICR1_EXTI1_PB
// | AFIO_EXTICR1_EXTI1_PB
// | AFIO_EXTICR1_EXTI2_PA
// | AFIO_EXTICR1_EXTI3_PA
// ;
// AFIO->EXTICR[1] = AFIO_EXTICR2_EXTI4_PA
// | AFIO_EXTICR2_EXTI5_PA
// | AFIO_EXTICR2_EXTI6_PA
// | AFIO_EXTICR2_EXTI7_PA
;
CLEAR_BIT( EXTI->IMR, 0xFFFFu ); // 禁止中断
CLEAR_BIT( EXTI->EMR, 0xFFFFu ); // no event 无中断事件
// SET_BIT ( EXTI->RTSR, 0x0006u ); // rising edge trigger 上升沿触发
SET_BIT ( EXTI->FTSR, 0x0002u ); // falling edge trigger 下降沿触发
WRITE_REG( EXTI->PR, 0xFFFFu ); // 通过写1能复位触发的中断标志
// SET_BIT ( EXTI->IMR, 0x384Fu ); // 允许中断
// // IO中断
// NVIC_EnableIRQ( EXTI0_IRQn );
NVIC_EnableIRQ( EXTI1_IRQn );
// NVIC_EnableIRQ( EXTI2_IRQn );
// NVIC_EnableIRQ( EXTI3_IRQn );
// NVIC_EnableIRQ( EXTI9_5_IRQn );
// NVIC_EnableIRQ( EXTI15_10_IRQn );
}
/********************************** 功能说明 ***********************************
* 中断开关控制
*******************************************************************************/
void EXTIx_IRQ_Enable( uint8_t EXTIx )
{
SET_BIT( EXTI->PR, 0x01u << EXTIx ); // 写1复位中断标志位
SET_BIT( EXTI->IMR, 0x01u << EXTIx ); // 允许中断。
}
void EXTIx_IRQ_Disable( uint8_t EXTIx )
{
CLEAR_BIT( EXTI->IMR, 0x01u << EXTIx ); // 禁止中断
SET_BIT( EXTI->PR, 0x01u << EXTIx ); // 写1复位中断标志位
}
uint16_t iz = 0;
void EXTI1_IRQHandler( void )
{
iz++;
SET_BIT( EXTI->PR, 0x01u << 1 ); // 写1复位中断标志位
if(ArmInitIsRuning[M1] )
{
if( !READ_BIT( GPIOB->IDR, GPIO_Pin_1 ) )
{
EXTIx_IRQ_Disable( 1 );
Motor_PWMCmd(M1, false );
CoordinateSet[M1] = 0u;
CoordinatePosition[M1] = 0;
}
}
else
{
if( READ_BIT( GPIOB->IDR, GPIO_Pin_1 ) )
{
EXTIx_IRQ_Disable( 1 );
osDelay(400);
Motor_PWMCmd(M1, false );
if(CoordinateSet[M1] >0)
CoordinatePosition[M1] = 1;
else
CoordinatePosition[M1] = -1;
CoordinateSet[M1] = 0u;
}
}
}
_Bool Exti_IOStateRead( enum enumPumpSelect Select )
{
_Bool state = false;
switch (Select)
{
case M1:
state = READ_BIT( GPIOB->IDR, GPIO_IDR_IDR1);
break;
default:
break;
}
return state;
}
void Exti_IRQ_Ctrl( enum enumPumpSelect Select, _Bool State )
{
switch (Select)
{
case M1:
State? EXTIx_IRQ_Enable(1) : EXTIx_IRQ_Disable(1);
break;
default:
break;
}
}
void MotorZero_Init( enum enumPumpSelect Select)
{
SET_BIT( GPIOA->BSRR, GPIO_BSRR_BS5 );
FindedZero[Select] =false;
EXTIx_IRQ_Disable(0);
Motor_PWMCmd( Select, false );
ArmInitIsRuning[Select] = true;
Exti_IRQ_Ctrl(Select, false);
Motor_En( Select, true );
Motor_Dir( Select, true );
osDelay(10u);
Motor_IECMD( Select, false );
DCMotor_PWM( Select, 55 );
if( !Exti_IOStateRead(Select) )
{
Motor_Dir( Select, false );
osDelay(10u);
Motor_PWMCmd( Select, true );
osDelay(600u);
Motor_PWMCmd( Select, false );
Motor_Dir( Select, true );
osDelay(150u);
}
Exti_IRQ_Ctrl(Select, true);
Motor_PWMCmd( Select, true );
CoordinateSet[Select] = 0u;
CoordinatePosition[Select] = 1u;
while( CoordinatePosition[Select] )
{
PluseCount[Select] = 0u;
osDelay( 20u );
}
PluseCount[Select] = 0u;
SetPluseCount[Select] = 0u;
CoordinateSet[Select] = 0u;
CoordinateSetOld[Select] = 0u;
Direction[Select] = false;
FindedZero[Select] =true;
// RegCoilsBufRst( (22u+Select*3u) );
usRegHoldingBuf[43] = 0;
usRegInputBuf[43] = 2;
usRegHoldingBuf[7] = CoordinateSet[Select] = 0;
ArmInitIsRuning[Select] = FindZero[Select] = false;
SET_BIT( GPIOA->BSRR, GPIO_BSRR_BR5 );
}
BaseType_t temp1,temp2,temp3;
void _task_MotorCTRL( void * p_arg )
{
uint32_t arg = (uint32_t)p_arg;
MotorCtrl((enum enumPumpSelect)arg );
}
//osThreadDef( _task_MotorCTRL, osPriorityAboveNormal, 2u, 0u );
osThreadId_t MName[pumpMax];
TaskHandle_t xTaskHandles[pumpMax];
void MotorCTRLInitiate( void )
{
SamplePumpSpeed_AcceleratedConver(M1,100);
SamplePumpSpeed_AcceleratedConver(M2,1000);
SamplePumpSpeed_AcceleratedConver(M3,100);
temp1 = xTaskCreate(_task_MotorCTRL, // 任务函数
"TaskName1", // 任务名(用于调试)
512, // 堆栈大小(以堆栈类型的大小为单位)
(void *)M1, // 传递给任务的参数
osPriorityNormal, // 任务优先级(根据需要调整)
&xTaskHandles[M1]); // 任务句柄的地址(用于引用)
temp2 = xTaskCreate(_task_MotorCTRL, // 任务函数
"TaskName2", // 任务名(用于调试)
512, // 堆栈大小(以堆栈类型的大小为单位)
(void *)M2, // 传递给任务的参数
osPriorityNormal, // 任务优先级(根据需要调整)
&xTaskHandles[M2]); // 任务句柄的地址(用于引用)
temp3 = xTaskCreate(_task_MotorCTRL, // 任务函数
"TaskName3", // 任务名(用于调试)
512, // 堆栈大小(以堆栈类型的大小为单位)
(void *)M3, // 传递给任务的参数
osPriorityNormal, // 任务优先级(根据需要调整)
&xTaskHandles[M3]); // 任务句柄的地址(用于引用)
}