• 【毕业设计教程】通过单片机控制步进电机 - 物联网 嵌入式 stm32



    1 简介

    Hi,大家好,这里是丹成学长,今天向大家介绍如何使用单片机控制步进电机

    大家可用于 课程设计 或 毕业设计


    单片机-嵌入式毕设选题大全及项目分享:

    https://blog.csdn.net/m0_71572576/article/details/125409052


    2 步进电机介绍

    步进电机是一种将电脉冲转化为角位移的执行机构。通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(即步进角),多用于雕刻机、3D打印机等需要精确控制的设备。本篇使用ULN2003驱动五线四相减速步进电机。

    在这里插入图片描述

    • 步进电机每次能转动的最小角度叫做步距角。
    • 每当步进电机接收到一个驱动信号后,步进电机将按照一定的方向转动一个固定的角度。
    • 通过控制脉冲的个数来精确的控制步进电机的角位移量,通过控制脉冲的频率来控制电机转动的速度及加速度,从而达到调速的目的。
    • 步进电机按照相数不同分为单相、双相、多相三种,励磁方式分为1相励磁方式和2相励磁方式。
    • 本文使用的步进电机型号为28BYJ-48,1相励磁方式驱动,通过给ABCD四相依次通电来实现转自不停转动。

    3 A4988驱动介绍

    由于一般的开发板的通用IO驱动能力有限,有些外设不能直接使用IO进行驱动,需要借助一些驱动电路间接控制大功率器件。A4988是大电流驱动阵列,多用于单片机、智能仪表、PLC、数字量输出卡等控制电路中,可直接驱动继电器等负载。

    在这里插入图片描述

    在这里插入图片描述

    4 电机启动代码

    #include "a4988.h"
    #include "delay.h"
    
    /*
    STEP1 PDout(15)
    SDIR1 PGout(2)  
    STEP2 PDout(14)
    SDIR2 PGout(3)  
    STEP3 PDout(13)
    SDIR3 PGout(4)  
    STEP4 PDout(12)
    SDIR4 PGout(5)  
    
    MSTEP PDout(15) //固定芯片步进STEP
    MDIR  PGout(2)  //固定芯片步进DIR
    CSTEP PDout(14) //磁铁步进STEP
    CDIR  PGout(3)  //磁铁步进DIR
    RSTEP PDout(13) //蠕动泵STEP
    RDIR  PGout(4)  //蠕动泵DIR
    USTEP PDout(12) //超声步进电机STEP
    UDIR  PGout(5)  //超声步进电机DIR
    */
    
    //方向脚初始化
    void Step_DIR_Init(void)
    {
     GPIO_InitTypeDef  GPIO_InitStructure;
     
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);   //使能PG端口时钟
        
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;  //端口配置
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽输出
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //IO口速度为50MHz
     GPIO_Init(GPIOG, &GPIO_InitStructure);                  //根据设定参数初始化
     GPIO_SetBits(GPIOG,GPIO_Pin_2);                         
     GPIO_SetBits(GPIOG,GPIO_Pin_3);    
     GPIO_SetBits(GPIOG,GPIO_Pin_4);        
     GPIO_SetBits(GPIOG,GPIO_Pin_5);    
    }
    
    //脉冲初始化,公用定时器4,重映射,4路频率会被一起改变
    void Step_Pulse_Init(u16 arr,u16 psc)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;
        
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);    //使能定时器4时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
        
        GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE); //Timer4重映射   
        
       //设置该引脚为复用输出功能,输出TIM4的PWM脉冲波形
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; //TIM_CH4
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出   
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIO
        
        //!!!!!配置完复用功能后,此时输出为低电平,似乎难以修改
        
       //初始化TIM4
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
    
        //初始化TIM4 Channel_1234 PWM模式     
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
        //TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; //关闭比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
        
        TIM_OC1Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC1
        //TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR1上的预装载寄存器
        
        TIM_OC2Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC2
        //TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR2上的预装载寄存器
        
        TIM_OC3Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC3
        //TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR3上的预装载寄存器
        
        TIM_OC4Init(TIM4, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM4 OC4
        //TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);  //使能TIM4在CCR4上的预装载寄存器
     
        TIM_CCxCmd(TIM4,TIM_Channel_1,TIM_CCx_Disable);//关闭TIM4通道1
        TIM_CCxCmd(TIM4,TIM_Channel_2,TIM_CCx_Disable);//关闭TIM4通道2
        TIM_CCxCmd(TIM4,TIM_Channel_3,TIM_CCx_Disable);//关闭TIM4通道3
        TIM_CCxCmd(TIM4,TIM_Channel_4,TIM_CCx_Disable);//关闭TIM4通道4
        
        TIM_Cmd(TIM4, DISABLE);  //先不使能TIM4 
    }
    
    
    
    //芯片电机运动
    void Mstep_move(u8 dir,u16 frequency)
    {
        MDIR = dir;     
        Step_Pulse_Init((u16)(100000/frequency-1),719);
        TIM_SetCompare4(TIM4,(u16)(50000/frequency));
        TIM_CCxCmd(TIM4,TIM_Channel_4,TIM_CCx_Enable);//开启TIM4通道4
        TIM_Cmd(TIM4, ENABLE);//必须放在最后使能
    
    }
    //芯片电机停止
    void Mstep_stop(void)
    {   
        TIM_SetCompare4(TIM4,0);    
        TIM_CCxCmd(TIM4,TIM_Channel_1,TIM_CCx_Disable);//关闭TIM4通道1
        TIM_CCxCmd(TIM4,TIM_Channel_2,TIM_CCx_Disable);//关闭TIM4通道2
        TIM_CCxCmd(TIM4,TIM_Channel_3,TIM_CCx_Disable);//关闭TIM4通道3
        TIM_CCxCmd(TIM4,TIM_Channel_4,TIM_CCx_Disable);//关闭TIM4通道4
        TIM_Cmd(TIM4, DISABLE);
    }
    
    
    //磁铁电机运动
    void Cstep_move(u8 dir,u16 frequency)
    {
        CDIR = dir;     
        Step_Pulse_Init((u16)(100000/frequency-1),719);
        TIM_SetCompare3(TIM4,(u16)(50000/frequency));
        TIM_CCxCmd(TIM4,TIM_Channel_3,TIM_CCx_Enable);//开启TIM4通道3
        TIM_Cmd(TIM4, ENABLE);//必须放在最后使能
    
    }
    //磁铁电机停止
    void Cstep_stop(void)
    {   
        TIM_SetCompare3(TIM4,0);
        TIM_CCxCmd(TIM4,TIM_Channel_1,TIM_CCx_Disable);//关闭TIM4通道1
        TIM_CCxCmd(TIM4,TIM_Channel_2,TIM_CCx_Disable);//关闭TIM4通道2
        TIM_CCxCmd(TIM4,TIM_Channel_3,TIM_CCx_Disable);//关闭TIM4通道3
        TIM_CCxCmd(TIM4,TIM_Channel_4,TIM_CCx_Disable);//关闭TIM4通道4
        TIM_Cmd(TIM4, DISABLE);
    }
    
    //超声电机运动
    void Ustep_move(u8 dir,u16 frequency)
    {
        UDIR = dir;     
        Step_Pulse_Init((u16)(100000/frequency-1),719);
        TIM_SetCompare1(TIM4,(u16)(50000/frequency));
        TIM_CCxCmd(TIM4,TIM_Channel_1,TIM_CCx_Enable);//开启TIM4通道1
        TIM_Cmd(TIM4, ENABLE);//必须放在最后使能
    
    }
    //超声电机停止
    void Ustep_stop(void)
    {   
        TIM_SetCompare1(TIM4,0);
        TIM_CCxCmd(TIM4,TIM_Channel_1,TIM_CCx_Disable);//关闭TIM4通道1
        TIM_CCxCmd(TIM4,TIM_Channel_2,TIM_CCx_Disable);//关闭TIM4通道2
        TIM_CCxCmd(TIM4,TIM_Channel_3,TIM_CCx_Disable);//关闭TIM4通道3
        TIM_CCxCmd(TIM4,TIM_Channel_4,TIM_CCx_Disable);//关闭TIM4通道4
        TIM_Cmd(TIM4, DISABLE);//USTEP会随波形停在高或低
    }
    
    //蠕动泵抽取
    void Rstep_move(u8 dir,u16 frequency)
    {
        RDIR = dir;     
        Step_Pulse_Init((u16)(100000/frequency-1),719);
        TIM_SetCompare2(TIM4,(u16)(50000/frequency));
        TIM_CCxCmd(TIM4,TIM_Channel_2,TIM_CCx_Enable);//开启TIM4通道2
        TIM_Cmd(TIM4, ENABLE);//必须放在最后使能
    
    }
    //蠕动泵停止
    void Rstep_stop(void)
    {   
        TIM_SetCompare2(TIM4,0);
        TIM_CCxCmd(TIM4,TIM_Channel_1,TIM_CCx_Disable);//关闭TIM4通道1
        TIM_CCxCmd(TIM4,TIM_Channel_2,TIM_CCx_Disable);//关闭TIM4通道2
        TIM_CCxCmd(TIM4,TIM_Channel_3,TIM_CCx_Disable);//关闭TIM4通道3
        TIM_CCxCmd(TIM4,TIM_Channel_4,TIM_CCx_Disable);//关闭TIM4通道4
        TIM_Cmd(TIM4, DISABLE);//RSTEP会随波形停在高或低
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179

    单片机-嵌入式毕设选题大全及项目分享:

    https://blog.csdn.net/m0_71572576/article/details/125409052


    5 最后

  • 相关阅读:
    实战三十一:基于LightGCN推荐算法的推荐系统详细教程(代码+数据)
    Elasticsearch - DSL 查询语句
    AIGC 设计能替代真正的设计师设计吗?
    Blender中的4种视图着色模式
    Qt 实现实时语音通话功能
    Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单
    爬虫小案例爬取塔某小说内容
    【编程题】【Scratch四级】2020.06 正话反说
    YB6502 5V输入双节串联磷酸铁锂电池升压充电芯片
    对话框管理器第八章:对话框中的自定义导航
  • 原文地址:https://blog.csdn.net/m0_71572576/article/details/125484556