步进电机C语言程序
- 格式:pdf
- 大小:122.35 KB
- 文档页数:7
步进电机控制-C程序及仿真步进电机步进电机和普通电动机不同之处是步进电机接受脉冲信号的控制。
步进电机可以直接接受数字信号,不需要进行数字与模拟量的转换,具有高精度快速启停能力。
在非超载的情况下,步进电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角。
这一线性关系的存在,加上步进电机只有周期性的误差而无累积误差等特点。
使得在速度、位置等控制领域用步进电机来控制变的非常的简单。
一、步进电机的结构和工作原理步进电机是一种专门用于位置和速度精确控制的特种电机。
步进电机的最大特点是其“数字性”,对于微电脑发过来的每一个脉冲信号,步进电机在其驱动器的推动下运转一个固定角度(简称一步),如下图所示。
如接收到一串脉冲步进电机将连续运转一段相应距离。
同时可通过控制脉冲频率,直接对电机转速进行控制。
步进电机在构造上有三种主要类型:反应式(Variable Reluctance,VR)、永磁式(Permanent Magnet,PM)和混合式(Hybrid Stepping,HS)。
反应式定子上有绕组、转子由软磁材料组成。
结构简单、成本低、步距角小,可达1.2°、但动态性能差、效率低、发热大,可靠性难保证。
永磁式永磁式步进电机的转子用永磁材料制成,转子的极数与定子的极数相同。
其特点是动态性能好、输出力矩大,但这种电机精度差,步矩角大(一般为7.5°或15°)。
混合式混合式步进电机综合了反应式和永磁式的优点,其定子上有多相绕组、转子上采用永磁材料,转子和定子上均有多个小齿以提高步矩精度。
其特点是输出力矩大、动态性能好,步矩角小,但结构复杂、成本相对较高。
混合型,因具有高精度、高转矩、微小步进角和数个优异的特征,所以刚开始在OA 关系,其它的分类上也大幅的被使用,特别是在生产量上大半是使用在盘片记忆关系的磁头转送上。
按定子上绕组来分,共有二相、三相和五相等系列。
接口课程设计任务书学生姓名专业班级指导老师工作单位计算机学院题目:步进电机控制设计(C程序设计语言)一、内容:在MIFID微机实验台上以双八拍的方式控制步进电机运行,用按钮控制启动和停止。
接口硬件电路图见说明书。
二、要求:1、控制步进电机运行的相序表存储在文件中。
2、按下SW1按钮,从文件中取出一个相序数据,从并行接口8255A的PA口输出,使步进电机运行。
相序数据在CRT上显示。
按下SW2按钮,步进电机运行停止。
3、SW1按钮的数字量由PC1输入,SW2按钮的数字量由PC0输入,4、设计程序运行时的界面友好。
三、进度安排:指导教师签名:年月日系主任(责任教师)签名:年月日一.设计目的和内容目的:通过步进电机控制实验,学习并行接口电路及其控制程序的设计原理与方法。
内容:在MIFID微机实验台上以双八拍的方式控制步进电机运行,用按钮控制启动和停止。
接口硬件电路图见说明书。
要求:1、控制步进电机运行的相序表存储在文件中。
2、按下SW1按钮,从文件中取出一个相序数据,从并行接口8255A的PA口输出,使步进电机运行。
相序数据在CRT上显示。
按下SW2按钮,步进电机运行停止。
3、SW1按钮的数字量由PC1输入,SW2按钮的数字量由PC0输入,4、设计程序运行时的界面友好。
二、实验预备知识可编程并行接口8255是一个具有两个8位(A端口和B端口)和两个4位(C端口)并行I/O端口的芯片。
在与外设进行数据传输时,把A、B、C3个端口分为两组。
A组由A端口和C端口的高4位组成。
B组由B端口和C端口的低4位组成。
为了满足多种数据传输的要求,可以通过对8255的编程用方式控制字设置3种工作方式来实现。
这3种工作方式为:方式0(基本I/O工作方式);方式1(选通I/O工作方式);方式2(双向传送方式)。
8255的控制字有工作方式控制字和C端口的位置位/复位控制字。
工作方式控制字是必须要预先设定的,C端口的位置位/复位控制字可视需要而定。
一、电子琴1、连线:按键K1~K7与P10~P16相连,蜂鸣器与P33(INT1)相连。
2、流程图3、程序#include "reg51.h"sbit P3_3=P3^3;unsigned char idata i,tl0_temp=0,th0_temp=0;void INTTO() interrupt 1{TH0=th0_temp;TL0=tl0_temp;P3_3=~P3_3;}main(){P1=0Xff;TMOD=0X01;ET0 =1;EA =1;TH0=0;TL0=0;TCON =0x10;while(1){i=P1;if(i==0xff)TR0=0;if(i==0xfe){th0_temp=0xfC;tl0_temp=0x42;TR0 =1;}if(i==0xFD){th0_temp=0xFC;tl0_temp=0xAE;TR0=1;}if(i==0xFB){th0_temp=0xFD;tl0_temp=0x0A;TR0 =1;}if(i==0xF7){th0_temp=0xFD;tl0_temp=0x35;TR0 =1;}if(i==0xEF){th0_temp=0xFD;tl0_temp=0x82;TR0 =1;}if(i==0xDF){th0_temp=0xFD;tl0_temp=0xC8;TR0 =1;}if(i==0xBF){th0_temp=0xFE;tl0_temp=0x05;TR0 =1;}}}二、步进电机1、连线P1.0---P1.3依次连接A-DP3.4—K2 调节转向P3.5—K1 调节转速2、流程图3、程序#include "reg51.h"sbit SW1=P3^4;sbit KEY1=P3^5;bit Key1Flag;void DELAY(unsigned char dly){unsigned char i,j;for(i=0;i<dly;i++)for(j=0;j<255;j++);}void Mode1_deasil(unsigned char dly){P1=0x01; //ADELAY(dly);P1=0x02; //BDELAY(dly);P1=0x04; //CDELAY(dly);P1=0x08; //DDELAY(dly);}void Mode1_anticlockwise(unsigned char dly){P1=0x08; //DDELAY(dly);P1=0x04; //CDELAY(dly);P1=0x02; //BDELAY(dly);P1=0x01; //ADELAY(dly);}main(){unsigned char counter;counter=10;while(1){if(SW1==1)Mode1_deasil(counter);elseMode1_anticlockwise(counter);if((Key1Flag==0)&&(KEY1==1))Key1Flag= 1;elseif((Key1Flag==1)&&(KEY1==0)){DELAY(50);if(KEY1==0){Key1Flag=0;counter=counter+50;if(counter>=250)counter=50;}}}}三、直流电机1、连线P3.5—PWM0-5V输出---直流电机输入(至D/A)P1.1 ——K1P1.2——K22、流程图3、程序#include "reg51.h"sbit PWMout=P3^5;sbit KEY1=P1^1;sbit KEY2=P1^2;bit Key1Flag;bit Key2Flag;unsigned char Th0_temp,Tl0_temp;void DelayS(unsigned int dly);void key_check(void);void INTTO() interrupt 1{TR0=0;PWMout=0;}void INTT1() interrupt 3{TL0=Tl0_temp;TH0=Th0_temp;TR0=1;PWMout=1;}void DelayS(unsigned int dly){unsigned int i;for(; dly>0; dly--){for(i=0; i<1000; i++);}}void key_check(void){if((Key1Flag==0)&&(KEY1==1))Key1Flag=1;else if((Key1Flag==1)&&(KEY1==0)){DelayS(10); //k1按下加速if(KEY1==0){Key1Flag=0;Th0_temp-=0x10;if(Th0_temp<=0) Th0_temp=0x10;}}else if((Key2Flag==0)&&(KEY2==1))Key2Flag=1;//k2按下减速else if ((Key2Flag==1)&&(KEY2==0)){DelayS(10);if(KEY2==0){Key2Flag=0;Th0_temp+=0x10;if(Th0_temp>=250)Th0_temp=0xF0;}}}void main(){TMOD=0x11;TL0=0x00;TH0=0x70;Th0_temp=0x70;Tl0_temp=0x00;TL1=0x00;TH1=0x00;ET1=1;ET0=1;EA=1;TR1=1;while(1){key_check();}}四、串口通讯1、连线实验箱仿真头的TxD,RxD接用户串行口的TxD,RxD。
步进电机控制程序(2008-06-05 19:07:55)转载分类:程序设计标签:it步进电机(键盘控制可调速)#include <reg51.h>#define uchar unsigned charstatic unsigned int count; //计数static int step_index; //步进索引数,值为0-7static bit turn; //步进电机转动方向static bit stop_flag; //步进电机停止标志static int speedlevel; //步进电机转速参数,数值越大速度越大,最小值为1,速度最慢static int spcount; //步进电机转速参数计数void ddelay(void); //键盘扫描延时函数void delay(unsigned int endcount); //延时函数,延时为endcount*1毫秒void gorun(); //步进电机控制步进函数sbit P10=P2^0 ; //电机端口定义sbit P11=P2^1 ;sbit P12=P2^2;sbit P13=P2^3 ;void ddelay(void){uchar i;for (i=300;i>0;i--);}uchar keyscan(void){uchar scancode;uchar tmpcode;P1 = 0xf8; // 发全0行扫描码if ((P1&0xf8)!=0xf8) // 若有键按下{ddelay(); // 延时去抖动if ((P1&0xf8)!=0xf8) // 延时后再判断一次,去除抖动影响{scancode = 0xfe;while((scancode&0x08)!=0) // 逐行扫描{P1 = scancode; // 输出行扫描码if ((P1&0xf8)!=0xf8) // 本行有键按下tmpcode = (P1&0xf8)|0x07;return((~scancode)+(~tmpcode)); // 返回特征字节码,为1的位即对应于行和列 }else scancode = (scancode<<1)|0x01; // 行扫描码左移一位}}}return(0); // 无键按下,返回值为0}void main(void){uchar key;count = 0;step_index = 0;spcount = 0;P10 = 0;P11 = 0;P12 = 0;P13 = 0;EA = 1; //允许CPU中断TMOD = 0x11; //设定时器0和1为16位模式1ET0 = 1; //定时器0中断允许TH0 = 0xFc;TL0 = 0x18; //设定时每隔1ms中断一次TR0 = 1; //开始计数stop_flag = 0;turn=0;speedlevel = 20;while(1){key = keyscan();switch(key){case 0x09: //按键#,正转以speedlevel = 1的速度转1000*0.5MS=0.5Sstop_flag=0;turn = 0;speedlevel =10;gorun();delay(1000);break;case 0x0c: //按键*,停止2000*0.5MS=0.5Sstop_flag=1;break;case 0x0a: //按键0,反转以speedlevel = 1的速度转1000*0.5MS=0.5Sstop_flag=0;turn=1;speedlevel =10;gorun();delay(1000);break;case 0x11: // 按键9,以--speedlevel的加速转1000*0.5MS=0.5Sstop_flag=0;if (speedlevel==1){ speedlevel=1;}else { --speedlevel;}gorun();delay(1000);break;case 0x12: // 按键8,以++speedlevel的减速转1000*0.5MS=0.5Sstop_flag=0;++speedlevel;gorun();delay(1000);break;}}}//定时器0中断处理void timeint(void) interrupt 1{TH0=0xFc;TL0=0x18; //设定时每隔1ms中断一次count++;spcount--;if(spcount<=0) //速度调整,SPEEDLEVEL越大,延时越长(延时约为1MS*SPEEDLEVEL),{ // 频率越小,速度越慢spcount = speedlevel;gorun();}}void delay(unsigned int endcount)//延时函数,延时为endcount*0.5毫秒{count=0;do{}while(count<endcount);void gorun(){if (stop_flag==1) {P10 = 0;P11 = 0;P12 = 0;P13 = 0;return;}switch(step_index) {case 0: //0P10 = 1;P11 = 0;P12 = 0;P13 = 0;break;case 1: //0、1P10 = 1;P11 = 1;P12 = 0;P13 = 0;break;case 2: //1P10 = 0;P11 = 1;P12 = 0;P13 = 0;break;case 3: //1、2P10 = 0;P11 = 1;P12 = 1;P13 = 0;break;case 4: //2P10 = 0;P11 = 0;P12 = 1;P13 = 0;break;case 5: //2、3P10 = 0;P11 = 0;P12 = 1;P13 = 1;break;case 6: //3P10 = 0;P11 = 0;P12 = 0;P13 = 1;break;case 7: //3、0P10 = 1;P11 = 0;P12 = 0;P13 = 1;}if (turn==0) //正转{step_index++;if (step_index>7)step_index=0;}else{ //反转step_index--;if (step_index<0)step_index=7;}}步进电机(键盘控制可调速加显示)#include <reg51.h>#define uchar unsigned charstatic unsigned int count; //计数static int step_index; //步进索引数,值为0-7static bit turn; //步进电机转动方向static bit stop_flag; //步进电机停止标志static int speedlevel; //步进电机转速参数,数值越大速度越大,最小值为1,速度最慢static int spcount; //步进电机转速参数计数void ddelay(void); //键盘扫描延时函数void delay(unsigned int endcount); //延时函数,延时为endcount*1毫秒void gorun(); //步进电机控制步进函数void Delay400Ms(void);void LCMInit(void); //LCM初始化void WriteCommandLCM(unsigned char WCLCM,BuysC); //BuysC为0时忽略忙检测void DisplayOneChar(uchar X, uchar Y, uchar DData);void DisplayListChar(uchar X, uchar Y,uchar ListLength, uchar *DData,uchar n);sbit P10=P3^0 ; //电机端口定义sbit P11=P3^1 ;sbit P12=P3^2;sbit P13=P3^3 ;uchar code speed[]={ 0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30};uchar code stop[] = {"stop"};uchar code go[] = {"go:"};uchar code back[] = {"back:"};uchar code max[] = {"max:8"};void ddelay(void){uchar i;for (i=300;i>0;i--);}uchar keyscan(void){uchar scancode;uchar tmpcode;P1 = 0xf8; // 发全0行扫描码if ((P1&0xf8)!=0xf8) // 若有键按下{ddelay(); // 延时去抖动if ((P1&0xf8)!=0xf8) // 延时后再判断一次,去除抖动影响{scancode = 0xfe;while((scancode&0x08)!=0) // 逐行扫描{P1 = scancode; // 输出行扫描码if ((P1&0xf8)!=0xf8) // 本行有键按下{tmpcode = (P1&0xf8)|0x07;return((~scancode)+(~tmpcode)); // 返回特征字节码,为1的位即对应于行和列 }else scancode = (scancode<<1)|0x01; // 行扫描码左移一位}}}return(0); // 无键按下,返回值为0}void main(void){uchar key;count = 0;step_index = 0;spcount = 0;P10 = 0;P11 = 0;P12 = 0;P13 = 0;EA = 1; //允许CPU中断TMOD = 0x11; //设定时器0和1为16位模式1ET0 = 1; //定时器0中断允许TH0 = 0xFc;TL0 = 0x18; //设定时每隔1ms中断一次TR0 = 1; //开始计数P0=0XFF;P3 &=0XEF; //573片选LCMInit(); //LCM初始化Delay400Ms();stop_flag = 0;turn=0;speedlevel = 5;DisplayListChar(0,0,3,go,1); //每次扫描键盘显示更新一次uchar code go[] DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次while(1){key = keyscan();switch(key){case 0x09: //按键#,正转以speedlevel = 1的速度转1000*0.5MS=0.5S stop_flag=0;turn = 0;speedlevel =5;gorun();WriteCommandLCM(0x01,1);//显示清屏,DisplayListChar(0,0,3,go,0); //每次扫描键盘显示更新一次uchar code go[] DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次delay(1000);break;case 0x0c: //按键*,停止2000*0.5MS=0.5Sstop_flag=1;WriteCommandLCM(0x01,1);//显示清屏,DisplayListChar(0,0,4,stop,0); //每次扫描键盘显示更新一次break;case 0x0a: //按键0,反转以speedlevel = 1的速度转1000*0.5MS=0.5S stop_flag=0;turn=1;speedlevel =5;gorun();WriteCommandLCM(0x01,1);//显示清屏,DisplayListChar(0,0,5,back,0); //每次扫描键盘显示更新一次DisplayOneChar(0,1,0x35); //每次扫描键盘显示更新一次delay(1000);break;case 0x11: // 按键9,以--speedlevel的加速转1000*0.5MS=0.5Sstop_flag=0;if (speedlevel==2){ speedlevel=2;}else { speedlevel--;}gorun();if(speedlevel==2){ DisplayListChar(0,1,5,max,0);}else {DisplayOneChar(0,1, speed[speedlevel]);} //每次扫描键盘显示更新一次 delay(1000);break;case 0x12: // 按键8,以++speedlevel的减速转1000*0.5MS=0.5Sstop_flag=0;speedlevel++;gorun();WriteCommandLCM(0x01,1);//显示清屏,if(turn==0){DisplayListChar(0,0,3,go,0); //每次扫描键盘显示更新一次uchar code go[] DisplayOneChar(0,1, speed[speedlevel]);} //每次扫描键盘显示更新一次else {DisplayListChar(0,0,5,back,0); //每次扫描键盘显示更新一次DisplayOneChar(0,1,speed[speedlevel]);} //每次扫描键盘显示更新一次delay(1000);break;}}}//定时器0中断处理void timeint(void) interrupt 1{TH0=0xFc;TL0=0x18; //设定时每隔1ms中断一次count++;spcount--;if(spcount<=0) //速度调整,SPEEDLEVEL越大,延时越长(延时约为1MS*SPEEDLEVEL),{ // 频率越小,速度越慢spcount = speedlevel;gorun();}}void delay(unsigned int endcount)//延时函数,延时为endcount*0.5毫秒{count=0;do{}while(count<endcount);}void gorun(){if (stop_flag==1){P10 = 0;P11 = 0;P12 = 0;P13 = 0;return;}switch(step_index){case 0: //0P10 = 1;P11 = 0;P12 = 0;P13 = 0;break;case 1: //0、1P10 = 1;P11 = 1;P12 = 0;P13 = 0;break;case 2: //1P10 = 0;P11 = 1;P12 = 0;P13 = 0;break;case 3: //1、2P10 = 0;P11 = 1;P12 = 1;P13 = 0;break;case 4: //2P10 = 0;P11 = 0;P12 = 1;P13 = 0;break;case 5: //2、3P10 = 0;P11 = 0;P12 = 1;P13 = 1;break;case 6: //3P10 = 0;P11 = 0;P12 = 0;P13 = 1;break;case 7: //3、0P10 = 1;P11 = 0;P12 = 0;P13 = 1;}if (turn==0) //正转 {step_index++;if (step_index>7)step_index=0; }else{ //反转step_index--;if (step_index<0)step_index=7;}}步进电机(自动循环调速)#include <reg51.h>sbit P00=P2^0 ;sbit P01=P2^1 ;sbit P02=P2^2;sbit P03=P2^3 ;static unsigned int count; //计数static int step_index; //步进索引数,值为0-7static bit turn; //步进电机转动方向static bit stop_flag; //步进电机停止标志static int speedlevel; //步进电机转速参数,数值越大速度越快,最小值为1,速度最慢static int spcount; //步进电机转速参数计数void delay(unsigned int endcount); //延时函数,延时为endcount*0.5毫秒void gorun(); //步进电机控制步进函数void main(void){count = 0;step_index = 0;spcount = 0;stop_flag = 0;P00 = 0;P01 = 0;P02 = 0;P03 = 0;EA = 1; //允许CPU中断TMOD = 0x11; //设定时器0和1为16位模式1ET0 = 1; //定时器0中断允许TH0 = 0xFE;TL0 = 0x0C; //设定时每隔0.5ms中断一次TR0 = 1; //开始计数turn = 0;do{speedlevel =4;delay(10000); //以speedlevel = 4的速度转2000*0.5MS=1Sspeedlevel =4;delay(10000); //以speedlevel = 4的速度转2000*0.5MS=1Sstop_flag=1;delay(6000);//停止,2000*0.5MS=3Sstop_flag=0;}while(1);}//定时器0中断处理void timeint(void) interrupt 1{TH0=0xFE;TL0=0x0C; //设定时每隔0.5ms中断一次count++;spcount--;if(spcount<=0){spcount = speedlevel;gorun();}}void delay(unsigned int endcount){count=0;do{}while(count<endcount);}void gorun(){if (stop_flag==1){P00 = 0;P01 = 0;P02 = 0;P03 = 0;return;}switch(step_index){case 0: //0P00 = 1;P01 = 0;P02 = 0;P03 = 0;break;case 1: //0、1P00 = 1;P01 = 1;P02 = 0;P03 = 0; break;case 2: //1P00 = 0;P01 = 1;P02 = 0;P03 = 0; break;case 3: //1、2P00 = 0;P01 = 1;P02 = 1;P03 = 0; break;case 4: //2P00 = 0;P01 = 0;P02 = 1;P03 = 0; break;case 5: //2、3P00 = 0;P01 = 0;P02 = 1;P03 = 1; break;case 6: //3P00 = 0;P01 = 0;P02 = 0;P03 = 1; break;case 7: //3、0P00 = 1;P01 = 0;P02 = 0;P03 = 1;}if (turn==0){step_index++;if (step_index>7) step_index=0; }else{step_index--;if (step_index<0)step_index=7;}}步进电机控制Link - Thu, 17 Jan 2008 12:41:32 +0800Description:本设计采用的步进电机为35BYJ46型四相八拍电机,电压为DC12V。
C 语言实现单片机控制步进电机加减速源程序1. 引言在现代工业控制系统中,步进电机作为一种常见的执行元件,广泛应用于各种自动化设备中。
而作为一种常见的嵌入式软件开发语言,C 语言在单片机控制步进电机的加减速过程中具有重要的作用。
本文将从单片机控制步进电机的加减速原理入手,结合 C 语言的编程技巧,介绍如何实现单片机控制步进电机的加减速源程序。
2. 单片机控制步进电机的加减速原理步进电机是一种能够精确控制角度的电机,它通过控制每个步骤的脉冲数来实现旋转。
在单片机控制步进电机的加减速过程中,需要考虑步进电机的加速阶段、匀速阶段和减速阶段。
在加速阶段,需要逐渐增加脉冲的频率,使步进电机的转速逐渐增加;在匀速阶段,需要保持恒定的脉冲频率,使步进电机以匀速旋转;在减速阶段,需要逐渐减小脉冲的频率,使步进电机的转速逐渐减小。
这一过程需要通过单片机的定时器和输出控制来实现。
3. C 语言实现步进电机加减速的源程序在 C 语言中,可以通过操作单片机的 GPIO 来控制步进电机的旋转。
在编写源程序时,需要使用单片机的定时器模块来生成脉冲信号,以控制步进电机的旋转角度和速度。
以下是一个简单的 C 语言源程序,用于实现步进电机的加减速控制:```c#include <reg52.h>void main() {// 初始化定时器// 设置脉冲频率,控制步进电机的加减速过程// 控制步进电机的方向// 控制步进电机的启停}```4. 总结与回顾通过本文的介绍,我们了解了单片机控制步进电机的加减速原理和 C 语言实现步进电机加减速源程序的基本思路。
掌握这些知识之后,我们可以更灵活地应用在实际的嵌入式系统开发中。
在实际项目中,我们还可以根据具体的步进电机型号和控制要求,进一步优化 C 语言源程序,实现更加精准和稳定的步进电机控制。
希望本文能为读者在单片机控制步进电机方面的学习和应用提供一定的帮助。
5. 个人观点与理解在我看来,掌握 C 语言实现单片机控制步进电机加减速源程序的技术是非常重要的。
步进电机控制(单⽚机C语⾔)模块⼆简单应⽤实例调试任务2 步进电机控制(H22)⼀、任务要求⽤单⽚机P1端⼝控制步进电机,编写程序输出脉冲序列到P1⼝,控制步进电机正转、反转,加速,减速。
⼆、任务⽬的1.了解步进电机控制的基本原理。
2.掌握控制步进电机转动的编程⽅法。
三、电路连线框图步进电机电流⼩于0.5A时可采⽤ULN2003A进⾏驱动(反相)四、原理控制说明步进电机驱动原理是通过对每相线圈中的电流的顺序切换来使电机作步进式旋转。
切换是通过单⽚机输出脉冲信号来实现的。
所以调节脉冲信号的频率便可以改变步进电机的转速,改变各相脉冲的先后顺序,可以改变电机的旋转⽅向。
步进电机的转速应由慢到快逐步加速。
电机驱动⽅式可以采⽤双四拍(AB→BC→CD→DA→AB)⽅式,也可以采⽤单四拍(A→B→C→D→A)⽅式,或单、双⼋拍(A→AB→B→BC→C→CD→D→DA→A)⽅式。
控制时公共端是接在VCC上的,所以实际控制脉冲是低电平有效。
单⽚机的P1⼝输出的脉冲信号经(MC1413或ULN2003A)倒相驱动后,向步进电机输出脉冲信号序列。
五、程序框图# include#define Astep 0x01#define Bstep 0x02#define Cstep 0x04#define Dstep 0x08unsigned char dly_c;void delay(){unsigned char tt,cc;cc = dly_c; //外循环次数tt = 0x0; //内循环次数do{do {}while(--tt);}while(--cc);}void main(){dly_c = 0x10;// 双四拍⼯作⽅式while(1){P1= Astep+Bstep;delay();P1= Bstep+Cstep;delay();P1= Cstep+Dstep;delay();P1= Dstep+Astep;delay();if (dly_c>3) dly_c --; // 加速控制};。
PID控制步进电机转速仿真及c程序#include<reg52.h>#include"lcd1602.h"sfr T2MOD = 0x0c9;#define uchar unsigned char#define uint unsigned intsbit Q0 = P2^4;sbit Q1 = P2^5;sbit Q2 = P2^6;sbit Q3 = P2^7;sbit PWM= P1^7;sbit UP= P1^0;sbit DOWM= P1^1;sbit GORB= P2^3; //换相sbit ADDSPEED = P1^2;sbit SUBSPEED= P1^3;uint tuint = 65535;uint tpwm = 1;//pwm周期为10000us tpwm变量表示pwm高电平时间,也相当于占空比(仿真时,频率高时,电机反应慢。
在实物上要加大频率)uchar t1_flag = 0;uint pulse = 0;uint t0_flag = 0;uchar t2_flag = 0;bit t2_over = 0;bit Just_Get = 1;#define ZZ { Q0 = 0;Q1 = 0;Q2 = 1;Q3 = 1;}//正转#define FZ { Q0 = 1;Q1 = 1;Q2 = 0;Q3 = 0;}//反转#define STOP{ Q0 = 1;Q1 = 0;Q2 = 1;Q3 = 0;}//停止//禁止出现Q0 = 0;Q1 = 1;Q2 = 0;Q3 = 1; 不然会烧掉mos管//************************ PID ************************************* float now = 0,bef = 0,bbef = 0; //本次采样值,上次采样值,上上次采样值float err_now,err_bef,err_bbef;//当前偏差,上次偏差,上上次偏差float error_add = 0;//所有偏差之和float set = 25;//设定值float kp = 25;float ki = 25;float kd = 0;//*****************************************************************void delayms(uint ms)//延时?个ms{uchar a,b,c;while(ms--){for(c=1;c>0;c--)for(b=142;b>0;b--)for(a=2;a>0;a--);}}void timer_init(){EA = 1;ET0 = 1;ET1 = 1;ET2 = 1;TMOD = 0x15; //定时器0 计数模式定时器1模式1T2MOD = 0x01;TH0 = TL0 = 255;TH2 = 0x3C;TL2 = 0xB0;//50MS}void timer1() interrupt 3{if(t1_flag == 0){t1_flag = 1;PWM = 1;TH1 = (tuint - tpwm + 1)/256;TL1 = (tuint - tpwm + 1)%256;}else{t1_flag = 0;PWM = 0;TH1 = (tuint - 10000 + tpwm + 1)/256;TL1 = (tuint - 10000 + tpwm + 1)%256;}}void timer0() interrupt 1{TH0 = TL0 = 255;t0_flag++;}void timer2() interrupt 5{TF2 = 0;TH2 = 0x3C;TL2 = 0xB0;//50MSt2_flag++;if(t2_flag == 2){TR0 = 0;TR2 = 0;t2_flag = 0;t2_over = 1;//表示100ms时间到}}void GetPulse(){t0_flag = 0;t2_flag = 0;TH0 = TL0 = 255;TH2 = 0x3C;TL2 = 0xB0;//50MSTR0 = 1;TR2 = 1;}int PID()//增量式PID{int change;err_now = set - now;err_bef = set - bef;err_bbef = set - bbef;change = kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);/*if(set >= now){if(set - now > 1)change = kp*(err_now -err_bef) + ki*err_now + kd*(err_now -2*err_bef + err_bbef);elsechange = 0.2*kp*(err_now - err_bef) + 0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);}else if(now > set){if(now - set > 1)change = kp*(err_now -err_bef) + ki*err_now + kd*(err_now -2*err_bef + err_bbef);elsechange = 0.2*kp*(err_now - err_bef) + 0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);}*///change = (kp + ki + kd)*(set - now) + (-kp - 2*kd)*(set - bef) + kd*(set - bbef);//change = kp*(set - now) + ki*(set - bef) + kd*(set - bbef);if(change > 0){printchar(1,10,'+');printuint(1,11,4,change);}else if(change < 0){printchar(1,10,'-');printuint(1,11,4,-change);}else if(change == 0){printchar(1,10,' ');printword(1,11," 0 ");}return(change);}int PID2()//位置式PID{int num = 0;static num_bef = 0;err_now = set - now;err_bef = set - bef;error_add = error_add + err_now; //误差累加。
独立按键控制步进电机运转C语言程序/** 名称:步进电机** 晶振:12MHZ ** 修改:无** 内容:主程序中用3个按键,加速、减速、启动和停止。
定时器做数码** 管动态扫描和步进电机驱动。
* ** 硬件事项:J19的7B,6B,5B,4B依次用杜邦线连接到P27,P26,P25,P24 ** *---------------------------------------------------------------*/ #include#define DataPort P1 //定义数据端口程序中遇到DataPort 则用P1 替换sbit LATCH1=P2^0;//定义锁存使能端口段锁存sbit LATCH2=P2^1;// 位锁存sbit S17=P3^3; //独立按键sbit S18=P3^2;sbit S19=P3^1;sbit S20=P3^0;unsigned char code HEY AO_DuanMa[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80 ,0x90};// 显示段码值0123456789unsigned char code HEYAO_WeiMa[]={0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};//分别对应相应的数码管点亮,即位码unsigned charTempData[8]={0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF}; //存储显示值的全局变量sbit A1=P2^7; //定义步进电机连接端口sbit B1=P2^6;sbit C1=P2^5;sbit D1=P2^4;#define Coil_AB1 {A1=1;B1=1;C1=0;D1=0;}//AB相通电,其他相断电#define Coil_BC1 {A1=0;B1=1;C1=1;D1=0;}//BC相通电,其他相断电#define Coil_CD1 {A1=0;B1=0;C1=1;D1=1;}//CD相通电,其他相断电#define Coil_DA1 {A1=1;B1=0;C1=0;D1=1;}//D相通电,其他相断电#define Coil_A1 {A1=1;B1=0;C1=0;D1=0;}//A相通电,其他相断电#define Coil_B1 {A1=0;B1=1;C1=0;D1=0;}//B相通电,其他相断电#define Coil_C1 {A1=0;B1=0;C1=1;D1=0;}//C相通电,其他相断电#define Coil_D1 {A1=0;B1=0;C1=0;D1=1;}//D相通电,其他相断电#define Coil_OFF {A1=0;B1=0;C1=0;D1=0;}//全部断电unsigned char Speed;bit StopFlag;bit Flag,sb;void Display(unsigned char FirstBit,unsigned char Num);void Init_Timer0(void);unsigned char KeyScan(void);//键盘扫描/*------------------------------------------------uS延时函数,含有输入参数unsigned char t,无返回值unsigned char 是定义无符号字符变量,其值的范围是0~255 这里使用晶振12M,大致延时长度如下T=tx2+5 uS------------------------------------------------*/ void DelayUs2x(unsigned char t){while(--t);}void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}/*------------------------------------------------ 主函数------------------------------------------------*/ main(){unsigned int j,i;//旋转一周时间unsigned char num;Init_Timer0();while(1) //正向{ Coil_OFFnum=KeyScan(); //循环调用按键扫描if(num==1)//第一个按键,速度等级增加{if(Speed<18)Speed++;}else if(num==2)//第二个按键,速度等级减小{if(Speed>1)Speed--;}else if(num==3)//第三个按键,电机停止和启动{switch(j){case 0:Coil_OFFStopFlag=1;j++;break;case 1: StopFlag=0;j--;break;}}else if(num==4){ sb=1;while((1)&&(sb)){Flag=1;i=50;while((i--)&&(Flag)) //正向{Coil_A1DelayMs(Speed);Coil_AB1 //遇到Coil_AB1 用{A1=1;B1=1;C1=0;D1=0;}代替DelayMs(Speed); //改变这个参数可以调整电机转速,//数字越小,转速越大,力矩越小Coil_B1DelayMs(Speed);Coil_BC1DelayMs(Speed);Coil_C1DelayMs(Speed);Coil_CD1DelayMs(Speed);Coil_D1DelayMs(Speed);Coil_DA1DelayMs(Speed);num=KeyScan();if(num==3)//第三个按键,电机停止和启动{Flag=0; sb=0;}}Coil_OFFi=50;while((i--)&&(Flag))//反?{ // num=KeyScan();Coil_A1DelayMs(Speed);Coil_DA1 //遇到Coil_AB1 用{A1=1;B1=1;C1=0;D1=0;}代替DelayMs(Speed); //改变这个参数可以调整电机转速,//数字越小,转速越大,力矩越小Coil_D1DelayMs(Speed);Coil_CD1DelayMs(Speed);Coil_C1DelayMs(Speed);Coil_BC1DelayMs(Speed);Coil_B1DelayMs(Speed);Coil_AB1DelayMs(Speed);num=KeyScan();if(num==3)//第三个按键,电机停止和启动{Flag=0; sb=0;}}TempData[0]=HEY AO_DuanMa[Speed/10];TempData[1]=HEYAO_DuanMa[Speed%10];}}//分解显示信息,如要显示68,则68/10=6 68%10=8TempData[0]=HEY AO_DuanMa[Speed/10];TempData[1]=HEY AO_DuanMa[Speed%10];}}/*------------------------------------------------显示函数,用于动态扫描数码管输入参数FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示如输入0表示从第一个显示。