完整的单片机控制步进电机程序
89C51单片机对步进电动机的C语言控制程序

89C51单片机对步进电动机的控制程序啊?兄弟做的如何了?我也是不懂啊,真是有点同病相怜了这个程序是课程设计的,现在老师要复杂点的,不让用延时程序了,因为浪费CPU时间,改为定时器扫描防抖,还有显示是用四个数码管,用四个键控制,其中一个起停,一个正反转,两个加减速。
我只能写到这些了,你有何进展,交流一下吧#define uchar unsigned char //定义一下方便使用#define uint unsigned int#define ulong unsigned long#include <reg52.h> //包括一个52标准内核的头文件sbit P10 = P1^0; //头文件中没有定义的IO就要自己来定义了sbit P11 = P1^1;sbit P12 = P1^2;sbit P13 = P1^3;sbit K1 = P3^2;sbit K2 = P3^5;sbit K3 = P3^6;sbit K4 = P3^7;sbit P20=P2^0;sbit P21=P2^1;bit ldelay=0; //长定时溢出标记,预置是0uchar a,m=50;uchar result;uint b,n;uint i,j;char code dx516[3] _at_ 0x003b;//这是为了仿真设置的/*********************************************************************** ***********///电机正转void zheng_z(){ uchar code ledp1[8]={0xfe,0xfc,0xfd,0xf9,0xfb,0xf3,0xf7,0xf6};//预定的写入P1的值正转uchar ledi1; //用来指示正转显示顺序P1=ledp1[ledi1];//读出一个值送到P1口ledi1++;//指向下一个if(ledi1==8)ledi1=0; //到了最后一个灯就换到第一个}//电机反转void fan_z(){ uchar code ledp2[8]={0xf6,0xf7,0xf3,0xfb,0xf9,0xfd,0xfc,0xfe};//预定的写入P1的值反转uchar ledi2; //用来指示反转显示顺序P1=ledp2[ledi2];//读出一个值送到P1口ledi2++; //指向下一个if(ledi2==8)ledi2=0; //到了最后一个灯就换到第一个}//减速void jian_s(){m+=5;if(m>=50)m=50;}//加速void jia_su(){ m-=5;if(m<=10)m=10;}/*******************************************************************/ void delay(uint j){j=100;for(i=0;i<j;i++){;}}void display(uint x){switch(x){case 0: P0=0xC0;break;case 1: P0=0xF9;break;case 2: P0=0xA4;break;case 3: P0=0xB0;break;case 4: P0=0x99;break;case 5: P0=0x92;break;case 6: P0=0x82;break;case 7: P0=0xF8;break;case 8: P0=0x80;break;case 9: P0=0x90;break;}}void sudu(uint c){switch(c){case 50: result=15;break;case 45: result=17;break;case 40: result=19;break;case 35: result=21;break;case 30: result=25;break;case 25: result=30;break;case 20: result=38;break;case 15: result=50;break;case 10: result=75;break;}}/*******************************************************************/ //主程序void main(void){TMOD = 0x01; //设定时器0为16位模式TH0 =0xdb; //赋T0的预置值0xdbTL0 =0xff;TR0=1; //启动定时器ET0=1; //打开定时器0中断EA=1; //打开总中断while(1) //主程扫描各键值{if(ldelay) //发现有时间溢出标记,进入处理{ldelay=0; //清除标记zheng_z();if(!K3)a=1; //如果读到K3为0if(!K4)a=0; //如果读到K4为0if(a==1)zheng_z();elsefan_z();if(!K1) //如果读到K1为0jian_s(); //减速if(!K2) //如果读到K2为0jia_su(); //加速/*********************************************************************** ************/sudu(m);b=result/10;n=result%10;P20=1;P21=0;display(b);delay (2);P20=~P20;P21=~P21;display(n);delay (2);}}}//定时器0中断timer0() interrupt 1{static uchar t;TH0 =0xdb; //赋T0的预置值0xdbTL0 =0xff;//TF0=0;t++;if(t==m){ t=0;ldelay=1;}}//定时器1中断/*timer1() interrupt 3{static uchar t;TF0=0;t++;if(t==20) { t=0; ldelay=1; } }*/。
基于单片机的步进电机控制

