⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 89c52-stepmotor.c

📁 AT89S52通过PWM控制步进电机的C51程序
💻 C
字号:
/******************************************************************************
*Project:步进电机控制程序练习 A practise program of stepper motor controlment 
        运行开始后电机正转,默认转速为最高速度的50%(2000Hz),速度可微调, 
        每次的增/减量为200Hz;正/反转切换过程中自动进行速度的逐步调节        
*MCU:  AT89s52    Frequency:11.0592MHz                                        
*I/O Port:  P1.0--正转指示LED	P1.1--反转指示LED	P1.3--加速	P1.4--减速
		P1.5--正/反转切换	P1.6--开始/停止;							
		P0.0~P0.3--步进电机ABCD四相控制输出    P0.4--L298使能输出INA,INB;
*Auther:  By yushun HUST 2009-3-19    All rights reserved.                  
*                                                                          
******************************************************************************/


#include<reg52.h>

#define unchar unsigned char
#define unint unsigned int

sbit Forword=P1^0;	  //Forword LED
sbit Reverse=P1^1;	  //Reverse	LED
/*
sbit P13=P1^3;	      //SpeedUp
sbit P14=P1^4;	      //SpeedDown
sbit P15=P1^5;	      //Switch
sbit P16=P1^6;	      //Start_Stop
*/
sbit PA=P0^0;
sbit PB=P0^1;
sbit PC=P0^2;
sbit PD=P0^3;

sbit INAB=P0^4;
					
unchar code PHA[8]={0x11,0x13,0x12,0x16,0x14,0x1c,0x18,0x19};//高四位为0001B是因运行时INAB=1
                  // A    AB   B    BC   C    CD   D    DA

unchar code PWM_H[10]={0xfc,0xfc,0xfd,0xfd,0xfd,0xfe,0xfe,0xfe,0xfe,0xfe};
unchar code PWM_L[10]={0x65,0xff,0x6c,0xbf,0xff,0x32,0x5c,0x7f,0x9c,0xb5};
				  //  1000Hz					2000Hz				2800Hz

unchar phase;
unchar pwm,pwm_temp;
bit Switch;                     //方向切换标志位,正转时Switch=1;
bit Start_Stop;                 //起停控制标志位,开始运转时Start_Stop=1.


/*****************************************************************************
延时子程序,延时时间10ms
*****************************************************************************/
void delay10ms(void)			
{
	unchar i,j;
	for(i=20;i>0;--i)
		for(j=248;j>0;--j)
			;
}


/*****************************************************************************
延时子程序,延时时间500ms
*****************************************************************************/
void delay500ms(void)			
{
	unchar i,j,k;
	for(i=5;i>0;--i)
		for(j=200;j>0;--j)
			for(k=248;k>0;--k)
			;
}


/*****************************************************************************
键盘扫描子程序
*****************************************************************************/ 
void keyscan(void)
{
	if((P1 & 0x78)!=0x78)
	{
		delay10ms();                        //软件去抖
		if((P1 & 0x78)!=0x78)
		{
			if((P1 & 0x78)==0x70)           //加速
			{
				if(pwm<10)
					pwm++;
				else
					pwm=9;
				delay500ms();               //速度改变频率控制,避免急加减速
			}

			if((P1 & 0x78)==0x68)           //减速
			{
				if(pwm>0)
					pwm--;
				else
					pwm=0;
				delay500ms();
			}

			if((P1 & 0x78)==0x58)            //改变运转方向	
			{
				Forword=Reverse=0;           //换向中,两个指示LED同时亮
				while(pwm>0)                 //换向前减速至最低速1000Hz
				{
					pwm--;
					delay500ms();
				}

				PA=PB=PC=PD=1;               //急停
				delay500ms();
				delay500ms();

				Switch=~Switch;              //执行方向变更
				if(Switch==1)                //指示LED变更
					Reverse=1;
				else
					Forword=1;

				while(pwm<5)                 //换向后加速至2000Hz
				{
					pwm++;
					delay500ms();
				}

			}

			if((P1 & 0x78)==0x38)            //运转、停止切换
			{
				Start_Stop=~Start_Stop;      //Start_Stop=1时运转

				if(Start_Stop==1)            //由停止开始运转,重新初始化参数
				{
					Switch=1;                //默认运转方向为正向
					Forword=Reverse=0;
					INAB=1;                  //使能L298输出
					pwm=pwm_temp=0;
					TH0=PWM_H[pwm];
					TL0=PWM_L[pwm];
					TR0=1;                   //开定时器0
					delay500ms();
					 while(pwm<5)            //加速至2000Hz
					{
						pwm++;
						delay500ms();
					}

					Reverse=1;
				}

				else                         //由运转到停止,关闭定时器0及L298降低功耗
				{
					Forword=Reverse=0;
					while(pwm>0)             //停止前减速至最低速1000Hz
					{
						pwm--;
						delay500ms();
					}

					PA=PB=PC=PD=1;           //急停
					delay500ms();
					delay500ms();
					
					TR0=0;                   //关定时器0
					INAB=0;                  //关L298,电机自由停止
					Forword=Reverse=1;
				}


			}


		}
	}
}


/*****************************************************************************
定时器0中断服务子程序
依次改变接通的相位phase;若脉宽控制pwm改变,则重新载入定时初值,从而改变脉冲周期
*****************************************************************************/	
void timer0(void) interrupt 1 using 1
{
	if(Switch==1)                        //正转时phase递增循环
	{
		if(phase>=7)                     //判断和改变相位
			phase=0;
		else
			phase++;
	}

	if(Switch==0)                        //反转时phase递减循环
	{
		if(phase<=0)                     //判断和改变相位
			phase=7;
		else
			phase--;
	}

    P0=PHA[phase];                       //相位输出
	
	TR0=0;                               //关定时器0
	if(pwm!=pwm_temp)                    //存在速度改变则重新赋初值
	{
		TH0=PWM_H[pwm];
		TL0=PWM_L[pwm];
	}
	
	else
		;

	TR0=1;	
	pwm_temp=pwm;
	
}	


/*****************************************************************************
主程序main
初始化系统参数及变量,开中断,键盘扫描输入
*****************************************************************************/
void main(void)
{
	P0=0x00;
	phase=0;                              //同时INAB=1
	pwm=pwm_temp=0;
	Switch=1;
	Start_Stop=0;
	Forword=Reverse=0;                   //系统复位指示
	delay500ms();
	delay500ms();
	P1=0xff;                             //同时LED熄灭

	ET0=1;                               //定时器0中断允许
	EA=1;                                //总中断允许

	while(1)
	{
		keyscan();
	}
	
}			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -