单片机控制42步进电机_51单片机控制42步进电机 - CSDN
精华内容
参与话题
  • 51单片机控制TB6600驱动器驱动42步进电机

    万次阅读 多人点赞 2020-08-15 10:45:44
    51单片机控制TB6600驱动器驱动42步进电机功能实现目标硬件简介硬件连接程序代码功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个...

    51单片机控制TB6600驱动器驱动42步进电机

    第一次

    以前总是看别人写的博客,通过别人的博客解决了我很多问题,从中也学到了各种知识,虽然不是很系统,但也比较有针对性。所以本次我将我这两天做的东西写成了博客,毕竟水平有限还需学习,所以此文仅供参考,但倘若能帮助到别人解决某些问题,明白某些知识那我将甚感欣慰。
    这是我第一次写博客,难免有很多不足之处,如有意见敬请发表评论 甚是感谢!

    功能实现目标

    1. 控制电机停止与启动。
    2. 控制电机正反转。
    3. 控制电机旋转速度。
    4. 能按一定角度进行步进。

    硬件简介

    本次采用的就是最最最简单的51单片机(不要问我后面程序为什么是reg52.h,问一次打一次)没有外接任何外围器件(除了按键)。只是单纯的控制I/O口,关于单片机的硬件结构就不讲了(其实我也不懂,只会控制下I/O口)。
    TB6600驱动器怎么说呢,我觉的它最大的优势就是性价比吧,几十块钱就可以买一个,而且也能实现要求不是很高的实验,对于学生党来说再合适不过了。输出电流和细分都可以通过拨片按需选择,最高细分可达1/32。电源:要求9-42V直流开关电源。电流的话自己看你的电机功率选择就行。
    -------------此处省略一万字-------------其他的我就不讲了自行百度下使用手册就行了,相信读懂这种简单的使用手册就不在话下了。

    硬件连接

    ----先说说驱动器和电机的连接----
    上图为TB6600说明书给出的接线图
    我此次选用的是两相四线的步进电机,把它的4根线按照电机给的说明书分别接到驱动的的A+,A-,B+,B-即可,驱动器的电源接线就不用说了吧!
    接下来重点来了,因为控制器与驱动器有两种接法,如下图
    TB6600说明书上的共阳接法
    TB6600说明书上的共阴接法
    虽然我们可以每一种都试一下也不耽误时间,但我还是要在这里讲解下为什么我选择了共阳而不选共阴。看过TB6600驱动器说明书的童靴,应该知道它与控制器(就是本文的单片机)的连接有两种方式,即共阴或者共阳,此刻有没有想到数码管的共阴共阳哈哈。其实都是一样的概念。我一看说明书毫不犹豫的就按照共阴的接法接好电路,结果一试,电机它丝毫不动。后来我看了下驱动器的接口是光驱动的,而选择共阴接法的话,就意味着我们得靠单片机I/0口的电流来驱动里面的发光二极管,我们都知道单片机I/o口的驱动能力非常小,查看手册可知I/O口的拉电流只有几uA根本不足以驱动发光二极管,的而它的灌电流可达15mA,此时足以驱动发光二极管,这就是为什么要选择共阳接法。

    程序代码

    // An highlighted block
    /*******************程序功能*********************
       1.控制电机停止与启动
       2.控制电机正反转
       3.控制电机转速
       3.控制电机按一定角度步进
    ************************************************/
    #include<reg52.h>
    //电机控制引脚
    sbit CLK  = P1^0;
    sbit ENA  = P1^1; 
    sbit DIR  = P1^2;		   
    //按键控制端
    sbit P_TS  = P2^0;	       //正转控制端
    sbit N_TS  = P2^1;		   //反转控制端
    sbit P_ADJ = P2^2;         //调速+
    sbit N_ADJ = P2^3;         //调速-
    sbit StopStart  = P2^4;	   //停止与启动
    sbit P_Step = P2^5;
    sbit N_Step = P2^6;
    sbit SS_Step = P2^7;
    
    unsigned int Tspeed[3]={20,4000,10000};	       //调速等级表
    unsigned int StepAngle[4]={100,200,400,800};   //步进角度表--90度/180度/360度/720度
    bit Run_Status=0;
    bit CY_status=0;
    unsigned int CYCLE=20;
    unsigned int cy_count=0;
    unsigned PWM_count=0;
    
    void Init_time();
    void Key_scan();
    void Step(unsigned int step_count);
    /*void delay()				  //延时函数
    {
    	unsigned int i = 200;
    	while (i--);
    } */
    void main()
    {
    	ENA=1;
    	CLK=0;
    	DIR=0;		   //初始化电机
    	Init_time();   //初始化定时器	   
    	while(1)
    	{
    		Key_scan();
    	}	
    }
    void Init_time()				 //初始化定时器
    {
    	TMOD |= 0x01;
    	TH0=(65536-CYCLE)/256; 		 //给time0装初值
    	TL0=(65536-CYCLE)%256;
    	//TH1=(65536-2000)/256;		 //给time1装初值
    	//TL1=(65536-2000)%256;
        IE = 0x82;
    	//PT1=1;                       //使得time1的优先级高于time0
    	TR0=1;				         //打开两个中断
    	//TR1=1;
    }
    void Enter_Timer0() interrupt 1				//进入定时器中断
    {
    	TH0=(65536-CYCLE)/256; 
    	TL0=(65536-CYCLE)%256;
    	CLK=~CLK;
    	PWM_count++;
    	if(PWM_count==(2*cy_count)&&CY_status)
    	{
    		PWM_count=0;
    		TR0=0;
    		ENA=0;
    	}	
    }
    /*void Enter_timer1() interrupt 3
    {
    	TH1=(65536-2000)/256;		 //给time1装初值
    	TL1=(65536-2000)%256;
    	Key_scan();
    } */
    
    /************************按键扫描程序************************
       功能:读取各按键值,判断是否按下,再处理相应事件
       
       注:按键控制程序,由于按键中断优先级高,且每个按键都设计
           为弹起有效, 所以长时间按住不放会导致电机减速甚至停
    	   止直至放开按键		      
    *************************************************************/
    void Key_scan()				   	   
    {
    	static char i=0,j=0;
    	if(P_TS==0)					   //正反转切换
    	{
    		//delay();				   //按键消抖
    		if(P_TS==0)
    		{
    			while(!P_CW);			   //按键按下直到放开
    			DIR=1;
    		}
    	}
    	if(N_TS==0)					   //正反转切换
    	{
    		//delay();				   //按键消抖
    		if(N_TS==0)
    		{
    			while(!N_CW);			   //按键按下直到放开
    			DIR=0;
    		}
    	}
    	if(P_ADJ==0)				   //加速
    	{
    		//delay();			
    		if(P_ADJ==0)
    	    {
    			while(!P_ADJ);
    			i--;
    			if(i<1)
    			i=0;
    			CYCLE=Tspeed[i];		
    		}
    	}
    	if(N_ADJ==0)				   //减速
    	{
    		//delay();
    		if(N_ADJ==0)
    		{
    			while(!N_ADJ);
    			i++;
    			if(i>2)
    			i=2;
    			CYCLE=Tspeed[i];
    		}
    	}
    	if(StopStart==0)
    	{
    		//delay();
    		if(StopStart==0)
    		{
    			while(!StopStart);
    			Run_Status=~Run_Status;
    			if(Run_Status)
    			{
    				ENA=1;		  //启动电机
    				TR0=1;		  //开启中断产生脉冲信号
    			}
    			else
    			{
    				ENA=0;		  //关闭电机
    				TR0=0;		  //关闭中断停止脉冲信号
    				CY_status=0;  //刷新步进标志位
    			}
    		}
    	}
    	if(P_Step==0)
    	{
    		//delay();
    		if(P_Step==0)		  //步进角度+
    		{
    			while(!P_Step);
    			j++;
    			if(j>3)
    			j=3;
    			Step(StepAngle[j]);			
    		}
    	}
    	if(N_Step==0)			  //步进角度-
    	{
    	//	delay();
    		if(N_Step==0)
    		{
    			while(!N_Step);
    			j--;
    			if(j<1)
    			j=0;
    			Step(StepAngle[j]);			
    		}
    	}
    	if(SS_Step==0)   //按一定步进角度步进,每按下一次转动一定步进角后停止
    	{
    		//delay();
    		if(SS_Step==0)
    		{
    			while(!SS_Step);
    			Step(StepAngle[j]);
    		}
    	}
    }
    /***********************角度控制函数*************************/
    void Step(unsigned int step_count)
    {
    	PWM_count=0;
    	CY_status=1;
    	cy_count=step_count;
    	ENA=1;
    	TR0=1;
    }
    
    展开全文
  • 单片机控制步进电机

    万次阅读 多人点赞 2019-06-06 19:07:38
    单片机控制步进电机正转 反转 加速 减速;由LCD1602实时显示步进电机的状态;F-正转,B-反转;数字越大,转速越大; 仿真原理图如下: MCU和LCD1602显示模块: ULN2803驱动和步进电机模块: C语言代码如下...

    简介:
    用单片机控制步进电机正转 反转 加速 减速;
    由LCD1602实时显示步进电机的状态;F-正转 B-反转;数字越大,转速越大;
    仿真原理图如下:
    MCU和LCD1602显示模块:
    在这里插入图片描述
    ULN2803驱动和步进电机模块:
    在这里插入图片描述
    C语言代码如下:

    /*-----------------------------
    FileName: StepperMotor.h
    Function: 函数头文件
    Author: Zhang Kaizhou
    Date: 2019-6-6 17:59:39
    ------------------------------*/
    #include <reg52.h>
    #include <string.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define Factor 5 // 转速控制常数	
    
    /*LCD1602端口设置*/
    sbit lcdrs = P1^0;
    sbit lcdrw = P1^1;
    sbit lcden = P1^2;
    
    /*步进电机驱动器端口设置*/
    sbit direcChange = P1^3; // 方向翻转
    sbit speedUp = P1^4; // 加速
    sbit slowDown = P1^5; // 减速
    
    /*主函数声明*/
    void keyScan();
    void execute();
    
    /*LCD1602显示相关函数声明*/
    void LCDInit();
    void displayInit();
    void display(uchar oper, uchar dat);
    void writeCommand(uchar command);
    void writeData(uchar dat);
    void delay(uchar xms);
    
    /*-------------------------------------------
    FileName:main.c
    Function: MCU控制步进电机
    Description:控制步进电机正转 反转 加速 减速;
    由LCD1602实时显示步进电机的状态;
    F-正转 B-反转;数字越大,转速越大;
    ---------------------------------------------
    Author: Zhang Kaizhou
    Date: 2019-6-6 17:56:41
    -------------------------------------------*/
    #include "StepperMotor.h"
    
    uchar code pulseTable0[] = {0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x04, 0x08}; // 一相励磁(同一时刻只有一个线圈通电,旋转角1.8度)
    uchar code pulseTable1[] = {0x0c, 0x06, 0x03, 0x09, 0x09, 0x03, 0x06, 0x0c}; // 二相励磁(同一时刻有两个线圈通电,旋转角1.8度)
    uchar code pulseTable2[] = {0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, 0x01, 0x09,
    						    0x09, 0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08}; // 一-二相励磁场(一二相交替励磁,旋转角0.9度)
    uchar speed = 0, startPos = 0; // 默认正转
    bit oper = 0/*操作数*/, direcFlag = 0; // 初始状态为正向
    
    void main(){
    	LCDInit(); // LCD1602显示初始化
    	displayInit();
    	while(1){
    		keyScan(); // 按键扫描
    		display(0, direcFlag);
    		display(1, speed);
    		execute();
    	}
    }
    
    /*按键扫描*/
    void keyScan(){
    	if(!speedUp){ // 加速
    		delay(5);
    		if(!speedUp){
    			if(speed < 4){
    				while(!speedUp);
    				speed++;
    			}else{
    				while(!speedUp);
    				speed = 3;
    			}
    		}
    	}
    	if(!slowDown){ // 减速
    		delay(5);
    		if(!slowDown){
    			if(speed != 0){
    				speed--;
    			}else{
    				while(!slowDown);
    				speed = 0;
    			}
    		}
    	}
    	if(!direcChange){ // 方向翻转
    		delay(5);
    		if(!direcChange){
    			while(!direcChange);
    			direcFlag = ~direcFlag;
    		}
    	}
    }
    
    /*步进电机控制执行函数*/
    void execute(){
    	uchar i, j;
    	startPos = (direcFlag == 0) ? 0 : 4; // 方向控制
    	for(i = startPos; i <= (startPos + 4); i++){
    		P2 = pulseTable0[i];
    		for(j = 0; j < (speed + 1) * Factor; j++){ // 用延时来控制脉冲输出的频率,从而控制步进电机转速
    			delay(10);
    		} 
    	}
    }
    
    /*-----------------------------
    FileName:display.c
    Function: LCD1602显示函数
    Author: Zhang Kaizhou
    Date: 2019-6-6 17:58:42
    ------------------------------*/
    #include "StepperMotor.h"
    
    uchar code table0[] = {"Direction:"}; // 每行的字符数据
    uchar code table1[] = {"Speed:"};
    uchar code table2[] = {"1234"};
    uchar code table3[] = {"FB"}; // F-正向 B-反向
    
    /*初始化LCD1602的设置*/
    void LCDInit(){
    	lcden = 0; // 拉低使能端,准备产生使能高脉冲信号
    	writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口)
    	writeCommand(0x0c); // 开显示,不显示光标
    	writeCommand(0x06); // 写一个字符后地址指针自动加1
    	writeCommand(0x01); // 显示清零,数据指针清零
    }
    
    /*LCD上电界面*/
    void displayInit(){
    	uchar i;
    	writeCommand(0x80); // 将数据指针定位到第一行首
    	for(i = 0; i < strlen(table0); i++){
    		writeData(table0[i]);
    		delay(5);
    	}
    	
    	writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
    	for(i = 0; i < strlen(table1); i++){
    		writeData(table1[i]);
    		delay(5);
    	}
    }
    
    /*LCD显示函数*/
    void display(uchar oper, uchar dat){
    	if(oper == 0){ // 方向显示
    		if(dat == 0){ // 正向
    			writeCommand(0x80 + strlen(table0)); // 数据指针定位到第一行空闲处
    			writeData(table3[0]);
    		}else if(dat == 1){ // 反向
    			writeCommand(0x80 + strlen(table0)); // 数据指针定位到第一行空闲处
    			writeData(table3[1]);
    		}
    	}
    	if(oper == 1){ // 速度显示
    		writeCommand(0x80 + 0x40 + strlen(table1)); // 数据指针定位到第二行空闲处
    		writeData(table2[dat]);
    	}
    }
    
    /*写指令函数*/
    void writeCommand(uchar command){
    	lcdrs = 0; // 命令选择
    	lcdrw = 0;
    	P0 = command;
    	delay(5);
    	
    	lcden = 1; // 产生一个正脉冲使能信号
    	delay(5);
    	lcden = 0;
    }
    
    /*写数据函数*/
    void writeData(uchar dat){
    	lcdrs = 1; // 数据选择
    	lcdrw = 0;
    	P0 = dat;
    	delay(5);
    	
    	lcden = 1;
    	delay(5);
    	lcden = 0;
    }
    
    /*延时函数*/
    void delay(uchar xms){
    	uint i, j;
    	for(i = xms; i > 0; i--)
    		for(j = 110; j > 0; j--);
    }
    
    展开全文
  • 基于STM32F4单片机步进电机控制(有代码)

    万次阅读 多人点赞 2019-01-05 11:13:08
    步进电机是将电脉冲控制信号转变为角位移或线位移的一种常用的数字控制执行元件,又称为脉冲电机。在驱动电源的作用下,步进电机受到脉冲的控制,其转子的角位移量和速度严格地与输入脉冲的数量和脉冲频率成正比。...

    步进电机简介

    步进电机是将电脉冲控制信号转变为角位移或线位移的一种常用的数字控制执行元件,又称为脉冲电机。在驱动电源的作用下,步进电机受到脉冲的控制,其转子的角位移量和速度严格地与输入脉冲的数量和脉冲频率成正比。步进电机每接收一个电脉冲,转子就转过一个相应的角度(步距角)。**改变通电顺序可改变步进电动机的旋转方向;改变通电频率可改变步进电动机的转速。**因此,通过控制输入电脉冲的数目、频率及电动机绕组的通电顺序就可以获得所需要的转角、转速及转向,利用单片机就可以很容易实现步进电机的开环数字控制。
    传统的步进电机控制方法是由触发器产生控制脉冲来进行控制的,但此种控制方法工作方式单一而且难于实现人机交互,当步进电机的参数发生变化时,需要重新进行控制器的设计。因此适合于单片机控制,单片机通过向步进电机驱动电路发送控制信号就能实现对步进电机的控制。


    PWM调速方法

    在步进电机控制系统中可以通过输人PWM波的方法来对步进电动的运动进行控制。PWM波的产生可以通过时钟频率、自动重装值等参数进行设置,从而调节PWM波的占空比和输出频率。
    脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制, PWM 原理如图:这里写图片描述
    我们假定定时器工作在向上计数 PWM模式,且当 CNT小于CCRx 时,输出 0,当 CNT大于等于CCRx 时输出 1。那么就可以得到如上的 PWM示意图:当 CNT 值小于 CCRx 的时候, IO 输出低电平(0),当 CNT 值大于等于 CCRx 的时候,IO 输出高电平(1),当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的频率,这就是 PWM 输出的原理。,
    通过控制脉冲占空比来改变电机的电枢电压.改变占空比的方法有3种:(1)定宽调频法,这种方法是保持t1不变,只改变t2,这样周期(T或频率)也随之改变;(2)调宽调频法,保持t1不变,而改变t2,这样也使周期T(或频率)改变;(3)定频调宽法,这种方法是使周期(T或频率)不变,而同时改变t1和t2.由于前两利,方法都改变了周期(或频率),当控制频率与系统的固有频率接近时,将会引起振荡,用的比较少,因此本系统用的是定频调宽法.在脉冲作用下,当电机通电时,速度增加.电机断电时,速度逐渐减小.只要按一定规律,改变通断电时间,即可实现对电机的转速控制。


    系统硬件电路

    系统硬件电路设计框图如下:
    这里写图片描述

    通过对STM32F4单片机编写程序实现对步进电机的控制,并且可以利用计算机和单片机的串口通信,接收到单片机所反馈回来的控制数据,包括:**步进电机的正向转动、反向转动、步进电机的定位功能以及调速功能。**要实现上述功能需要对STM32F4的以下模块进行设置,主要包括:串口通信模块、按键输入模块、电机驱动模块三大部分。下面就以重要模块的实现过程来进行详细的论述。

    串口通信模块

    串口作为 MCU 的重要外部接口,同时也是软件开发重要的调试手段, 其重要性不言而喻。现在基本上所有的 MCU 都会带有串口, STM32 自然也不例外。STM32F4 的串口资源相当丰富的,功能也相当强劲。 ALIENTEK 探索者 STM32F4 开发板所使用的 STM32F407ZGT6 最多可提供 6 路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持 LIN、 支持调制解调器操作、 智能卡协议和 IrDA SIR ENDEC 规范、具有 DMA 等。
    处理器与外部设备通信的两种方式:
    并行通信:
    -传输原理:数据各个位同时传输。
    -优点:速度快
    -缺点:占用引脚资源多

    串行通信:
    -传输原理:数据按位顺序传输。
    -优点:占用引脚资源少
    -缺点:速度相对较慢
    这里我们选用串行通信。串行通信按照数据传送方向,分为:
    单工
    数据传输只支持数据在一个方向上传输
    半双工
    允许数据在两个方向上传输,但是,在某一时刻,只允许数
    据在一个方向上传输,它实际上是一种切换方向的单工通信;
    全双工
    允许数据同时在两个方向上传输,因此,全双工通信是两个
    单工通信方式的结合,它要求发送设备和接收设备都有独立
    的接收和发送能力。 这里写图片描述
    这里我们给出串口配置的一般步骤:
    ①串口时钟使能:RCC_APBxPeriphClockCmd();
    GPIO时钟使能:RCC_AHB1PeriphClockCmd();
    ② 引脚复用映射:
    GPIO_PinAFConfig();
    ③GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF
    ④串口参数初始化:USART_Init();
    ⑤开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
    NVIC_Init();
    USART_ITConfig();
    ⑥使能串口:USART_Cmd();
    ⑦编写中断处理函数:USARTx_IRQHandler();
    ⑧串口数据收发:
    void USART_SendData();//发送数据到串口,DR
    uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
    ⑨串口传输状态获取:
    FlagStatus USART_GetFlagStatus();
    void USART_ClearITPendingBit();

    相关代码如下:

    void uart_init(u32 bound) //GPIO端口设置 
    { 
    GPIO_InitTypeDef GPIO_InitStructure; 
    USART_InitTypeDef USART_InitStructure; 
    NVIC_InitTypeDef NVIC_InitStructure; 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIO时钟 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1 
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //使能GPIOA9时钟 
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //使能GPIOA10时钟 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHZ 
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用功能 
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 
    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10 
    USART_InitStructure.USART_BaudRate = bound;//波特率设置 
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 
    USART_Init(USART1, &USART_InitStructure); //初始化串口1 
    USART_Cmd(USART1, ENABLE); //使能串口1 
    #if EN_USART1_RX 
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 
    } 
    
    void USART1_IRQHandler(void)                	//串口1中断服务程序
    {
    	u8 Res;
    #if SYSTEM_SUPPORT_OS 	
    //如果SYSTEM_SUPPORT_OS为真,则需要支持OS
    	OSIntEnter();    
    #endif
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接受到的数据必须是0x0d 0x0a结尾)
    	{
    		Res =USART_ReceiveData(USART1);//(USART1->DR);	//(USART1->DR);//读取接收到的数据
    		
    		if((USART_RX_STA&0x8000)==0)//接收未完成
    		{
    			if(USART_RX_STA&0x4000)//接收到了0x0d
    			{
    				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
    				else USART_RX_STA|=0x8000;	//接收完成了
    			}
    			else //还没收到0X0D
    			{	
    				if(Res==0x0d)USART_RX_STA|=0x4000;
    				else
    				{
    					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
    					USART_RX_STA++;
    					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收  
    				}		 
    			}
    		}   		 
      } 
    #if SYSTEM_SUPPORT_OS 	
    //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    	OSIntExit();  											 
    #endif
    } 
    #endif	
    

    按键输入模块

    STM32F4开发板上的按键 KEY0 连接在 PE4 上、 KEY1 连接在 PE3 上、 KEY2 连接在 PE2 上、 KEY_UP连接在 PA0 上。 如图所示:
    这里写图片描述
    在此次实验中,我们设置按下 KEY-UP, 电机以 所设定频率回到绝对原点; 按下 KEY0, 电机以所设定频率顺时针转动; 按下 KEY1, 电机以所设定频率逆时针转动。
    下面给出实现按键输入的一般步骤:
    ①使能按键对应IO口时钟。调用函数:
    RCC_AHB1PeriphClockCmd ();
    ②初始化IO模式:上拉/下拉输入。调用函数:
    GPIO_Init();
    ③扫描IO口电平(库函数/寄存器/位操作)。
    相关代码如下:

    void KEY_Init(void)
    {
      GPIO_InitTypeDef  GPIO_InitStructure;
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //KEY0 KEY1 KEY2对应引脚
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
      GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIO2,3,4
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//WK_UP对应引脚  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;//下拉
      GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0
     } 
    
    u8 KEY_Scan(u8 mode)
    {	 
    	static u8 key_up=1;//按键松开标志
    	if(mode)key_up=1;  //支持连接		  
    	if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
    	{
    		delay_ms(10);//去抖动
    		key_up=0;
    		if(KEY0==0)return 1;
    		else if(KEY1==0)return 2;
    		else if(KEY2==0)return 3;
    		else if(WK_UP==1)return 4;
    	}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1; 	    
     	return 0;// 无按键按下
    }
    

    电机驱动模块

    电源与驱动器连接方法如下图:这里写图片描述
    驱动器与STM32F4连接如下图:
    这里写图片描述
    代码需要用到的 4 个主要函数如下:
    void Driver_Init(void);//驱动器初始化
    void TIM8_OPM_RCR_Init(u16 arr, u16 psc); //TIM8_CH2 初始化 单脉冲+重复计数模式
    void Locate_Rle(long num, u32 frequency, DIR_Type dir) //相对定位函数
    void Locate_Abs(long num, u32 frequency);/绝对定位函数
    1)驱动器初始化函数,主要就是初始化与驱动器 ENA+,DIR+相连的 2 个 IO为推挽输出。
    2) TIM8_CH2 初始化, 此例程产生脉冲所使用的定时器均是 TIM8_CH2(PC7) ,定时器工作在单脉冲+重复计数模式,需要注意的是定时器必须初始化为 1MHz 计数频率。
    3) 相对定位函数: 在步进电机当前位置基础上顺时针(CW)或者逆时针(CCW)走 num 个脉冲, 此函数带方向控制, DIR_Type 是 driver.h 下声明的一个枚举类型,用于设置电机旋转方向,参数 dir=CW,电机顺时针旋转; dir=CCW,电机逆时针旋转。
    绝对定位函数:步进电机按设定频率转动到设置的绝对位置, 开发板上电和复位时,当前位置为 0,电机的当前位置用一个 long 型变量 current_pos 指示。 在current_pos=0 的基础上顺时针转动后 current_pos 为正, 否则为负。 5) 此例程配置了 usmart 函数和按键函数,可以通过按键或者串口调用相对定位函数和绝对定位函数控制驱动器,从而控制步进电机。
    驱动模块代码如下:

    u8 rcr_remainder;   //重复计数余数部分
    u8 is_rcr_finish=1; //重复计数器是否设置完成
    long rcr_integer;	//重复计数整数部分
    long target_pos=0;  //有符号方向
    long current_pos=0; //有符号方向
    DIR_Type motor_dir=CW;//顺时针
    

    驱动控制信号线初始化:

    void Driver_Init(void)
    {
    	GPIO_InitTypeDef  GPIO_InitStructure;
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟
     	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6; //DRIVER_DIR DRIVER_OE对应引脚
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE5,6
    		GPIO_SetBits(GPIOE,GPIO_Pin_5);//PE5输出高 顺时针方向  DRIVER_DIR
    	GPIO_ResetBits(GPIOE,GPIO_Pin_6);//PE6输出低 使能输出 DRIVER_OE
    }
    

    单脉冲+重复计数模式:

    void TIM8_OPM_RCR_Init(u16 arr,u16 psc)
    {		 					 
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);  	//TIM8时钟使能    
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 	//使能PORTC时钟	                                                                     	
    	GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM8); //GPIOC7复用为定时器8
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;           //GPIOC7
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;      //下拉
    	GPIO_Init(GPIOC,&GPIO_InitStructure);               //初始化PF9
    	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    	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(TIM8, &TIM_TimeBaseStructure); //根据TIM_TimeBaseStructure中指定的参数化TIMX的时间基数单位
    	TIM_ClearITPendingBit(TIM8,TIM_IT_Update);
    	TIM_UpdateRequestConfig(TIM8,TIM_UpdateSource_Regular); /********* 设计只有计数溢出作为更新中断 ********/
    	TIM_SelectOnePulseMode(TIM8,TIM_OPMode_Single);/******* 单脉冲模式**********/
     	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
    	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出2使能
    	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; /****** 比较输出2N使能 *******/
    	TIM_OCInitStructure.TIM_Pulse = arr>>1; //设置待装入捕获比较寄存器的脉冲值
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
    	TIM_OC2Init(TIM8, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMX
    	TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);  //CH2预装载值 
    	TIM_ARRPreloadConfig(TIM8, ENABLE); //使能TIMX在ARR上的预装载值
    	TIM_ITConfig(TIM8, TIM_IT_Update ,ENABLE);  //TIM8   使能或者失能指定的TIM中断
     	NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;  //TIM8中断
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级1级
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
    	TIM_ClearITPendingBit(TIM8, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM中断源
    	TIM_Cmd(TIM8, ENABLE);  //使能TIM8											  
    }
    

    TIM8更新中断服务程序:

    void TIM8_UP_TIM13_IRQHandler(void)
    {
    	if(TIM_GetITStatus(TIM8,TIM_FLAG_Update)!=RESET)//更新中断
    	{
    		TIM_ClearITPendingBit(TIM8,TIM_FLAG_Update);//清除更新中断标志位		
    		if(is_rcr_finish==0)//重复计数器未设置完成
    		{
    			if(rcr_integer!=0) //整数部分脉冲还未发送
    			{
    				TIM8->RCR=RCR_VAL;//设置重复计数值
    				rcr_integer--;//减少RCR_VAL+1个脉冲			
    			}else if(rcr_remainder!=0)//余数部分脉冲 不为0
    			{
    				TIM8->RCR=rcr_remainder-1;//设置余数部分
    				rcr_remainder=0;//清零
    				is_rcr_finish=1;//重复计数器设置完成				
    			}else goto out;   //rcr_remainder=0直接退出			 
    			TIM_GenerateEvent(TIM8,TIM_EventSource_Update);//产生一个更新事件 重新初始化计数器
    			TIM_CtrlPWMOutputs(TIM8,ENABLE);	//MOE主输出使能	
    			TIM_Cmd(TIM8, ENABLE);  //使能TIM8			
    			if(motor_dir==CW) //如果方向为顺时针 
    				current_pos+=(TIM8->RCR+1);//加上重复计数值
    			else          //否则方向为逆时针
    				current_pos-=(TIM8->RCR+1);//减去重复计数		
    		}else
    		{
    out:		is_rcr_finish=1;//重复计数器设置完成
    			TIM_CtrlPWMOutputs(TIM8,DISABLE);	//MOE 主输出关闭
    			TIM_Cmd(TIM8, DISABLE);  //关闭TIM8				
    			printf("µ±Ç°Î»ÖÃ=%ld\r\n",current_pos);//打印输出
    		}	
    	}
    }
    

    启动TIM8:

    void TIM8_Startup(u32 frequency)   //启动定时器8
    {
    	u16 temp_arr=1000000/frequency-1; 
    	TIM_SetAutoreload(TIM8,temp_arr);//设定自动重装值	
    	TIM_SetCompare2(TIM8,temp_arr>>1); //匹配值2等于重装值一半,是以占空比为50%
    	TIM_SetCounter(TIM8,0);//计数器清零
    	TIM_Cmd(TIM8, ENABLE);  //使能TIM8
    }
    

    相对定位函数:

    void Locate_Rle(long num,u32 frequency,DIR_Type dir) //相对定位函数
    {
    	if(num<=0) //数值小于等于0 则直接返回
    	{
    		printf("\r\nThe num should be greater than zero!!\r\n");
    		return;
    	}
    	if(TIM8->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;
    	}
    	motor_dir=dir;//得到方向	
    	DRIVER_DIR=motor_dir;//设置方向
    		if(motor_dir==CW)//顺时针
    		target_pos=current_pos+num;//目标位置
    	else if(motor_dir==CCW)//逆时针
    		target_pos=current_pos-num;//目标位置
    	rcr_integer=num/(RCR_VAL+1);//重复计数整数部分
    	rcr_remainder=num%(RCR_VAL+1);//重复计数余数部分
    	is_rcr_finish=0;//重复计数器未设置完成
    	TIM8_Startup(frequency);//开启TIM8
    }
    

    绝对定位函数:

    void Locate_Abs(long num,u32 frequency)//绝对定位函数
    {
    	if(TIM8->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;
    	}
    	target_pos=num;//设置目标位置
    	if(target_pos!=current_pos)//目标和当前位置不同
    	{
    		if(target_pos>current_pos)
    			motor_dir=CW;//顺时针
    		else
    			motor_dir=CCW;//逆时针
    		DRIVER_DIR=motor_dir;//设置方向
    		
    		rcr_integer=abs(target_pos-current_pos)/(RCR_VAL+1);//重复计数整数部分
    		rcr_remainder=abs(target_pos-current_pos)%(RCR_VAL+1);//重复计数余数部分
    		is_rcr_finish=0;//重复计数器未设置完成
    		TIM8_Startup(frequency);//开启TIM8
    	}
    }
    

    最后是主函数:

    int main(void)
    { 
    	u8 i;
    	u8 keyval;
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    	delay_init(168);      //初始化延时函数
    	uart_init(115200);		//初始化串口波特率115200
    	usmart_dev.init(84); 	//初始化USMART			
    	LED_Init();					  //初始化LED
     	KEY_Init();					//初始化按键
    	Driver_Init();			//驱动器初始化
    	TIM8_OPM_RCR_Init(999,168-1); //1MHz计数频率 单脉冲+重复计数模式
    	while(1) 
    	{		 	  
    		keyval=KEY_Scan(0);
    		if(keyval==WKUP_PRES)
    		{
    			Locate_Abs(0,500);//按下WKUP,回到零点
    		}else if(keyval==KEY0_PRES)
    		{
    			Locate_Rle(1200,500,CW);//按下KEY0,以500Hz的频率 顺时针发200脉冲
    		}else if(keyval==KEY1_PRES)
    		{
    			Locate_Rle(1200,500,CCW);//按下KEY1,以500Hz频率 逆时针发400脉冲
    		}			
    		delay_ms(10);
    		i++;
    		if(i==50)	
    		{	
    			i=0;
    			LED1=!LED1;
    		}			
    	}
    }
    

    可以根据实际要求修改参数值以达到相应目的控制步进电机转动的转速和步距角。


    实验验证

    设置驱动器细分和电流, 完成硬件接线, 然后给开发板上电(USB232 接口), 打开 XCOM 调试助手,找到对应COM,设置波特率 115200,1 位停止位,8位数据位,无校验,勾上发送新行,然后打开串口,最后给驱动器上电。按下 KEY-UP, 电机以 500Hz 频率回到绝对原点; 按下 KEY0, 电机以 500Hz 频率顺时针走 200 个脉冲; 按下KEY1,电机以 500Hz 频率逆时针走 400 个脉冲;依次按下KEY_UP, KEY0, KEY1,串口打印的情况如下。
    这里写图片描述
    点击发送条目后边的数字就可调用该函数, 这儿的相对的定位函数 Locate_Rle 最后
    一个参数用于设置电机旋转方向的, 0(CCW) 表示逆时针方向, 1(CW) 表示顺时针方向,实验时, 如果电机旋转方向和设置方向相反, 只需更改 driver.h 下的CW=0,CCW=1;每调用一次函数,串口打印当前的位置。 然后我们依次调用这 4 个函数, 根据串口的打印, 可以看到当前位置的变化情况,如图所示。
    这里写图片描述


    结语

    本文介绍了利用单片机控制基于STM32F4芯片的步进电机定位控制系统的整体设计思路以及用pwm实现对步进电机控制的脉冲时序的分配进行了详细的仿真。利用STM32F4芯片严谨的基于硬件的编程语言和精确的时间控制特点,准确地实现了精确定位功能,对步进电机的运行速度的精确控制。实践证明,这种方法定位准确,控制速度精确,是一种行之有效的方案。


    1.此次实验所选用的的驱动器为TB6600步进电机专用驱动器。
    TB6600步进电机驱动器是一款专业的两相步进电机驱动,可实现正反转控制。通 过S1 S2 S3 3位拨码开关选择8 档细分控制(1、2、4、8、16 ),通过S4 S5 S6 3位拨码开关选择6档电流控制(0.5A,1A,1.5A,2.0A,2.5A,3.0A, 3.5A, 4.0A)。适合驱动86,57,42,39 型两相、四相混合式步进电机。驱动器具有 噪音小,震动小,运行平稳的特点。
    这里写图片描述
    TB6600步进电机专用驱动器电气参数如下表:
    这里写图片描述
    2.此次实验所选用的步进电机为57步进电机。其相关参数及尺寸如下。
    这里写图片描述

    展开全文
  • 42步进电机控制的参考资料

    千次阅读 2018-02-02 08:51:40
    基于stm32单片机,keil5编译平台 又一参考资料 ... 应该是指使用TB6600电机驱动器之类的...我们已经有了一个同时控制四个步进电机的例程,你可以去参考 硬石步进电机资料(2016-06-06更新) http://www.ing10bbs.com/fo

    基于stm32单片机,keil5编译平台
    又一参考资料
    http://www.ing10bbs.com/forum.php?mod=viewthread&tid=93&fromuid=4

    应该是指使用TB6600电机驱动器之类的吧
    我们已经有了一个同时控制四个步进电机的例程,你可以去参考
    硬石步进电机资料(2016-06-06更新)
    http://www.ing10bbs.com/forum.ph … id=93&fromuid=4
    (出处: 硬石社区)

    资源帖:http://www.ing10bbs.com/forum.php?mod=viewthread&tid=1458&fromuid=4

    /**
      ******************************************************************************
      * 文件名程: main.c 
      * 作    者: 硬石嵌入式开发团队
      * 版    本: V1.0
      * 编写日期: 2015-10-04
      * 功    能: 步进电机控制实现
      ******************************************************************************
      * 说明:
      * 本例程配套硬石stm32开发板YS-F1Pro使用。
      * 
      * 淘宝:
      * 论坛:http://www.ing10bbs.com
      * 版权归硬石嵌入式开发团队所有,请勿商用。
      ******************************************************************************
      */
    /* 包含头文件 ----------------------------------------------------------------*/
    #include "stm32f1xx_hal.h"
    #include "StepMotor/bsp_STEPMOTOR.h"
    #include "key/bsp_key.h"
    
    /* 私有类型定义 --------------------------------------------------------------*/
    /* 私有宏定义 ----------------------------------------------------------------*/
    #define STEPMOTOR_MICRO_STEP      32  // 步进电机驱动器细分,必须与驱动器实际设置对应
    
    /* 私有变量 ------------------------------------------------------------------*/
    uint8_t dir=0; // 0 :顺时针   1:逆时针 
    uint8_t ena=0; // 0 :正常运行 1:停机
    
    /* 扩展变量 ------------------------------------------------------------------*/
    extern __IO uint16_t Toggle_Pulse; /* 步进电机速度控制,可调节范围为 650 -- 3500 ,值越小速度越快 */
    
    /*
    *    当步进电机驱动器细分设置为1时,每200个脉冲步进电机旋转一周
    *                          为32时,每6400个脉冲步进电机旋转一周
    *    下面以设置为32时为例讲解:
    *    pulse_count用于记录输出脉冲数量,pulse_count为脉冲数的两倍,
    *    比如当pulse_count=12800时,实际输出6400个完整脉冲。
    *    这样可以非常方便步进电机的实际转动圈数,就任意角度都有办法控制输出。
    *    如果步进电机驱动器的细分设置为其它值,pulse_count也要做相应处理
    *
    */
    __IO uint32_t pulse_count; /*  脉冲计数,一个完整的脉冲会增加2 */
    
    /* 私有函数原形 --------------------------------------------------------------*/
    /* 函数体 --------------------------------------------------------------------*/
    /**
      * 函数功能: 主函数.
      * 输入参数: 无
      * 返 回 值: 无
      * 说    明: 无
      */
    int main(void)
    {  
      uint8_t key1_count=1;
    
      /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
      HAL_Init();
      /* 配置系统时钟 */
      SystemClock_Config();
    
      KEY_GPIO_Init();
    
      /* 高级控制定时器初始化并配置PWM输出功能 */
      STEPMOTOR_TIMx_Init();
    
      /* 确定定时器 */
      HAL_TIM_Base_Start(&htimx_STEPMOTOR);
      /* 启动比较输出并使能中断 */
      HAL_TIM_OC_Start_IT(&htimx_STEPMOTOR,TIM_CHANNEL_1);
    
      /* 无限循环 */
      while (1)
      {
        if(KEY1_StateRead()==KEY_DOWN)  // 功能选择
        {
           key1_count++;
           if(key1_count==5)
             key1_count=1;
        }
        if(KEY2_StateRead()==KEY_DOWN)  // 功能调节
        {
          switch(key1_count)
          {
            case 1:
              Toggle_Pulse-=50;
              if(Toggle_Pulse<300)  // 最快速度限制
                Toggle_Pulse=300;
              break;
            case 2:
              Toggle_Pulse+=100;
              if(Toggle_Pulse>3500)         // 最慢速度限制
                Toggle_Pulse=3500;
              break;  
            case 3:                // 方向控制
              if(dir==0)
              {
                STEPMOTOR_DIR_REVERSAL();  // 反转
                dir=1;
              }
              else
              {
                STEPMOTOR_DIR_FORWARD();   // 正转
                dir=0;
              }
              break;  
            case 4:                // 脱机使能控制
              if(ena==0)
              {
                STEPMOTOR_OUTPUT_ENABLE(); // 停机
                ena=1;
              }
              else
              {
                pulse_count=0;            // 重新计数
                STEPMOTOR_OUTPUT_DISABLE();  // 正常运行
                ena=0;
              }
              break;
            default:
              break;          
          }
        }
        if(pulse_count==STEPMOTOR_MICRO_STEP*200*2*10)  // 转动10圈后停机 
        {
          STEPMOTOR_OUTPUT_DISABLE(); // 停机
        }
      }
    }
    
    /**
      * 函数功能: 定时器比较输出中断回调函数
      * 输入参数: htim:定时器句柄指针
      * 返 回 值: 无
      * 说    明: 无
      */
    void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
    {
      __IO uint16_t count;
      count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);
      __HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,TIM_CHANNEL_1,count+Toggle_Pulse);
      pulse_count++;
    }
    
    /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
    
    展开全文
  • 基于STC89C51和L298N的42步进电机控制

    万次阅读 多人点赞 2020-06-19 09:17:19
    步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角。步进电机必须由双环形...
  • 51单片机按键控制步进电机加减速及正反转

    万次阅读 多人点赞 2020-04-09 18:44:09
    之前尝试用单片机控制42步进电机正反转,电机连接导轨实现滑台前进后退,在这里分享一下测试程序及接线图,程序部分参考网上找到的,已经实际测试过,可以实现控制功能。 所用硬件:步进电机及驱动器、STC89C52...
  • 单片机控制步进电机-电路连接

    千次阅读 多人点赞 2019-02-22 21:26:14
    单片机控制步进电机-线路连接 说明:如何利用单片机去控制步进电机?本案例讲解的内容是硬件连接部分,采用常用的电子器件去实现单片机控制步进电机的功能。后续会分别讲解单片机程序,S曲线生成方法,上位机等...
  • 单片机-控制-步进电机

    千次阅读 多人点赞 2018-08-18 23:01:57
    开始浏览正文之前,请大家先花几分钟看完这段...通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(即步进角),是现代数字程序控制系统中的主要执行元件,应用极为...
  • 单片机控制步进电机-AVR详细程序

    千次阅读 2019-02-22 21:24:48
    单片机控制步进电机-单片机程序(avr) 硬件线路连接图见上一篇文章 软件: ICCV7 FOR AVR-写程序 Progisp-烧程序 速度S曲线生成器(后续后单独讲解)-生成S曲线数组代码 硬件: Atmega16 ASP下载线 杜邦...
  • 基于51单片机步进电机控制

    万次阅读 多人点赞 2018-05-10 18:23:41
    前面笔者分享过基于51单片机的两种小车制作,我们利用的是L298N驱动控制电机转动,那么接下来,笔者给大家介绍两种利用51单片机控制步进电机的小程序。 首先我们要如何使电机转动呢,源程序如下: #include &...
  • 51单片机步进电机实验

    千次阅读 2019-05-19 19:30:38
    1.步进电机图片 2.步进电机介绍 ...这一线性关系的存在,加上步进电机只有周期性的误差而无累积误差等特点,使得步进电机在速度、位置等控制领域的控制操作非常简单。虽然步进电机应用广泛,但它并不像...
  • 单片机控制步进电机和部分机器人电路图,接线图,代码
  • at89c51单片机扩展芯片控制步进电机proteus仿真图,可进行正转反转和速度控制
  • 该工程是在keil开发环境下c51单片机控制步进电机的控制程序,实现四相四拍、四相八拍的正转及反转
  • 4按键控制,分别是启停、正反转、+速、-速。51单片机控制板电路图,程序源码+注解下载
  • 【arduino】arduino uno + A4988控制42步进电机

    万次阅读 多人点赞 2017-12-02 09:21:09
    MS1 , MS2 , MS3 跳线说明:(例子里是低电平,悬空或接地线,使用全步进模式) ...分别是全步进,1/2步进,1/4...步进电机走一步是1.8度,一圈就是200步。例如使用1/16步进,则需要走3200步才等于一圈。 ms1 
  • 如何用51单片机控制步进电机运动

    万次阅读 多人点赞 2017-01-05 17:56:26
    本来接触单片机挺久了的,但是一直只是停留在非常初级的认识阶段,本科的时候上过几门课,但是从来没有自己捣鼓过单片机,这次突然来了兴趣,感觉一下子学到了好多东西,在这里好好整理一下。这篇文章只适合于入门...
  • 利用单片机控制基于STM32F4芯片的步进电机定位控制系统的整体设计思路以及用pwm实现对步进电机控制的脉冲时序的分配进行了详细的仿真。利用STM32F4芯片严谨的基于硬件的编程语言和精确的时间控制特点,准确地实现了...
  • 单片机控制步进电机运动控制系统 ,朱雷平,,采用单片机AT89C55作为控制系统的核心,控制双步进电机带小负载做运动。 单片机接收相应的信号执行显示程序和轨迹控制程序,向LCD显�
  • Arduino单片机控制步进电机

    千次阅读 2019-12-12 01:05:10
    步进电机是一种将电脉冲转化为角位移的执行机构。当步进电机的驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(即步长)。通过控制脉冲个数来控制角位移量,达到准确定位的目的;通过...
1 2 3 4 5 ... 20
收藏数 1,850
精华内容 740
关键字:

单片机控制42步进电机