打印
[STM32L1]

STM32F103步进电机驱动简单控制

[复制链接]
1372|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
stm32f103步进电机驱动控制 一、硬件接线方法 本文采用混合式二相步进电机-J8HB2401-野火42步进电机,驱动器为野火EBF-MSD4805,下面是常用接线方式:




使用特权

评论回复
评论
狗啃模拟 2022-8-22 23:49 回复TA
———————————————— 版权声明:本文为CSDN博主「小昌快跑」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_44690557/article/details/125607583 
沙发
狗啃模拟|  楼主 | 2022-8-22 23:30 | 只看该作者

使用特权

评论回复
板凳
狗啃模拟|  楼主 | 2022-8-22 23:32 | 只看该作者
如上图所示通常采用共阴接线方式,具体接线按照自己需求进行完成。
另外二相电机步距角1.8°,步进驱动器侧面SW1-SW8分别为细分设定、电流设定和驱动模式选择开关。

使用特权

评论回复
地板
狗啃模拟|  楼主 | 2022-8-22 23:40 | 只看该作者

使用特权

评论回复
5
狗啃模拟|  楼主 | 2022-8-22 23:44 | 只看该作者
二、程序

    代码如下(示例):

1.main.c
#include "stm32f10x.h"
#include "tim.h"
#include "bsp_usart.h"
#include "stm32f10x_it.h"
#include "stm32f10x_conf.h"
/* 共阴 */
/*
PUL+->PA.1  PUL-接GND
DIR+->PA.8  DIR-接GND
*/
extern int motor_dir2;
extern int motor_speed;

int main(void)
{       
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        
        USART_Config();                    
        Driver_Init();/* GPIO_Init */                       
        TIM2_Init(999,72-1);      
        while(1)
        {       
                Locate_Rle2(motor_speed,motor_dir2);/* 变速以及方向 */       
        }
}

使用特权

评论回复
6
狗啃模拟|  楼主 | 2022-8-22 23:46 | 只看该作者
2.tim.c
#include "tim.h"
#include "bsp_usart.h"

long current_pos[2] = {0,0};
int motor_dir2 = 0;
u8 count[2] = {0,0};
u32 motor_speed = 0;
u8 rcr_remainder;     //重复计数余数部分
u8 is_rcr_finish = 1;   //重复计数器是否设置完成
long rcr_integer;          //重复计数整数部分
long target_pos = 0;    //有符号方向

/* 电机转速与方向函数 */
void Locate_Rle2(u32 frequency,DIR_Type dir)
{
        motor_dir2 = dir;
       
        DRIVER_DIR = motor_dir2;
        if(motor_dir2 == CW){motor_speed = 3000;}/* motor_dir2高电平时转速3000Hz */
        else if(motor_dir2 == CCW){motor_speed = 10000;}/* motor_dir2低电平时转速10000Hz */
        frequency = motor_speed;
       
        if(TIM2->CR1&0x01)
        {
                printf("\r\nThe last time pulses is not send finished,wait please!\r\n");
                return;
        }
        if((frequency<20)||(frequency>100000))
        {
                printf("\r\nThe frequency is out of range! please reset it!!(range:20Hz~100KHz)\r\n");
                return;
        }
        TIM2_Startup(frequency);                       
}

/* PA8 - DIR+*/
void Driver_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                       
        GPIO_SetBits(GPIOA,GPIO_Pin_8);                                               
}

/* PA1- PUL+ TIM2_CH2 */
void TIM2_Init(u16 arr,u16 psc)
{                                                          
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);                                                                             

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                               
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                       
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
       
        TIM_TimeBaseStructure.TIM_Period = arr;                                         
        TIM_TimeBaseStructure.TIM_Prescaler =psc;                               
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;                        
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);                
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);                               

        TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Regular);
        TIM_SelectOnePulseMode(TIM2,TIM_OPMode_Single);                       
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;               
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_Pulse = arr>>1;                                
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
        TIM_OC2Init(TIM2, &TIM_OCInitStructure);                                

        TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);                 
        TIM_ARRPreloadConfig(TIM2, ENABLE);                                        
       
        TIM_ITConfig(TIM2, TIM_IT_Update ,ENABLE);                         

        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                 
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        
        NVIC_Init(&NVIC_InitStructure);                                                 
       
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);                         
        TIM_Cmd(TIM2, DISABLE);                                                                                                                            
}