基于单片机的步进电机控制步进电机是一种常用的电动执行元件,在许多领域中都有广泛的应用。
为了实现对步进电机的精确控制,通常使用单片机来实现控制算法。
本文将介绍一个基于单片机的步进电机控制方案,并详细说明其实现过程和步骤。
首先,需要明确步进电机的工作原理。
步进电机通过控制电流的方向和大小来实现精确的旋转控制。
通常,步进电机由若干个驱动器组成,每个驱动器控制一个电机相位。
单片机通过控制驱动器的状态来控制步进电机的旋转。
1.硬件设计和搭建首先,需要根据步进电机的特性选择合适的单片机和驱动器。
单片机的选择应考虑其计算能力、IO口数量和通信接口等因素。
驱动器的选择应考虑其控制精度、最大电流和保护功能等因素。
然后,根据步进电机的型号和参数,设计并搭建电路板。
在电路板上,需要连接单片机、驱动器和步进电机,以及相应的电源和信号线。
2.控制算法设计在单片机中,需要设计控制算法来实现步进电机的精确控制。
常用的控制算法有定位控制、速度控制和加速度控制等。
根据实际需求,选择合适的控制算法,并编程实现。
3.编程实现根据控制算法的设计,使用合适的编程语言(如C语言或汇编语言)编写程序。
程序应包括步进电机的初始化代码、控制算法的实现代码和中断服务程序等。
在程序中,需要通过单片机的IO口控制驱动器,以改变驱动器的状态,从而控制步进电机的旋转方向和速度。
同时,还需要通过测量步进电机的位置和速度来实现闭环控制。
4.调试和优化完成编程后,需要进行调试和优化,以保证步进电机的控制精度和可靠性。
可通过调整控制算法的参数、增加传感器和使用滤波算法等方式来提高步进电机控制的性能。
综上所述,本文介绍了一个基于单片机的步进电机控制方案。
通过硬件设计和搭建、控制算法设计、编程实现和调试优化等步骤,可以实现对步进电机的精确控制。
这种方案在工业自动化、仪器仪表和机器人等领域具有广泛的应用价值。
c语言实现单片机控制步进电机加减速源程序

C 语言实现单片机控制步进电机加减速源程序1. 引言在现代工业控制系统中,步进电机作为一种常见的执行元件,广泛应用于各种自动化设备中。
而作为一种常见的嵌入式软件开发语言,C 语言在单片机控制步进电机的加减速过程中具有重要的作用。
本文将从单片机控制步进电机的加减速原理入手,结合 C 语言的编程技巧,介绍如何实现单片机控制步进电机的加减速源程序。
2. 单片机控制步进电机的加减速原理步进电机是一种能够精确控制角度的电机,它通过控制每个步骤的脉冲数来实现旋转。
在单片机控制步进电机的加减速过程中,需要考虑步进电机的加速阶段、匀速阶段和减速阶段。
在加速阶段,需要逐渐增加脉冲的频率,使步进电机的转速逐渐增加;在匀速阶段,需要保持恒定的脉冲频率,使步进电机以匀速旋转;在减速阶段,需要逐渐减小脉冲的频率,使步进电机的转速逐渐减小。
这一过程需要通过单片机的定时器和输出控制来实现。
3. C 语言实现步进电机加减速的源程序在 C 语言中,可以通过操作单片机的 GPIO 来控制步进电机的旋转。
在编写源程序时,需要使用单片机的定时器模块来生成脉冲信号,以控制步进电机的旋转角度和速度。
以下是一个简单的 C 语言源程序,用于实现步进电机的加减速控制:```c#include <reg52.h>void main() {// 初始化定时器// 设置脉冲频率,控制步进电机的加减速过程// 控制步进电机的方向// 控制步进电机的启停}```4. 总结与回顾通过本文的介绍,我们了解了单片机控制步进电机的加减速原理和 C 语言实现步进电机加减速源程序的基本思路。
掌握这些知识之后,我们可以更灵活地应用在实际的嵌入式系统开发中。
在实际项目中,我们还可以根据具体的步进电机型号和控制要求,进一步优化 C 语言源程序,实现更加精准和稳定的步进电机控制。
希望本文能为读者在单片机控制步进电机方面的学习和应用提供一定的帮助。
5. 个人观点与理解在我看来,掌握 C 语言实现单片机控制步进电机加减速源程序的技术是非常重要的。
单片机驱动步进电机程序代码

/********************************************************实现功能:正转程序使用芯片:A T89S52编译环境:Keil作者:【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!********************************************************/ #include<reg52.h> //库文件#define uchar unsigned char //字符型宏定义#define uint unsigned int //整型宏定义uchar tcnt; //定时器计数初值定义uint sec; //速度值定义uchar buf[11];uchar bai,shi,ge;/********************控制位定义*************************/sbit shi_neng=P1^0; // 使能控制位sbit fang_shi=P1^1; // 工作方式控制位sbit fang_xiang=P1^2;// 旋转方向控制位sbit mai_chong=P1^3; // 脉冲控制位/********************延时函数***************************/void delay1ms(uchar z){uchar x,y;for(x=0;x<z;x++)for(y=0;y<110;y++);}/***************************定时中断服务函数*************/void t0(void) interrupt 1 using 0 //定时中断服务函数{tcnt++; //每过250ust tcnt 加一if(tcnt==1) //当tcnt满足条件时{tcnt=0; //计满重新再计sec++;if(sec==6) //括号内数值越小,电机转动速度越快{sec=0; //计满重新再计mai_chong=~mai_chong; //脉冲输出}}}/***********************定时器0/1初始化****************************/void T0_Init(){ET0 = 1;TMOD = 0x22;TH0=0x06; //对TH0 TL0 赋值TL0=0x06;TR0=1; //开始定时sec=0;mai_chong=1; // 脉冲控制位}/***********************串口初始化****************************/void Uart_Init(){TMOD = 0x22;TH1 = 0xFD;TL1 = 0xFD;SCON = 0x50;PCON &= 0xef;TR1 = 1;}/***********************数据接收函数****************************/void ReceiveBuf(){int i;for(i=0;i<11;i++){buf[i] = SBUF;while(RI == 0);RI=0;}}/***********************角度控制函数****************************/void Control(){if((bai==buf[5])&(shi==buf[6])&(ge==buf[7])){shi_neng=0;};if(bai<buf[5]){shi_neng=1;fang_xiang=0;}else if(bai>buf[5]){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&shi<buf[6]){shi_neng=1;fang_xiang=0;}else if((bai==buf[5]&shi>buf[6])){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&(shi==buf[6]&(ge<buf[7]))){shi_neng=1;fang_xiang=0;}else if((bai==buf[5])&(shi==buf[6])&(ge>buf[7])) {shi_neng=1;fang_xiang=1;};if((bai==buf[5])&(shi==buf[6])&(ge==buf[7])){shi_neng=0;};delay1ms(3);bai=buf[5];shi=buf[6];ge=buf[7];}/************************主函数****************************/main(){EA=1;T0_Init();Uart_Init();while(1){// shi_neng=1; // 使能控制位fang_shi=1; // 工作方式控制ReceiveBuf();delay1ms(1);Control();delay1ms(10);}}/*************************结束******************************/。
步进电机的 单片机控制方法

