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

📄 steper.c

📁 步近电机控制代码
💻 C
字号:
/*----------------------------------------------------------------------------------------------------
名称:  步进电机四相八拍驱动程序
文件名:steper.c
作者:  eastboy
E-mail: eastboy_007@163.com
日期:  2008年7月16日
版本:  1.0
申明:  按键部分程序参考了raosibin的4×4按键状态机思想程序
说明:  
   1.可通过按键选择正转或反转,碰到限位开关后自动微调上一次微调值后停止;
   2.可通过按键微调,即低速转动,以便精确调整位置;
   3.仿真时通过两个按钮模拟前后限位开关,以模拟实际生活当中步进电机带轴运动时部件的前后电限位,
     程序并可自动记住以前后限位开关为基点的微调步数;
   4.本程序只是通过了软件功能仿真,未做实物实验,不保证实际使用时可用,实际使用时应做相应参数调整;
   5.本程序未加入电机过流保护部分,有兴趣可以自行加入。
-----------------------------------------------------------------------------------------------------*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <stdint.h>

#define ShortPush 0x40
#define LongPush 0x80

volatile uint8_t Direction=0,Limit=0;  //Direction旋转方向,0为顺时针,1为逆时针;Limit限位,0为前限位,1为后限位
volatile uint8_t Pflag=0,TuneFlag=0; //Pflag限位开关标志,1为开关动作;TuneFlag微调标志,0为不微调,1为微调加,2为微调减,3为微调连加,4为微调连减
volatile SlowSpeed=0;//低速标志,1为低速,0为高速,用于微调时选低速
static uint8_t stepper[8]={0x80,0xC0,0x40,0x60,0x20,0x30,0x10,0x90};  //驱动状态码表
volatile uint16_t Position[2]={0x00,0x00};//限位开关动作后的微调步数记录

volatile uint8_t keycode=0x00;
volatile uint8_t LastKey=0xFF,CurKey=0x00;
volatile uint8_t keytimes=0x00;
volatile uint8_t key_limit=0x00;
volatile uint8_t stepcnt=0;
volatile uint16_t Pcnt=0;

#define StepperStop()  { TCCR1B=0x00;  PORTD&=~(1<<PD3); PORTC&=~(1<<PC2|1<<PC3); }//Disable driver
#define StepperStart() { PORTD|=(1<<PD3); TCCR1B=(1<<CS02|1<<CS00); TIMSK|=1<<TOIE1;}//Enable driver
	
ISR(SIG_OVERFLOW1)
{
	TCCR1B=0x00;//停止定时器
	if(SlowSpeed==1) //60ms
	{
		TCNT1H=0xC5;
		TCNT1L=0x69;
	}
	else if(SlowSpeed==0)  //15ms
	{
		TCNT1H=0xF1;
		TCNT1L=0x5B;
	}
	
	if(Direction==0)
	{
		PORTC&=~(1<<PC2|1<<PC3);
		PORTD=((1<<PD3)|stepper[stepcnt]);
		stepcnt++;
		if(stepcnt>7)		stepcnt=0;
		PORTC|=1<<PC2;
	}
	else if(Direction==1)
	{
		PORTC&=~(1<<PC3|1<<PC2);
		PORTD=((1<<PD3)|stepper[stepcnt]);
		stepcnt--;
		if(stepcnt==0xFF)	stepcnt=7;
		PORTC|=1<<PC3;
	}
	
	if(TuneFlag!=0)
	{
		switch(TuneFlag)
		{
			case 0x01:
			case 0x03:
				if(Limit==0x00)
					if(Pcnt>0) Pcnt--;
				else
					Pcnt++;
				break;
			case 0x02:
			case 0x04:
				if(Limit==0x00)
					Pcnt++;
				else
				{
					if(Pcnt>0) Pcnt--;
				}
				break;
			default:
				break;
		}
		Position[Limit]=Pcnt;
		eeprom_is_ready();
		eeprom_write_word((Limit==0x00 ? 0x01 : 0x03),Position[Limit]);
		
		if(TuneFlag==1 || TuneFlag==2)
		{
			StepperStop();
			goto T0End;
		}
		else
			StepperStart();
			goto T0End;
	}
	
	if(Pflag==1)
	{
		Pcnt++;
		if(Pcnt>=Position[Limit])
		{
			StepperStop();
			goto T0End;
		}	
		else
			TCCR1B=(1<<CS11|1<<CS10);//启动定时器
	}
	else
		TCCR1B=(1<<CS11|1<<CS10);//启动定时器
	T0End:
		;
}

ISR(SIG_INTERRUPT0)
{
	cli();
	StepperStop();
	key_limit=(PINB & 0X30);
	if(key_limit==0x20)  //前限位
	{
		Direction=1;
		Limit=0;
	}
	else if(key_limit==0x10)	//后限位
	{
		Direction=0;
		Limit=1;
	}
	Pflag=1;
	Pcnt=0;
	StepperStart();
	sei();
}
ISR(SIG_OVERFLOW0)
{
	TCNT0=0x64;
	
	CurKey=(PINB & 0X0F);
	if(CurKey==LastKey)
	{
		keytimes++;
		if(keytimes%5==0)//短按
		{
			keycode=(ShortPush|CurKey);
		}
		else if(keytimes>100) //长按
		{
			keytimes=101;
			keycode=(LongPush|CurKey);
		}
	}
	else if(CurKey!=LastKey)
	{
		LastKey=CurKey;
		keytimes=0x00;
	}
	else //无键按下或已释放
	{
		keytimes=0x00;
	}

}

void Timer0_init()
{
	TCCR0=0x00;
	TCNT0=0x64;        //10mS
	TCCR0=(1<<CS02|1<<CS00);	//1024预分频
	TIMSK|=1<<TOIE0;	
}

void Timer1_init()
{
	TCCR1B=0x00;//停止定时器
	TCNT1H=0xF1;
	TCNT1L=0x5B;//初始值
	TCCR1A=0x00;
	//TCCR1B=(1<<CS11|1<<CS10);//启动定时器
	TIMSK|=1<<TOIE1;
}
void avr_init()
{
//初始化端口
	DDRB=0X00;   //配置为输入,内部上拉
	PORTB=0XFF;
	
	DDRC=(1<<PC2|1<<PC3); //PC2,PC3 LED Out
	PORTC=0x00;
	
	DDRD=(1<<PD3|1<<PD4|1<<PD5|1<<PD6|1<<PD7);
	PORTD=0X00;
	
	MCUCR=(1<<ISC01);
	GICR=1<<INT0;
	
//初始化变量
	Direction=0;
	eeprom_is_ready();
	if(eeprom_read_byte(0x00)==0xFF)
	{
		eeprom_is_ready();
		eeprom_write_byte(0x00,0x00);
		eeprom_is_ready();
		eeprom_write_word(0x01,0x0000);
		eeprom_is_ready();
		eeprom_write_word(0x03,0x0000);
		Position[0]=0;
		Position[1]=0;
	}
	else
	{
		Position[0]=eeprom_read_word(0x01);
		Position[1]=eeprom_read_word(0x03);
	}
	
	Timer0_init();
    Timer1_init();
	
}

int main()
{
	cli();
	avr_init();
	sei();
	while(1)
	{
		switch(keycode)
		{
			case 0x4E:   //正转
				Direction=0;     //旋转方向,0为顺时针,1为逆时针
				SlowSpeed=0;  //速度标志,为1时慢速
				Pflag=0;      		//限位标志,为1时限位开关作用
				TuneFlag=0;    //微调标志,0为正常运转,1为位置微调
				StepperStart();
				break;
			case 0x4D:   //反转
				Direction=1;
				SlowSpeed=0;
				Pflag=0;
				TuneFlag=0;
				StepperStart();
				break;
			case 0x4B:   //微调+
				Direction=0;
				SlowSpeed=1;
				TuneFlag=1;
				Pflag=0;
				StepperStart();
				break;
			case 0x47:  //微调-
				Direction=1;
				SlowSpeed=1;
				TuneFlag=2;
				Pflag=0;
				StepperStart();
				break;
			case 0x8E:
				
				break;
			case 0x8D:
				
				break;
			case 0x8B:   //连续微调+
				TuneFlag=3;
				Pflag=0;
				break;
			case 0x87:  //连续微调-
				TuneFlag=4;
				Pflag=0;
				break;
			default:
				break;
		}
	}
}

⌨️ 快捷键说明

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