void TIM2_Startup(u32 frequency)   
{
        u16 temp_arr=1000000/frequency-1;
        TIM_SetAutoreload(TIM2,temp_arr);
        TIM_SetCompare2(TIM2,temp_arr>>1);
       
        TIM_SetCounter(TIM2,0);
        TIM_Cmd(TIM2, ENABLE);  
}

使用特权

评论回复
7
狗啃模拟|  楼主 | 2022-8-22 23:47 | 只看该作者
3.tim.h
#include "stm32f10x.h"
#include "stdlib.h"

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
#define PAout(n)          BIT_ADDR(GPIOA_ODR_Addr,n)
#define GPIOA_ODR_Addr    (GPIOA_BASE+12)
#define DRIVER_DIR        PAout(8)

typedef enum
{
        CW = 1,//高电平顺时针
        CCW = 0,//低电平逆时针
}DIR_Type;

void Driver_Init(void);
void TIM2_Init(u16 arr,u16 psc);
void TIM2_Startup(u32 frequency);
void Locate_Rle2(u32 frequency,DIR_Type dir);

使用特权

评论回复
8
狗啃模拟|  楼主 | 2022-8-22 23:48 | 只看该作者
4.stm32f10x_it.c
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "tim.h"
#include "bsp_usart.h"
#include "systick.h"

extern u8 count[2];
extern long current_pos[2]; //有符号方向
extern int motor_dir2;
int counter = 0;

/******* TIM2 - 1ms*********/
void TIM2_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM2,TIM_FLAG_Update)!=RESET)
        {
                TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);       
                count[0]++;
                counter ++;
                TIM_GenerateEvent(TIM2,TIM_EventSource_Update);
       
                TIM_Cmd(TIM2, ENABLE);                                            

                if(count[0]==200)
                {
                        if(motor_dir2==CW)                                                   
                                current_pos[0]+=count[0];
                        else                                                                    
                                current_pos[0]-=count[0];
                        TIM_Cmd(TIM2, DISABLE);                                                   
                        printf("\r\n motor2=%ld\r\n",current_pos[0]);
                        count[0]=0;
                }
               
                if(counter <= 5000){motor_dir2=CW;}/* 定时器前5s拉高motor_dir2电平 */
                else if((counter > 5000) && (counter <= 10000)){motor_dir2=CCW;}/* 拉低电平 */
                else if(counter > 10000){counter=0;}/* 复位 */
        }
}

使用特权

评论回复
9
狗啃模拟|  楼主 | 2022-8-22 23:49 | 只看该作者
a.中断函数可以从保准库中进行拷贝,具体采用哪一个串口自己需要对照原理图;
b.PAout(n)函数采用GPIO-位带操作, 把“位带地址+ 位序号”转换成别名地址宏统一公式如下,详见野火指南:
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x02000000+((addr & 0x00FFFFFF)<<5)+(bitnum<<2))

使用特权

评论回复
10
童雨竹| | 2022-9-29 19:24 | 只看该作者

需要设定一个阈值来对像素点进行设置

使用特权

评论回复
11
Uriah| | 2022-9-30 11:30 | 只看该作者

一种了解状态变化的简单方法

使用特权

评论回复
12
Bblythe| | 2022-9-30 14:29 | 只看该作者

单片机一般都有内部程序区和数据区

使用特权

评论回复
13
Wordsworth| | 2022-12-25 07:28 | 只看该作者

代码量小的时候用来做条件判断

使用特权

评论回复
14
万图| | 2022-12-25 10:27 | 只看该作者

但是如果不懂程序设计的思想的话,会给你做项目的过程中带来很多很多的困惑。

使用特权

评论回复
15
帛灿灿| | 2022-12-25 13:26 | 只看该作者

STM32CUBEMX配置生成初始化代码

使用特权

评论回复
16
Bblythe| | 2022-12-25 14:29 | 只看该作者

单片机一般都有内部程序区和数据区

使用特权

评论回复
17
周半梅| | 2022-12-25 16:25 | 只看该作者

光绘出零件间联机的PCB设计布线

使用特权

评论回复
18
Pulitzer| | 2022-12-25 17:28 | 只看该作者

只要内存占用量不超过 256.0 就可以用 small 模式编译

使用特权

评论回复
19
huangcunxiake| | 2022-12-25 17:45 | 只看该作者
这是步进电机吗

使用特权

评论回复
20
童雨竹| | 2022-12-25 19:24 | 只看该作者

二值化就是让图像的像素点矩阵中的每个像素点的灰度值为0(黑色)或者255(白色

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

803

帖子

2

粉丝