步进电机的单片机控制方法
步进电机的单片机控制方法包括以下步骤:
1. 选择合适的单片机,并设置相应的电源。
一般情况下,步进电机的最大值电流可以通过单片机的脉冲输出控制。
2. 根据步进电机的特性进行旋转方向的控制。
3. 设计一个脉冲计数器,用于确定步进电机的旋转角度。
根据中断函数的触发,可以在固定的时间间隔内输出脉冲信号,从而实现步进电机的控制。
4. 根据应用需求设计相应的算法,实现步进电机的速度和位置控制。
例如,可以使用PID控制算法等。
5. 在控制程序完成后,进行电路布局和调试。
总之,步进电机的单片机控制方法需要根据具体的应用需求进行设计,同时还需要注意控制精度和延时等因素。
步进电机控制程序(c语言51单片机)

// pri_dj = Pme );
if( i == set_pwm_width ) { P1 = 0xff; i = 0; one _round_flg = 0; while ( !one_round_flg & key_puse );}
if(!key_puse) { delay(4ms); if(!key_puse) break; }
while ( key_puse & key_clear ); delay ( 8ms );
if ( !key_clear ) { round_num = 0; display(); }
if ( !key_puse ) break; }
while( !key_puse ); delay(8ms);
while( !key_puse ); }
set_display_num(); for(i = 0; i < LEDLen ; i ++){
P0 = 0xf0; P0 = P0 | LEDBuf[i] ; if(i==0) led_1000 = 0; //P0^4 if(i==1) led_100 = 0; //P0^5 if(i==2) led_10 = 0; //P0^6 if(i==3) led_1 = 0; //P0^7
delay ( 1ms ); tmp = (~(P2 | 0xF0)); P2 = 0x7F; // 0111 1111
delay ( 1ms ); tmp = (~(P2 | 0xF0)) * 10 + tmp; set_round_num = set_round_num + tmp * 100; set_round_num = set_round_num * Chilun_Num;
单片机控制步进电机转动程序设计_概述及说明

单片机控制步进电机转动程序设计概述及说明1. 引言1.1 概述在现代工业和科技领域中,步进电机常被用于各种自动化设备和精密控制系统中。
步进电机以其精准的定位和可控性而被广泛应用于数控机床、印刷设备、医疗仪器等领域。
单片机是一种高度集成的微处理器,具有强大的计算能力和丰富的外设接口,可以为步进电机提供有效的控制信号和驱动能力。
本文将介绍单片机对步进电机转动程序设计的概念、原理和实现过程,并进行相关实验与结果分析。
通过深入了解单片机与步进电机之间的关系,我们可以更好地理解并合理设计步进电机转动程序,提高整个系统的稳定性和效率。
1.2 文章结构本文分为五个主要部分。
引言部分旨在说明文章背景、目的及结构安排,从而使读者对文章内容有清晰的认识。
接下来将介绍单片机控制步进电机转动程序设计的相关概念、原理和要点,并详细描述硬件准备与连接配置。
然后,将着重阐述步进电机驱动程序的设计与编码实现过程。
随后,将介绍转动程序的测试方法和优化技巧。
最后,通过实验数据的分析和讨论,总结结论并展望未来针对问题的研究方向及相关工程应用前景。
1.3 目的本文的目的是探讨单片机控制步进电机转动程序设计的相关要点,并提供具体的硬件连接配置、驱动程序设计和优化方法。
通过阅读本文,读者将能够了解并应用单片机在步进电机控制中的原理和技巧,从而实现更加精确和可靠的步进电机转动控制。
同时,本文还旨在为有关领域研究者提供有关步进电机转动程序设计的参考资料,并预测其未来在工程应用中可能展示出来的前景及意义。
2. 单片机控制步进电机转动程序设计:2.1 步进电机概述:步进电机是一种将电动机转换为角位移输出的装置。
与直流电机不同,步进电机可以精确地控制角度和位置。
它由多个绕组(相)构成,每个绕组都被称为一个相位。
通过在不同的相之间交替通电,可以使步进电机转动一个固定的角度。
2.2 单片机控制步进电机原理:单片机是一种微处理器芯片,它具有强大的计算和控制能力。
单片机驱动步进电机程序代码

单片机驱动步进电机程序代码(总4页)-CAL-FENGHAI.-(YICAI)-Company One1-CAL-本页仅作为文档封面,使用请直接删除/********************************************************实现功能:正转程序使用芯片:AT89S52晶振:11.0592MHZ编译环境:Keil作者:【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!********************************************************/ #include<reg52.h> //库文件#define uchar unsigned char //字符型宏定义#define uint unsigned int //整型宏定义uchar tcnt; //定时器计数初值定义uint sec; //速度值定义uchar buf[11];uchar bai,shi,ge;/********************控制位定义*************************/sbit shi_neng=P1^0; // 使能控制位sbit fang_shi=P1^1; // 工作方式控制位sbit fang_xiang=P1^2;// 旋转方向控制位sbit mai_chong=P1^3; // 脉冲控制位/********************延时函数***************************/void delay1ms(uchar z){uchar x,y;for(x=0;x<z;x++)for(y=0;y<110;y++);}/***************************定时中断服务函数*************/void t0(void) interrupt 1 using 0 //定时中断服务函数{tcnt++; //每过250ust tcnt 加一if(tcnt==1) //当tcnt满足条件时{tcnt=0; //计满重新再计sec++;if(sec==6) //括号内数值越小,电机转动速度越快{sec=0; //计满重新再计mai_chong=~mai_chong; //脉冲输出}}}/***********************定时器0/1初始化****************************/void T0_Init(){ET0 = 1;TMOD = 0x22;TH0=0x06; //对TH0 TL0 赋值TL0=0x06;TR0=1; //开始定时sec=0;mai_chong=1; // 脉冲控制位}/***********************串口初始化****************************/void Uart_Init(){TMOD = 0x22;TH1 = 0xFD;TL1 = 0xFD;SCON = 0x50;PCON &= 0xef;TR1 = 1;}/***********************数据接收函数****************************/void ReceiveBuf(){int i;for(i=0;i<11;i++){buf[i] = SBUF;while(RI == 0);RI=0;}}/***********************角度控制函数****************************/ void Control(){if((bai==buf[5])&(shi==buf[6])&(ge==buf[7])){shi_neng=0;};if(bai<buf[5]){shi_neng=1;fang_xiang=0;}else if(bai>buf[5]){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&shi<buf[6]){shi_neng=1;fang_xiang=0;}else if((bai==buf[5]&shi>buf[6])){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&(shi==buf[6]&(ge<buf[7]))){shi_neng=1;fang_xiang=0;}else if((bai==buf[5])&(shi==buf[6])&(ge>buf[7])){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&(shi==buf[6])&(ge==buf[7])){shi_neng=0;};delay1ms(3);bai=buf[5];shi=buf[6];ge=buf[7];}/************************主函数****************************/main(){EA=1;T0_Init();Uart_Init();while(1){// shi_neng=1; // 使能控制位fang_shi=1; // 工作方式控制ReceiveBuf();delay1ms(1);Control();delay1ms(10);}}/*************************结束******************************/。
单片机驱动步进电机程序代码

单片机驱动步进电机程序代码(总4页)-CAL-FENGHAI.-(YICAI)-Company One1-CAL-本页仅作为文档封面,使用请直接删除/********************************************************实现功能:正转程序使用芯片:AT89S52晶振:11.0592MHZ编译环境:Keil作者:【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!********************************************************/ #include<reg52.h> //库文件#define uchar unsigned char //字符型宏定义#define uint unsigned int //整型宏定义uchar tcnt; //定时器计数初值定义uint sec; //速度值定义uchar buf[11];uchar bai,shi,ge;/********************控制位定义*************************/sbit shi_neng=P1^0; // 使能控制位sbit fang_shi=P1^1; // 工作方式控制位sbit fang_xiang=P1^2;// 旋转方向控制位sbit mai_chong=P1^3; // 脉冲控制位/********************延时函数***************************/void delay1ms(uchar z){uchar x,y;for(x=0;x<z;x++)for(y=0;y<110;y++);}/***************************定时中断服务函数*************/void t0(void) interrupt 1 using 0 //定时中断服务函数{tcnt++; //每过250ust tcnt 加一if(tcnt==1) //当tcnt满足条件时{tcnt=0; //计满重新再计sec++;if(sec==6) //括号内数值越小,电机转动速度越快{sec=0; //计满重新再计mai_chong=~mai_chong; //脉冲输出}}}/***********************定时器0/1初始化****************************/void T0_Init(){ET0 = 1;TMOD = 0x22;TH0=0x06; //对TH0 TL0 赋值TL0=0x06;TR0=1; //开始定时sec=0;mai_chong=1; // 脉冲控制位}/***********************串口初始化****************************/void Uart_Init(){TMOD = 0x22;TH1 = 0xFD;TL1 = 0xFD;SCON = 0x50;PCON &= 0xef;TR1 = 1;}/***********************数据接收函数****************************/void ReceiveBuf(){int i;for(i=0;i<11;i++){buf[i] = SBUF;while(RI == 0);RI=0;}}/***********************角度控制函数****************************/ void Control(){if((bai==buf[5])&(shi==buf[6])&(ge==buf[7])){shi_neng=0;};if(bai<buf[5]){shi_neng=1;fang_xiang=0;}else if(bai>buf[5]){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&shi<buf[6]){shi_neng=1;fang_xiang=0;}else if((bai==buf[5]&shi>buf[6])){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&(shi==buf[6]&(ge<buf[7]))){shi_neng=1;fang_xiang=0;}else if((bai==buf[5])&(shi==buf[6])&(ge>buf[7])){shi_neng=1;fang_xiang=1;};if((bai==buf[5])&(shi==buf[6])&(ge==buf[7])){shi_neng=0;};delay1ms(3);bai=buf[5];shi=buf[6];ge=buf[7];}/************************主函数****************************/main(){EA=1;T0_Init();Uart_Init();while(1){// shi_neng=1; // 使能控制位fang_shi=1; // 工作方式控制ReceiveBuf();delay1ms(1);Control();delay1ms(10);}}/*************************结束******************************/。
51单片机控制步进电机程序及硬件电路图

#include <AT89X51.h>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;P1_0 = 0;P1_1 = 0;P1_2 = 0;P1_3 = 0;EA = 1; //允许CPU中断TMOD = 0x11; //设定时器0和1为16位模式1 ET0 = 1; //定时器0中断允许TH0 = 0xFE;TL0 = 0x0C; //设定时每隔0.5ms中断一次TR0 = 1; //开始计数turn = 0;speedlevel = 2;delay(10000);speedlevel = 1;do{speedlevel = 2;delay(10000);speedlevel = 1;delay(10000);stop_flag=1;delay(10000);stop_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){P1_0 = 0;P1_1 = 0;P1_2 = 0;P1_3 = 0;return;}switch(step_index){case 0: //0P1_0 = 1;P1_1 = 0;P1_2 = 0;P1_3 = 0; break; case 1: //0、1 P1_0 = 1;P1_1 = 1;P1_2 = 0;P1_3 = 0; break; case 2: //1P1_0 = 0;P1_1 = 1;P1_2 = 0;P1_3 = 0; break; case 3: //1、2 P1_0 = 0;P1_1 = 1;P1_2 = 1;P1_3 = 0;break; case 4: //2 P1_0 = 0;P1_1 = 0;P1_2 = 1;P1_3 = 0; break; case 5: //2、3 P1_0 = 0;P1_1 = 0;P1_2 = 1;P1_3 = 1; break; case 6: //3P1_0 = 0;P1_1 = 0;P1_2 = 0;P1_3 = 1; break; case 7: //3、0 P1_0 = 1;P1_1 = 0;P1_2 = 0;P1_3 = 1;}if (turn==0){step_index++; if (step_index>7)step_index=0; }else{step_index--;if (step_index<0)step_index=7; }}。
51单片机控制的步进电机C语言程序

51单片机控制的步进电机C语言程序用的是L298驱动的和ULN2003一样,你把它换成2003就行拉#include <AT89X51.H>unsigned char codetable[]={0xf1,0xf3,0xf2,0xf6,0xf4,0xfc,0xf8,0xf9,0x00,0xf1,0xf9,0xf8,0xfc,0xf4,0xf6,0xf2,0x f3,0x00};unsigned char temp,temp_old;unsigned char key;unsigned char i,j,k,m,s;void delay(int i){for(m=i;m>0;m--)for(j=250;j>0;j--)for(k=10;k>0;k--);}void saomiao(){P3=0xff;P3_4=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0e:key=1;break;case 0x0d:key=2;break;case 0x0b:key=3;break;case 0x07:key=4;break;}temp=P3;temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_5=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}temp=P3;temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}}void main(void){while(1){saomiao();if(key==1){ P1=0;P2=0;saomiao();}if(key==2){temp_old=key;for(s=0;s<8;s++){ P2=table[s];P1_4=0;delay(13);saomiao();if(key!=temp_old){P1_4=1;break;}}}if(key==3){temp_old=key;for(s=0;s<8;s++){ P2=table[s];P1_5=0;delay(5);saomiao();if(key!=temp_old){P1_5=1;break;}}}if(key==4){temp_old=key; for(s=0;s<8;s++){ P2=table[s];P1_6=0;delay(20);saomiao();if(key!=temp_old){P1_6=1;break;}}}if(key==5){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_7=0;delay(13);saomiao();if(key!=temp_old){P1_7=1;break;}}}if(key==6){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_5=0;delay(5);saomiao();if(key!=temp_old){P1_5=1;break;}}}if(key==7){temp_old=key;for(s=9;s<17;s++){ P2=table[s];P1_6=0;delay(20);saomiao();if(key!=temp_old){P1_6=1;break;}}}}}C语言程序源代码#include <REGX51.H> // 51寄存器定义#include "intrins.h"#define control P1 //P1_0:A相,P1_1:B相,P1_2:C相,P1_3:D相#define discode P0 //显示代码控制端口#define uchar unsigned char //定义无符号型变量#define uint unsigned intsbit en_dm=P3^0; //显示代码锁存控制sbit en_wk=P3^1; //位控锁存控制uchar code corotation[4]= {0x03,0x06,0x0c,0x09};//电机正转uchar code rollback[4]={0x0c,0x06,0x03,0x09}; //电机反转uchar code tab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示字段uint code Levspeed[5]={500,400,300,200,100};//电机速度等级uchar Hscan,speedcount;//Hscan行扫描,speedcount 速度等级计数uint uu; //频率计数uint step,setstep; //step:电机步伐计数,setstep:手动设置电机步伐uint speed=500; //电机初始速度uchar count;uchar flag[5];uchar butcount; //按键次数//****************************************//flag[0] 正转标志//flag[1] 反转标志//flag[2] 加速标志//flag[3] 减速标志//flag[4] 设置标志//****************************************Delay1mS(unsigned int tt) //延时1ms “Delay1mS”延时子程序,用循环语句延时。
基于51单片机的步进电机小车的控制程序

voidmove_left(uintspeed_l,ucharcw,ucharen);//左电机运动函数
voidmove_right(uintspeed_r,ucharcw,ucharen);//右电机运动函数
void delay(unsignedintk);//延时函数
speed=speed_l;
if(cw==1)
{
cw_left=1;
}
else
{
cw_left=0;
}
if(en==1)
{
en_left=1;
}
else
{
en_left=0;
}
}
voidmove_right(uintspeed_r,ucharcw,ucharen)
{//speed_r速度控制变量cw方向控制变量en使能控制变量
speed=speed_r;//speed数值与速度成反比请结合实际情况进行调节,
if(cw==1)//但速度不能无限加快因为步进电机有速度上限
{//而且速度加快是力矩会下降,容易导致丢步现象
cw_right=1;//所以实际应用当中应调节到速度可力矩比较合适的数值
}//应考虑到电池电压,轮胎直径等因素
{
move_left(15,0,1);
move_right(15,0,1);
delay(800);
}
if(ir_left==0&&ir_mid==0&&ir_right==1)
{
move_left(15,0,1);
move_right(15,0,1);
delay(400);
msp430单片机控制步进电机实验的电路图及C程序

各模块的电路图如下:试验程序如下:#include <msp430x14x.h>#define DCO_FREQ 1000000 // DCO frequency#define ONE_SEC_CNT 512 // Number of WDT interrupts in 1 second#define DEBOUNCE_CNT 0x05 // (1/512)*5 = ~10 msec debounce#define DIR_MASK 0x01 // 0x01 is clockwise, 0x00 is counter-clockwise #define STEP_MASK 0x02 // 0x00 is full-stepping, 0x02 is half-stepping #define MOTION_MASK 0x04 // 0x00 is continuous, 0x04 is single-step#define DEFAULT_RA TE 0x8000 // Default stepping rate#define MIN_RATE 0x8000 // Minimum stepping rate#define MAX_RATE 0x0800 // Maximum stepping rate// Default state is full-stepping, clockwise, continuousunsigned char state = 1; // State variableunsigned char stepIndex = 0; // State table indexunsigned int rate = DEFAULT_RA TE; // Stepping rateunsigned char change_rate_flag = 0; // Flag indicating rate changeunsigned int max_rate = MAX_RA TE; // Maximum stepping rateunsigned int min_rate = MIN_RA TE; // Minimum stepping rate unsigned int SW[4];void sys_init(void);void Set_DCO(unsigned long freq);void timerA_Init(void);void uart0_Init(void);void wdt_Init(void);void toggle_stepping_mode(void);void increase_stepping_rate(void);void decrease_stepping_rate(void);void toggle_motion(void);void toggle_direction(void);//定义串口操作变量char nRev_UART0; // 串口0 的接收标志char UART0_TX_BUF[10]; // 串口0 的发送缓冲区char UART1_RX_Temp[10];char UART0_RX_BUF[10]; // 串口0 的接收缓冲区int nTX0_Len;int nRX0_Len;int nRX0_Len_temp;char nTX0_Flag;int nSend_TX0;// 整步状态表Astatic const unsigned char fullStepA[] ={0x00,0x00,0x01,0x01};// 半步状态表Bstatic const unsigned char fullStepB[] ={0x01,0x00,0x00,0x01};// 半步状态表Astatic const unsigned char HalfStepA[] = {0x01, // 001 10x06, // 110 20x00, // 000 30x00, // 000 40x00, // 000 50x07, // 111 60x01, // 001 70x01 // 001 8};// 逆时钟、半步状态表Bstatic const unsigned char CcwHalfStepB[] = {0x01, // 001 10x01, // 001 20x01, // 001 30x06, // 110 40x00, // 000 50x00, // 000 60x00, // 000 70x07 // 111 8};// 顺时钟、半步状态表Bstatic const unsigned char CwHalfStepB[] = {0x00, // 000 10x00, // 000 20x00, // 000 30x07, // 111 40x01, // 001 50x01, // 001 60x01, // 001 70x06 // 110 8};void main(void){int i;// 停止WDTWDTCTL = WDTPW + WDTHOLD;sys_init();_EINT();for(;;){if(nRev_UART0 == 1){nRev_UART0 = 0;for(i = 0;i < nRX0_Len;i++) UART1_RX_Temp[i] = UART0_RX_BUF[i];if((UART1_RX_Temp[0] == 'A') && (UART1_RX_Temp[1] == 'T')){UART0_TX_BUF[0] = 'O';UART0_TX_BUF[1] = 'K';UART0_TX_BUF[2] = 13;nTX0_Len = 3;switch(UART1_RX_Temp[2]){case 'D': // 方向toggle_direction();break;case 'C': // 运动模式toggle_motion();break;case 'M': // 步进模式toggle_stepping_mode();break;case 'F': // 增加速率increase_stepping_rate();break;case 'S': // 降低速率decrease_stepping_rate();break;default: break;}}else{UART0_TX_BUF[0] = 'E';UART0_TX_BUF[1] = 'R';UART0_TX_BUF[2] = 'O';UART0_TX_BUF[3] = 'R';UART0_TX_BUF[4] = 'R';UART0_TX_BUF[5] = 13;nTX0_Len = 6;}// 设置中断标志,进入发送中断程序IFG1 |= UTXIFG0;nRX0_Len = 0;}}}void sys_init(void){// 设置下降沿触发中断P1IES = 0x0f;P1IFG = 0x00;P1IE = 0x0f;// 设置P2.3,2,1,0 为输出// 设置P3.3,2,1,0 为输出P2OUT = 0x00;P3OUT = 0x00;P2DIR |= 0x0f;P3DIR |= 0x0f;// 设置DCOSet_DCO(DCO_FREQ);// 初始化Timer AtimerA_Init();// 初始化UART0uart0_Init();// 初始化WDTwdt_Init();}void Set_DCO(unsigned long freq){unsigned int clkCnt;unsigned int numDcoClks;unsigned int prevCnt = 0;// ACLK = LFXT1CLK/8 = 4096 HzBCSCTL1 |= DIV A_3;numDcoClks = freq/4096;TACCTL2 = CM_1 + CCIS_1 + CAP; TACTL = TASSEL_2 + MC_2 + TACLR; while(1){while( !(TACCTL2 & CCIFG) ){}TACCTL2 &= ~CCIFG;clkCnt = TACCR2 - prevCnt;prevCnt = TACCR2;if( numDcoClks == clkCnt ){break;}else if( clkCnt > numDcoClks ){DCOCTL--;if( DCOCTL == 0xFF ){if( BCSCTL1 & 0x07 ){BCSCTL1--;}else{break;}}}else{DCOCTL++;if( DCOCTL == 0x00 ){if( (BCSCTL1 & 0x07) != 0x07 ){BCSCTL1++;}else{break;}}}}// ACLK = LFXT1CLK/1 = 32768 HzBCSCTL1 &= ~DIV A_3;TACCTL2 = 0;TACTL = 0;}void wdt_Init(void){// 设置时钟源为ACLK,1秒内产生512此WDTCTL = WDTPW + WDTTMSEL + WDTCNTCL + WDTSSEL + WDTIS0 + WDTIS1; }void uart0_Init(void){//将寄存器的内容清零U0CTL = 0X00;//数据位为8bitU0CTL += CHAR;U0TCTL = 0X00;//波特率发生器选择ACLKU0TCTL += SSEL0;//波特率为9600UBR0_0 = 0X03;UBR1_0 = 0X00;UMCTL_0 = 0x4A;//使能UART0的TXD和RXDME1 |= UTXE0 + URXE0;//使能UART0的RX中断IE1 |= URXIE0;//使能UART0的TX中断IE1 |= UTXIE0;//设置P3.4为UART0的TXDP3SEL |= BIT4;//设置P3.5为UART0的RXDP3SEL |= BIT5;//P3.4为输出管脚P3DIR |= BIT4;}void timerA_Init(void){TACCR0 = rate;TACCTL0 = CCIE;TACTL = TASSEL_2 + MC_1 + TACLR;}interrupt [TIMERA0_VECTOR] void TimerA_ISR(void) {unsigned char index;unsigned char p2 = 0;unsigned char p3 = 0;// 判断步进速率是否需要改变if( change_rate_flag ){TACCR0 = rate;change_rate_flag = 0;}// 判断状态switch( (state & 0x3) ){case 0x00: // 整步、逆时钟方向index = stepIndex & 0x03;p2 |= fullStepA[index];p3 |= fullStepB[index];P2OUT = p2;P3OUT = p3;++stepIndex;break;case 0x01: // 整步、顺时钟方向index = stepIndex & 0x03;p3 |= fullStepA[index];p2 |= fullStepB[index];P3OUT = p3;P2OUT = p2;++stepIndex;break;case 0x02: // 半步、逆时钟方向index = stepIndex & 0x07;p2 |= HalfStepA[index];p3 |= CcwHalfStepB[index];P2OUT = p2;P3OUT = p3;++stepIndex;break;case 0x03: // 半步、顺时钟方向index = stepIndex & 0x07;p3 |= CwHalfStepB[index];p2 |= HalfStepA[index];P3OUT = p3;P2OUT = p2;++stepIndex;break;default: break;}// 如果单步状态下,禁止定时器中断if( state & MOTION_MASK ){TACCTL0 &= ~CCIE;}}////////////////////////////////////////// 处理来自串口0 的接收中断interrupt [UART0RX_VECTOR] void UART0_RX_ISR(void) {//接收来自的数据UART0_RX_BUF[nRX0_Len_temp] = RXBUF0;nRX0_Len_temp += 1;if(nRX0_Len_temp >= 2)if(UART0_RX_BUF[nRX0_Len_temp - 2] == '\r' && UART0_RX_BUF[nRX0_Len_temp - 1] == '\n') {// 过滤掉回车换行(\r\n)if(nRX0_Len_temp == 2){nRX0_Len_temp = 0;}else if(nRX0_Len_temp > 2){nRX0_Len = nRX0_Len_temp;nRev_UART0 = 1;nRX0_Len_temp = 0;}}}////////////////////////////////////////// 处理来自串口0 的发送中断interrupt [UART0TX_VECTOR] void UART0_TX_ISR(void) {if(nTX0_Len != 0){// 表示缓冲区里的数据没有发送完nTX0_Flag = 0;TXBUF0 = UART0_TX_BUF[nSend_TX0];nSend_TX0 += 1;if(nSend_TX0 >= nTX0_Len){nSend_TX0 = 0;nTX0_Len = 0;nTX0_Flag = 1;}}}interrupt [WDT_VECTOR] void WDT_ISR(void){unsigned char sw_state;static unsigned char one_sec_flag = 0;// 获得P1口的输入sw_state = ~P1IN & 0x0f;// 判断是否有键按下if( sw_state == 0x00 ){// 禁止看门狗中断IE1 &= ~WDTIE;// 判断是否S2的激活状态小于1秒if( !one_sec_flag && (SW[1] >= DEBOUNCE_CNT) ){toggle_motion();}// 复位状态计数器SW[0] = 0;SW[1] = 0;SW[2] = 0;SW[3] = 0;// 复位标志one_sec_flag = 0;// 使能P1口的中断功能P1IFG = 0x00;P1IE = 0x0f;}else{// 检查是否是S1状态if( sw_state & 0x01 ){if( SW[0] < ONE_SEC_CNT ){// 增加状态计数器++SW[0];}if( SW[0] == DEBOUNCE_CNT ){toggle_direction();}}else{SW[0] = 0;}// 检查是否是S2状态if( sw_state & 0x02 ){if( SW[1] < ONE_SEC_CNT ){// 增加状态计数器++SW[1];}if( SW[1] == ONE_SEC_CNT )toggle_stepping_mode();one_sec_flag = 1;SW[1] = 0;}}else{// 判断是否S2的激活状态小于1秒if( !one_sec_flag && (SW[1] >= DEBOUNCE_CNT) ) {toggle_motion();}one_sec_flag = 0;SW[1] = 0;}// 检查是否是S3状态if( sw_state & 0x04 ){// 检查是否是连续模式if( (state & MOTION_MASK) == 0 ){if( SW[2] < ONE_SEC_CNT ){// 增加状态计数器++SW[2];}if( SW[2] == DEBOUNCE_CNT ){increase_stepping_rate();}}else // 单步模式{// 增加状态计数器++SW[2];if( (SW[2] % DEBOUNCE_CNT) == 0 ){increase_stepping_rate();}}else{SW[2] = 0;}// 检查是否是S4状态if( sw_state & 0x08 ){if( SW[3] < ONE_SEC_CNT ){// 增加状态计数器++SW[3];}if( SW[3] == DEBOUNCE_CNT ){decrease_stepping_rate();}}else{SW[3] = 0;}}}interrupt [PORT1_VECTOR] void PORT1_ISR(void) {// 禁止端口1的中断P1IE = 0x00;// 清除端口1的中断标志P1IFG = 0x00;// 使能看门狗中断IE1 |= WDTIE;}void increase_stepping_rate(void){unsigned int new_rate;// 检查是否是连续模式if( (state & MOTION_MASK) == 0 )new_rate = rate >> 1;if( new_rate >= max_rate ){rate = new_rate;change_rate_flag = 1;}}//使能定时器A的中断TACCTL0 |= CCIE;}void decrease_stepping_rate(void){// 检查是否是连续模式if( (state & MOTION_MASK) == 0 ){if( rate <= (min_rate >> 1) ){rate <<= 1;change_rate_flag = 1;}}// 使能定时器A的中断TACCTL0 |= CCIE;}void toggle_stepping_mode(void){// 切换步进模式state ^= STEP_MASK;// 检查是否是半步模式if( state & STEP_MASK ){// 从整步模式切换到半步模式// 定时器的频率加倍rate = (rate >> 1);change_rate_flag = 1;max_rate = (MAX_RA TE >> 1);min_rate = (MIN_RATE >> 1);}else // 整步模式// 从半步模式切换到整步模式// 定时器的频率减半rate = (rate << 1);change_rate_flag = 1;max_rate = MAX_RATE;min_rate = MIN_RA TE;}}void toggle_motion(void){state ^= MOTION_MASK;// 检查是否是连续步进模式if( (state & MOTION_MASK) == 0 ){// 使能定时器中断TACCTL0 |= CCIE;}}void toggle_direction(void){state ^= DIR_MASK;}。