STM32F407简单驱动步进电机(标准库)
配置
单片机型号:STM32F104ZGT6
步进电机:YK28HB40-01A
驱动器:YKD2204M-Plus
接线方式:
pu+:接对应的产生PWM的引脚,这里接PF9,对应TIM14_CH1通道!
pu-:接单片机的GND;
DR+:接单片机的3.3V(电机转动的方向固定)或者单片机的控制引脚这里是PF8
DR-:接单片机的GND;
这里没有使用电机的使能引脚!!!
-V:接24V的负极
+V:接24V的正极
A+:接的步进电机的红线(需要参考对应的原理图,不同的电机接法存在差异)
A-:步进电机的蓝线
B+:步进电机的绿线
B-:步进电机的黑线
采用定时器主从模式,发送固定脉冲,控制步进电机的转动;
比如在驱动器上,将脉冲调到1600挡位,表示当有1600个脉冲到来时,电机转动一周。如果输入800个脉冲,则电机就转动半圈;
主定时器采用TIM14_CH1;
从定时器采用TIM12_ITR3;
表72在407中文手册370页; 表79在464页; 图165在446页; 图166在447页
代码部分
采用标准库进行开发,先创建好工程!
再创建一个pwm.c和pwm.h文件就可以驱动了!
pwm.c
#include "PWM.h"
#include "stm32f4xx.h" /*
*PF9 TIM14_CH1通道
*PF8 方向引脚
*/
void TIM14_PWM_Init(void) //主定时器 //uint32_t arr,uint32_t psc
{ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); //使能定时器 14 时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能PORTF时钟GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9 复用为定时器 14GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //GPIOF8GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //复用推挽输出GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF8//TIM_InternalClockConfig()TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period =100-1; //arr; //设置自动重装载值 100-1TIM_TimeBaseStructure.TIM_Prescaler =1050-1;//psc; //设置预分频值TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim 0=TIM_CKD_DIV1TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCStructInit(&TIM_OCInitStructure); //默认的初始化TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择 PWM 模式 1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;//输出极性高 //TIM_OCPolarity_Low; //输出极性低TIM_OCInitStructure.TIM_Pulse=50;//CCRTIM_OC1Init(TIM14, &TIM_OCInitStructure); //初始化 TIM//TIM_SelectMasterSlaveMode();//TIM_SelectOutputTrigger();TIM_OC1PreloadConfig(TIM14,TIM_OCPreload_Enable); //通道1的CCR可以更改TIM_ARRPreloadConfig(TIM14,ENABLE); //使能ARR预装载寄存器TIM_Cmd(TIM14, DISABLE); //使能 TIM14}void TIM12_Init(void)//从定时器
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12,ENABLE); //使能定时器 12 时钟TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period = 65535; //设置自动重装载值 100-1TIM_TimeBaseStructure.TIM_Prescaler =1-1; //设置预分频值TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim 0=TIM_CKD_DIV1TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInit(TIM12, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的//TIM_SelectMasterSlaveMode(TIM12,);TIM_SelectInputTrigger(TIM12,TIM_TS_ITR3); //TIM14主 TIM12从:ITR3TIM_SelectSlaveMode(TIM12,TIM_SlaveMode_External1);//从模式TIM_ITConfig(TIM12,TIM_IT_Update,DISABLE);TIM_ARRPreloadConfig(TIM12,ENABLE); //使能ARR预装载寄存器NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM8_BRK_TIM12_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStructure);TIM_Cmd(TIM12, DISABLE); //使能 TIM12
}/**
uint16_t Num 发送的脉冲数(从定时器的ARR值)
uint8_t Dir 步进电机的旋转方向
uint16_t Speed 速度(更改主定时器的ARR值)
*/
void PWM_Output_Speed(uint16_t Num,uint8_t Dir,uint16_t Speed)
{if(Dir==1){GPIO_ResetBits(GPIOF,GPIO_Pin_8);//正转}else{GPIO_SetBits(GPIOF,GPIO_Pin_8); //反转}TIM_Cmd(TIM12, DISABLE);//关闭TIM12使能TIM_SetAutoreload(TIM12,Num);//从新设置ARR计数值TIM_GenerateEvent(TIM12,TIM_EventSource_Update);//配置由软件生成定时器事件,新修改ARR计数值后,马上软件更改一次事件TIM_Cmd(TIM12, ENABLE); //使能 TIM12TIM_ClearITPendingBit(TIM12,TIM_IT_Update);//清楚中断标志位TIM_ITConfig(TIM12,TIM_IT_Update,ENABLE);//开启定时器12的中断TIM_SetAutoreload(TIM14,Speed);//从新设置ARR计数值TIM_GenerateEvent(TIM14,TIM_EventSource_Update);//配置由软件生成定时器事件,新修改ARR计数值后,马上软件更改一次事件TIM_SetCompare1(TIM14,Speed/2); //设置CCR的值为ARR的一半,占空比为50%TIM_GenerateEvent(TIM14,TIM_EventSource_CC1);//配置后由软件生成通道一的事件,马上生效TIM_Cmd(TIM14, ENABLE); //使能 TIM14
}void TIM8_BRK_TIM12_IRQHandler(void)
{if(TIM_GetITStatus(TIM12,TIM_IT_Update) != RESET){TIM_ClearITPendingBit(TIM12,TIM_IT_Update);TIM_Cmd(TIM12, DISABLE);//关闭TIM12使能TIM_Cmd(TIM14, DISABLE);//关闭TIM14使能TIM_ITConfig(TIM12,TIM_IT_Update,DISABLE);//关闭定时器12的中断}
}
pwm.h
#ifndef __PWM_H__
#define __PWM_H__#include "stm32f4xx.h" void TIM14_PWM_Init(void); //uint32_t arr,uint32_t psc
void TIM12_Init(void);
void PWM_Output_Speed(uint16_t Num,uint8_t Dir,uint16_t Speed);#endif
main函数部分
#include "stm32f4xx.h" // Device header
#include "pwm.h"int main()
{TIM14_PWM_Init(); //168M/168=1Mhz的计数频率,重装载值100,所以PWM频率为 1M/100=1Khz.TIM12_Init();PWM_Output_Speed(3200,0,40);//发送的脉冲数 步进电机的旋转方向 速度(更改主定时器的ARR值)while(1){}}
通过PWM_Output_Speed(3200,0,40);输入 3200个脉冲,电机逆时针转2圈。最后一位参数为速度;
PWM_Output_Speed(1600,1,40);就是沿顺时针方向旋转一周;
通过修改PWM_Output_Speed();可以实现电机的角度、方向、速度控制。
其他方式的pwm简单驱动
采用定时器的翻转模式,驱动电机的转动:
#include "PWM.h"
#include "stm32f4xx.h" /*
*PF9 TIM14_CH1通道
*PF8 为方向引脚
*/uint16_t CCR1=1000;void TIM14_PWM_Init(uint32_t arr,uint32_t psc)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); //使能定时器 14 时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能PORTF时钟GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9 复用为定时器 14GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //GPIOF8GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //复用推挽输出GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF8TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period = arr-1; //设置自动重装载值 输出频率TIM_TimeBaseStructure.TIM_Prescaler =psc-1; //设置预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim 0=TIM_CKD_DIV1TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的TIM_OCInitTypeDef TIM_OCInitStructure;TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //翻转模式 //TIM_OCMode_PWM1; //选择 PWM 模式 1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;//输出极性高 //TIM_OCPolarity_Low; //输出极性低TIM_OCInitStructure.TIM_Pulse=CCR1; //CCRTIM_OC1Init(TIM14, &TIM_OCInitStructure); //初始化 TIMTIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Disable);//失能 //使能TIM14在CCR1上的预装载寄存器 TIM_OCPreload_Enable
// TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能 TIM_ClearFlag(TIM14,TIM_FLAG_CC1); //清除定时器中断标志位TIM_ITConfig(TIM14,TIM_FLAG_CC1,ENABLE); //开启定时器比较中断NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM8_TRG_COM_TIM14_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStructure);TIM_Cmd(TIM14, ENABLE); //使能 TIM14
}void TIM8_TRG_COM_TIM14_IRQHandler(void)
{uint16_t num = 0;if(TIM_GetITStatus(TIM14,TIM_FLAG_CC1)==SET){TIM_ClearITPendingBit(TIM14,TIM_FLAG_CC1);num=TIM_GetCapture1(TIM14);TIM_SetCompare1(TIM14,num+CCR1);}
}
在main函数中调用TIM14_PWM_Init(65536,1);
运行结果就是使电机沿单一方向转动,通过修改ARR值可以调速;
通过在main函数调用下面函数,可控制电机的旋转方向;(引脚接线注意接对)
GPIO_SetBits(GPIOF,GPIO_Pin_8); //反转
GPIO_ResetBits(GPIOF,GPIO_Pin_8); //正转
直接输出pwm波形的驱动
pwm.c
#include "PWM.h"
#include "stm32f4xx.h"
//#include "uart.h"/*
*PF9 TIM14_CH1通道
*
*/
void TIM14_PWM_Init(uint32_t arr,uint32_t psc)
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); //使能定时器 14 时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能PORTF时钟GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9 复用为定时器 14GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF9TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值 100-1TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim 0=TIM_CKD_DIV1TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择 PWM 模式 1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High; //TIM_OCPolarity_Low; //输出极性低TIM_OCInitStructure.TIM_Pulse=50;//CCRTIM_OC1Init(TIM14, &TIM_OCInitStructure); //初始化 TIMTIM_Cmd(TIM14, ENABLE); //使能 TIM14}
在main函数中调用TIM14_PWM_Init(100-1,1680-1);
运行结果就是使电机沿单一方向转动,通过修改ARR值可以调速;