STM32开发项目:步进电机驱动库
目录
- 项目背景
- 驱动库介绍
- 源码分析
- 头文件
- 源文件
- 应用指南
项目背景
在各类项目开发中,我们会经常涉及到步进电机的控制。一般情况下,单片机都是通过操作步进电机驱动器或驱动芯片实现对步进电机的控制。步进电机驱动器(芯片)一般都是留有三个接口En,Dir,Pul。En是步进电机使能(或脱机)的信号,高电平时,步进电机会断电脱机。Dir是步进电机转向信号,高电平与低电平代表着正转与反转。Pul是步进电机运动的脉冲信号,每接受到一个脉冲,步进电机运行一步(或一个细分步)。
驱动库介绍
本步进电机驱动库主要实现了对步进电机驱动器上述三种信号的控制,同时也封装好了电机点动、长动、往复三种运动模式。通过将步进电机封装抽象为一个结构体类型,我们可以轻松实现对多个不同步进电机的运动控制。同时,本库函数配套的应用指南中也给出了步进电机与光电对管的配套使用例程。
源码分析
头文件
头文件中定义了步进电机结构体类型,它是对步进电机(驱动器)控制的抽象,与平台无关。在代码注释中有对每个成员的描述。特别需要注意的是,void StepMotor_TryMove(StepMotor_Struct* StepMotor_P)
是电机运动控制的核心函数,它主要负责实现了电机三种运动模式。需要在定时器的更新中断服务函数中周期性的调用此函数。
/** stepmotor.h** Created on: 2020年8月31日* Author: Tao*/#ifndef SOURCE_ALWHALESLIB_HARDWARE_INC_STEPMOTOR_H_
#define SOURCE_ALWHALESLIB_HARDWARE_INC_STEPMOTOR_H_#define USE_STEPMOTOR#ifdef USE_STEPMOTOR#include "stepmotor.h"
#include "stm32f10x_conf.h"#define SETPMOTOR_NUM 4/***步进电机的控制引脚映射***/
#define STEPMOTOR_1_EN GPIOB_OUT(15)
#define STEPMOTOR_1_DIR GPIOB_OUT(13)
#define STEPMOTOR_1_PUL GPIOB_OUT(14)#define STEPMOTOR_2_EN GPIOD_OUT(10)
#define STEPMOTOR_2_DIR GPIOD_OUT(8)
#define STEPMOTOR_2_PUL GPIOD_OUT(9)#define STEPMOTOR_3_EN GPIOD_OUT(13)
#define STEPMOTOR_3_DIR GPIOD_OUT(11)
#define STEPMOTOR_3_PUL GPIOD_OUT(12)#define STEPMOTOR_4_EN GPIOC_OUT(6)
#define STEPMOTOR_4_DIR GPIOD_OUT(14)
#define STEPMOTOR_4_PUL GPIOD_OUT(15)
/*******************************/typedef void (*SetState_FP)(uint8_t state);
typedef void (*SetParam_FP)(uint32_t param);/*** @brief 步进电机的结构体封装* triggerCount是电机单步运动的边沿次数,1: 单次,即电平跳变, 2: 双次,即脉冲* SetPulse是驱动电机运动的函数指针,一般情况下,应该为它注册一个操作GPIO端口电平的指针* 一般会在定时器的更新中断服务函数中调用SetPulse,每次调用都将端口电平翻转* triggerCount = 1 时,定时器的更新频率 = 步进电机速度(步/s)* triggerCount = 2 时,定时器的更新频率/2 = 步进电机速度(步/s)** 一般通过定时器驱动步进电机的运动,定时器的启停即为电机的启停,定时器的频率即为电机的速度* SetExec设置电机运动启停的函数指针,一般情况下,应该为它注册一个可以打开、关闭驱动定时器的函数* SetSpeed是设置电机运动速度的函数指针,一般情况下,应该为它注册一个可以设置驱动定时器的更新周期的函数*/
typedef struct
{//电机是否正在运动uint8_t IsRun;//电机单步运动的边沿次数(1: 单次,即电平跳变, 2: 双次,即脉冲)uint8_t triggerNum;//电机运行的步数计数uint32_t StepCount;//电机循环计数(仅在工作模式为往复时生效)uint8_t LoopCount;//电机设置运动步数uint32_t StepSV;//电机的工作模式(0:距离, 1:往复, 2:长动)uint8_t WorkMode;//驱动步进电机的硬件定时器指针,//此成员与硬件相关,设置它的主要目的是为了编写各处理函数时的方便
// TIM_TypeDef* DriveTimer;//设置激活电机的函数指针(激活电机后,电机将处于锁定状态,相当于通电)//只有处于激活状态的电机才能被控制SetState_FP SetEn;//设置电机运动方向的函数指针(0:正方向, 1:逆方向, 2:翻转方向)SetState_FP SetDir;//电机单步运动的函数指针(0:低电平, 1:高电平, 2:翻转电平)SetState_FP SetPulse;//设置电机运动速度的函数指针SetParam_FP SetSpeed;//设置电机运动启停的函数指针SetState_FP SetExec;
} StepMotor_Struct;extern StepMotor_Struct StepMotor[SETPMOTOR_NUM];void StepMotor_Init();
void StepMotor_SetWorkMode(StepMotor_Struct* StepMotor_P, uint8_t mode);
void StepMotor_SetLoopCount(StepMotor_Struct* StepMotor_P, uint32_t loopCount);
void StepMotor_SetStep(StepMotor_Struct* StepMotor_P, uint32_t step);
void StepMotor_TryMove(StepMotor_Struct* StepMotor_P);#endif
#endif /* SOURCE_ALWHALESLIB_HARDWARE_INC_STEPMOTOR_H_ */
源文件
在源文件中,静态函数static void StepMotor_1_SetEn_Handler(uint8_t state)
,…,static void StepMotor_4_SetExec_Handler(uint8_t state)
是与平台相关的代码,它们用来注册步进电机结构体成员的各功能函数指针。
StepMotor_Struct StepMotor[SETPMOTOR_NUM]
结构体数组在声明时就直接进行了初始化。当然也可以利用void StepMotor_Init()
函数(本源码中没有实现)实现上述结构体数组的初始化。与平台相关的代码主要在静态函数中,它们是抽象电机控制的具体实现。
初始化结构体数组之后,所有对步进电机的控制都是围绕操作结构体成员展开。当然可以直接操作结构体成员,但笔者推荐使用封装好的常用步进电机操作函数来控制步进电机,例如void StepMotor_SetWorkMode(StepMotor_Struct* StepMotor_P, uint8_t mode)
,void StepMotor_SetStep(StepMotor_Struct* StepMotor_P, uint32_t step)
等。
/** stepmotor.c** Created on: 2020年8月31日* Author: Tao*/#include "stepmotor.h"#ifdef USE_STEPMOTOR/**********************************/
static void StepMotor_1_SetEn_Handler(uint8_t state)
{STEPMOTOR_1_EN = state;
}static void StepMotor_2_SetEn_Handler(uint8_t state)
{STEPMOTOR_2_EN = state;
}static void StepMotor_3_SetEn_Handler(uint8_t state)
{STEPMOTOR_3_EN = state;
}static void StepMotor_4_SetEn_Handler(uint8_t state)
{STEPMOTOR_4_EN = state;
}/**********************************/
static void StepMotor_1_SetDir_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_1_DIR = state;}else{STEPMOTOR_1_DIR = ~STEPMOTOR_1_DIR;}
}static void StepMotor_2_SetDir_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_2_DIR = state;}else{STEPMOTOR_2_DIR = ~STEPMOTOR_2_DIR;}
}static void StepMotor_3_SetDir_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_3_DIR = state;}else{STEPMOTOR_3_DIR = ~STEPMOTOR_3_DIR;}
}static void StepMotor_4_SetDir_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_4_DIR = state;}else{STEPMOTOR_4_DIR = ~STEPMOTOR_4_DIR;}
}/**********************************/
static void StepMotor_1_SetPulse_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_1_PUL = state;}else{STEPMOTOR_1_PUL = ~STEPMOTOR_1_PUL;}
}static void StepMotor_2_SetPulse_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_2_PUL = state;}else{STEPMOTOR_2_PUL = ~STEPMOTOR_2_PUL;}
}static void StepMotor_3_SetPulse_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_3_PUL = state;}else{STEPMOTOR_3_PUL = ~STEPMOTOR_3_PUL;}
}static void StepMotor_4_SetPulse_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_4_PUL = state;}else{STEPMOTOR_4_PUL = ~STEPMOTOR_4_PUL;}
}/**********************************/
static void StepMotor_1_SetSpeed_Handler(uint32_t speed)
{speed = speed * StepMotor[0].triggerNum;//frequency < 1k, psc = 7200if (speed < 1000){TIM5->PSC = 7200 - 1;}//frequency < 10k, psc = 720else if (speed < 10000){TIM5->PSC = 720 - 1;}//frequency < 100k, psc = 72else if (speed < 100000){TIM5->PSC = 72 - 1;}else{return;}//Set the update frequency of the timer.TIM5->ARR = 72000000.0 / (TIM5->PSC + 1) / speed - 1;return;
}static void StepMotor_2_SetSpeed_Handler(uint32_t speed)
{speed = speed * StepMotor[1].triggerNum;//frequency < 1k, psc = 7200if (speed < 1000){TIM6->PSC = 7200 - 1;}//frequency < 10k, psc = 720else if (speed < 10000){TIM6->PSC = 720 - 1;}//frequency < 100k, psc = 72else if (speed < 100000){TIM6->PSC = 72 - 1;}else{return;}//Set the update frequency of the timer.TIM6->ARR = 72000000.0 / (TIM6->PSC + 1) / speed - 1;return;
}static void StepMotor_3_SetSpeed_Handler(uint32_t speed)
{speed = speed * StepMotor[2].triggerNum;//frequency < 1k, psc = 7200if (speed < 1000){TIM7->PSC = 7200 - 1;}//frequency < 10k, psc = 720else if (speed < 10000){TIM7->PSC = 720 - 1;}//frequency < 100k, psc = 72else if (speed < 100000){TIM7->PSC = 72 - 1;}else{return;}//Set the update frequency of the timer.TIM7->ARR = 72000000.0 / (TIM7->PSC + 1) / speed - 1;return;
}static void StepMotor_4_SetSpeed_Handler(uint32_t speed)
{speed = speed * StepMotor[3].triggerNum;//frequency < 1k, psc = 7200if (speed < 1000){TIM8->PSC = 7200 - 1;}//frequency < 10k, psc = 720else if (speed < 10000){TIM8->PSC = 720 - 1;}//frequency < 100k, psc = 72else if (speed < 100000){TIM8->PSC = 72 - 1;}else{return;}//Set the update frequency of the timer.TIM8->ARR = 72000000.0 / (TIM8->PSC + 1) / speed - 1;return;
}/**********************************/
static void StepMotor_1_SetExec_Handler(uint8_t state)
{TIM_Cmd(TIM5, state);
}static void StepMotor_2_SetExec_Handler(uint8_t state)
{TIM_Cmd(TIM6, state);
}static void StepMotor_3_SetExec_Handler(uint8_t state)
{TIM_Cmd(TIM7, state);
}static void StepMotor_4_SetExec_Handler(uint8_t state)
{TIM_Cmd(TIM8, state);
}StepMotor_Struct StepMotor[SETPMOTOR_NUM] =
{//Initialization of step motor 1{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_1_SetEn_Handler,.SetDir = StepMotor_1_SetDir_Handler,.SetPulse = StepMotor_1_SetPulse_Handler,.SetSpeed = StepMotor_1_SetSpeed_Handler,.SetExec = StepMotor_1_SetExec_Handler,},//Initialization of step motor 2{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_2_SetEn_Handler,.SetDir = StepMotor_2_SetDir_Handler,.SetPulse = StepMotor_2_SetPulse_Handler,.SetSpeed = StepMotor_2_SetSpeed_Handler,.SetExec = StepMotor_2_SetExec_Handler,},//Initialization of step motor 3{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_3_SetEn_Handler,.SetDir = StepMotor_3_SetDir_Handler,.SetPulse = StepMotor_3_SetPulse_Handler,.SetSpeed = StepMotor_3_SetSpeed_Handler,.SetExec = StepMotor_3_SetExec_Handler,},//Initialization of step motor 4{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_4_SetEn_Handler,.SetDir = StepMotor_4_SetDir_Handler,.SetPulse = StepMotor_4_SetPulse_Handler,.SetSpeed = StepMotor_4_SetSpeed_Handler,.SetExec = StepMotor_4_SetExec_Handler,},
};/*** @brief 完成步进电机的初始化*/
void StepMotor_Init()
{}/*** @brief 设置步进电机的运动步数* 运动步数与内部的StepCount, StepSV的关系主要取决于triggerNum,即触发多少次电机实际运行1步。* 在驱动信号的形式上即是单边沿触发(triggerNum = 1, 跳变信号)还是双边沿触发(triggerNum = 2, 脉冲信号)* @param StepMotor_P: 步进电机结构体指针* @param step: 电机运动步数*/
void StepMotor_SetStep(StepMotor_Struct* StepMotor_P, uint32_t step)
{StepMotor_P->StepSV = step * StepMotor_P->triggerNum;StepMotor_P->StepCount = StepMotor_P->StepSV;
}/*** @brief 设置步进电机的工作模式* @param StepMotor_P: 步进电机结构体指针* @param mode: 电机工作模式* @arg 0: 点动* @arg 1: 往复* @arg 2: 长动*/
void StepMotor_SetWorkMode(StepMotor_Struct* StepMotor_P, uint8_t mode)
{StepMotor_P->WorkMode = mode;
}/*** @brief 设置步进电机的循环次数* @param StepMotor_P: 步进电机结构体指针* @param loopCount: 电机循环次数(仅在工作模式为往复时生效)*/
void StepMotor_SetLoopCount(StepMotor_Struct* StepMotor_P, uint32_t loopCount)
{StepMotor_P->LoopCount = loopCount;
}/*** @brief 在定时器的更新中断服务函数中周期性调用此函数* @param StepMotor_P: 步进电机结构体指针* 需要注意的是,传入的步进电机结构体的SetSpeed与SetExec指针所依赖的驱动定时器* 应当与调用本函数的驱动定时器一致,否则会出现错误*/
void StepMotor_TryMove(StepMotor_Struct* StepMotor_P)
{//正常工作模式if (StepMotor_P->WorkMode == 0){if (StepMotor_P->StepCount != 0){//翻转一次脉冲端口电平StepMotor_P->SetPulse(2);StepMotor_P->StepCount--;}else{//停止步进电机StepMotor_P->SetExec(0);StepMotor_P->IsRun = 0;}}//往复工作模式else if (StepMotor_P->WorkMode == 1){if (StepMotor_P->LoopCount != 0){if (StepMotor_P->StepCount != 0){StepMotor_P->SetPulse(2);StepMotor_P->StepCount--;}else{StepMotor_P->LoopCount--;StepMotor_P->StepCount = StepMotor_P->StepSV;//翻转方向StepMotor_P->SetDir(2);}}else{StepMotor_P->SetExec(0);StepMotor_P->IsRun = 0;}}//连续工作模式else if (StepMotor_P->WorkMode == 2){//翻转一次脉冲端口电平StepMotor_P->SetPulse(2);}else{}
}#endif
应用指南
- 根据硬件平台实现结构体成员中的各函数指针(
SetState_FP SetEn
,SetState_FP SetDir
,SetState_FP SetPulse
,SetParam_FP SetSpeed
,SetState_FP SetExec
,)的回调函数。这些回调函数或是操作GPIO的电平输出,或者控制着硬件定时器的频率与启停。以STM32F103平台为例:
//SetEn的回调函数
static void StepMotor_1_SetEn_Handler(uint8_t state)
{STEPMOTOR_1_EN = state;
}//SetDir的回调函数
static void StepMotor_1_SetDir_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_1_DIR = state;}else{STEPMOTOR_1_DIR = ~STEPMOTOR_1_DIR;}
}//SetPulse的回调函数
static void StepMotor_1_SetPulse_Handler(uint8_t state)
{if(state < 2){STEPMOTOR_1_PUL = state;}else{STEPMOTOR_1_PUL = ~STEPMOTOR_1_PUL;}
}//SetSpeed的回调函数
static void StepMotor_1_SetSpeed_Handler(uint32_t speed)
{speed = speed * StepMotor[0].triggerNum;//frequency < 1k, psc = 7200if (speed < 1000){TIM5->PSC = 7200 - 1;}//frequency < 10k, psc = 720else if (speed < 10000){TIM5->PSC = 720 - 1;}else{return;}//Set the update frequency of the timer.TIM5->ARR = 72000000.0 / (TIM5->PSC + 1) / speed - 1;return;
}//SetExec的回调函数
static void StepMotor_1_SetExec_Handler(uint8_t state)
{TIM_Cmd(TIM5, state);
}
- 初始化步进电机结构体变量(数组)。可以在声明时直接将结构体变量(数组)进行初始化,也可以利用
void StepMotor_Init()
函数实现结构体变量(数组)的初始化。
StepMotor_Struct StepMotor[SETPMOTOR_NUM] =
{//Initialization of step motor 1{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_1_SetEn_Handler,.SetDir = StepMotor_1_SetDir_Handler,.SetPulse = StepMotor_1_SetPulse_Handler,.SetSpeed = StepMotor_1_SetSpeed_Handler,.SetExec = StepMotor_1_SetExec_Handler,},//Initialization of step motor 2{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_2_SetEn_Handler,.SetDir = StepMotor_2_SetDir_Handler,.SetPulse = StepMotor_2_SetPulse_Handler,.SetSpeed = StepMotor_2_SetSpeed_Handler,.SetExec = StepMotor_2_SetExec_Handler,},//Initialization of step motor 3{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_3_SetEn_Handler,.SetDir = StepMotor_3_SetDir_Handler,.SetPulse = StepMotor_3_SetPulse_Handler,.SetSpeed = StepMotor_3_SetSpeed_Handler,.SetExec = StepMotor_3_SetExec_Handler,},//Initialization of step motor 4{.IsRun = 0,.triggerNum = 2,.StepCount = 0,.LoopCount = 0,.StepSV = 100,.WorkMode = 0,.SetEn = StepMotor_4_SetEn_Handler,.SetDir = StepMotor_4_SetDir_Handler,.SetPulse = StepMotor_4_SetPulse_Handler,.SetSpeed = StepMotor_4_SetSpeed_Handler,.SetExec = StepMotor_4_SetExec_Handler,},
};
- 在项目工程的合适位置配置控制功能的回调函数中所依赖的定时器,并配置定时器的更新中断
void Timer_Config()
{TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);TIM_DeInit(TIM5);TIM_TimeBaseInitStructure.TIM_Prescaler = TIM5_Prescaler - 1;TIM_TimeBaseInitStructure.TIM_Period = TIM5_Period - 1;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM5, TIM_FLAG_Update);TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);// TIM_ARRPreloadConfig(TIM5, ENABLE);
}void NVIC_Config()
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Timer5 is used for drive step motor 1.NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}
- 在定时器的更新中断服务函数中调用
void StepMotor_TryMove(StepMotor_Struct* StepMotor_P)
。
void TIM5_IRQHandler(void)
{if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET){StepMotor_TryMove(&StepMotor[0]);TIM_ClearFlag(TIM5,TIM_FLAG_Update);TIM_ClearITPendingBit(TIM5,TIM_IT_Update);}
}
- 设置电机的启动参数并启动电机。
void StepMotor_RunM1(void)
{//设置运动参数StepMotor_SetStep(&StepMotor[0], 1200);StepMotor_SetWorkMode(&StepMotor[0], 1);StepMotor_SetLoopCount(&StepMotor[0], 50);StepMotor[0].SetSpeed(3000);//启动电机并设置标志位StepMotor[0].SetExec(1);StepMotor[0].IsRun = 1;
}
- 停止电机,一般在光电对管触发的外部中断服务函数中调用。
void StepMotor_StopM1(void)
{//停止电机并设置标志位StepMotor[0].SetExec(0);StepMotor[0].IsRun = 0;StepMotor[0].StepCount = 0;
}
- 特别说明1:在光电对管触发的外部中断服务函数中调用停止电机函数时,应当注意软件滤波消除抖动,也可以适当延时后再关闭电机以摆脱光电对管触发的临界点位置。
void EXTI0_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line0) != RESET){//延时以消除抖动delay_ms(10);if(MOTOR_LIMIT_SWITCH_1_1 == 0){//Stop motor 1StepMotor[0].SetExec(0);StepMotor[0].IsRun = 0;StepMotor[0].StepCount = 0;}EXTI_ClearITPendingBit(EXTI_Line0);}
}
- 特别说明2:触发光电对管后,电机再启动需要有方向保护,不能继续向原方向运动,否则会由于光电对管无法再次被触发而导致电机失控。可以在控制电机启停的业务代码中增加对光电对管状态的判断:
void StepMotor_RunM1(void)
{//设置运动参数StepMotor_SetStep(&StepMotor[0], 1200);StepMotor_SetWorkMode(&StepMotor[0], 1);StepMotor_SetLoopCount(&StepMotor[0], 50);StepMotor[0].SetSpeed(3000);if((MOTOR_LIMIT_SWITCH_1_1 ==0) &&(STEPMOTOR_1_DIR == 0)){return;}else if((MOTOR_LIMIT_SWITCH_1_2 ==0) &&(STEPMOTOR_1_DIR == 1)){return;}else{//启动电机并设置标志位StepMotor[0].SetExec(1);StepMotor[0].IsRun = 1;}
}
STM32开发项目:步进电机驱动库相关推荐
- a4988 脉宽要求_基于STM32的微型步进电机驱动控制器设计
基于STM32的微型步进电机驱动控制器设计 摘 要: 设计了一种微型步进电机驱动控制器,通过上位机界面修改步进电机转速.旋转角度.细分系数.该设计以STM32F103T8U6作为主控制器,以A4988 ...
- arduino步进电机程序库_Arduino基础入门篇27—步进电机驱动库的使用
本篇介绍步进电机驱动库的使用,通过读取电位器输入,控制步进电机转动相应角度. Stepper库是官方提供的驱动库,我们启动Arduino IDE,点击「文件」-「示例」就能找到Stepper库,官方提 ...
- arduino步进电机程序库_Arduino入门教程15(步进电机驱动库的使用):Arduino Uno R3+ULN2003+步进电机 使用Stepper驱动库,控制步进电机转动角度...
本篇介绍步进电机驱动库的使用,通过读取电位器输入,控制步进电机转动相应角度. Stepper库是官方提供的驱动库,我们启动Arduino IDE,点击「文件」-「示例」就能找到Stepper库,官方提 ...
- 基于STM32单片机闭环步进电机驱动调速仿真(仿真+源码+全套资料)
资料编号:081 (1) 基本功能:本任务通过输出脉冲控制步进电机的停止.运动.方向.使用 两个按键分别控制步进电机的正转和反转,再次按下这两个按键,步进电机停止, 同时 LCD 显示电机状态信息. ...
- arduino 步进电机驱动库_一文看懂arduino驱动uln2003操作步进电机的方法
arduino驱动uln2003操作步进电机的方法 1.网上买的步进电机,很多接线顺序都不对.经过不懈努力查资料,终于找到了能用的接线方式: 电机上的12345针脚,对应着接线端子的42135. 2. ...
- arduino 步进电机驱动库_Arduino第三方库_步进电机控制
目前做一个项目遇到一个问题,就是在实现步进电机运动时,点动模式电机振动很厉害,现在就一个非常强大的第三方库Accelstepper进行研究分析. 官网的函数说明: #include 中的公共成员函数: ...
- STM32开发项目:借助DMA传输高效的使用ADC
目录 项目背景 DMA简介 DMA请求 DMA通道 DMA仲裁 DMA配置 从哪里来到哪里去 要传多少,单位是什么 什么时候传输完成 代码示例 配置GPIO 相关变量定义 配置ADC 配置DMA 获取 ...
- STM32开发项目:定时器预装载寄存器(ARR)
项目背景 笔者在进行某项目开发时,需要实时调节定时器的周期,以控制定时器下次更新中断的时间. 预装载寄存器 自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值.当计数 ...
- STM32开发项目:STM32F407的BootLoader程序
日期 作者 版本 说明 2020.11.03 Tao V0.0 完成主体内容的撰写 目录 BootLoader程序介绍 源码实现 源文件 stm32f4_flash.ld 使用指南 设置用户程序下载位 ...
- STM32开发项目:一些模拟电子开关的介绍与驱动
日期 作者 版本 说明 2020.09.29 Tao V1.0 撰写了ADG408.DG467芯片的简介与驱动 2020.09.30 Tao V1.1 撰写了WAS3157B芯片的简介与驱动 2020 ...
最新文章
- 基于深度学习的人脸检测与静默活体检测——C++实现
- Python学习笔记:常用第三方模块3
- track文件 什么是git_git常用命令
- python模糊图像清晰化_视频模糊图像处理
- python线性回归可视化_【Python可视化5】Seaborn之线性回归
- emmet 工具的基本使用,总结
- NUC1014 排版题.输出排列成菱形的字母【打印图案】
- Nginx源码阅读(gdb 调试nginx文件) -- 解析配置文件
- spring源码bean的加载过程
- 理解结构与表现相分离
- 李志 逼哥 完整专辑网盘下载
- 计算机专业及相关知识测试,计算机知识及测验考试.doc
- 高通骁龙410e/APQ8016E嵌入式物联网应用处理器解决方案
- Verilog语言控制Xilinx FPGA引脚demo
- 《MySQL必知必会》的读后感
- AI规则迎来进化:从“阿西莫夫三原则”到“李彦宏四原则”
- 学过c语言如何入门Python?
- PCB工艺规范及PCB设计安规原则
- 【嵌入式开发板】迅为iTOP-4412开发板板及资料介绍
- 【python】制作商品历史价格查询