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

📄 m8hv04_pwm_hf.c

📁 AVR MEGA8 伺服电机脉冲发生器程序,用PWM方式发出连续变频的脉冲,可控制启动速度,加减速度,最高速度等参数,还有回零功能.SPI控制接口.带仿真PROTEUS文件
💻 C
字号:
#define TestSteps 8000
#define SPIendMark 1
//使用FASTPWM输出脉冲,脉冲宽度由T1PulseWidth决定
//脉冲宽度=T1PulseWidth * 0.125 us
#define T1PulseWidth 100
//HomeSpeed 定义HOME动作时的转速,>80
#define HomeSpeed 100
//Msteps_home_SP 定义HOME动作最大运动步数,比每圈脉冲数相等
#define Msteps_home_SP 1000
#include <iom8v.h>
#include <macros.h>
//ISARM pro
#define OUTQN0OFF PORTC|=0x01       //for 
#define OUTQN0ON PORTC&=~0x01
#define OUTQN1OFF PORTC|=0x02       //For 
#define OUTQN1ON PORTC&=~0x02
#define OUTQN1Pulse PORTC^=0x02

#define OUTQN2OFF PORTC|=0x04      //For 
#define OUTQN2ON PORTC&=~0x04
#define OUTQN2Pulse PORTC^=0x04
#define OUTQN3OFF PORTC|=0x08      //For 
#define OUTQN3ON PORTC&=~0x08
#define OUTQN3Pulse PORTC^=0x08

// motor 方向
#define OUTmotorDirCW PORTB&=~0x01
//顺时针
#define OUTmotorDirCCW PORTB|=0x01
#define OUTmotorDirPU PORTB^=0x01

// made pulse
#define OUTmotorPulse PORTB^=0x02
#define OUTmotorPulseON PORTB&=~0x02
#define OUTmotorPulseOFF PORTB|=0x02

//INPUT Define
//Home PD2
#define INhomeSen 0x02

#define DInput00 (PIND&0x02)
#define DriverRDY (PIND&0x04)
#define DInput02 (PIND&0x08)
#define DInput03 (PIND&0x10)

#define MCaddress 91
#define Com_MoveDF 81
#define Com_HomeDF 71
#define Com_StopDF 85
//////////////////////////////

unsigned int Timer1Set[200];	

unsigned int T1cSet;

///SPI
unsigned char RecTemp=0;
unsigned char SenTemp=5;
unsigned char SPI_Work=0;//spi staus
unsigned char SPI_Index=0;
unsigned char SPI_Index_Max=7;
unsigned char SPI_RecvBuf[8];
unsigned char SPI_TranBuf[8]={91,0,0,0,0,0,0,0};

unsigned char MCC_RecvBuf[8]; //马达控制器接收缓冲区
unsigned char MCC_TranBuf[9]={91,0,0,0,0,0,0,0};//马达控制器发送缓冲区


//MC control
unsigned char MC_Command=0;
unsigned int Target_POS=0;
unsigned int Old_POS=0;
unsigned int Now_POS=0;
unsigned int Move_Speed;
unsigned int PPsteps=0;

unsigned char MV_Step=0;
unsigned char MC_RDY=0;
unsigned char STATUS;
unsigned char HomeOK;   //1:已找到HOME位
unsigned int TC1V0;   //T1的值
unsigned int PosNow=0;//当前位置
	
	
	//unsigned int T1cSet;        //计数初值	
	unsigned int Home_TC1V0_SP=300; //Home计数初值setpoint	
	unsigned int Msteps_Total;//总运动步数setpoint
	unsigned int AccSteps;  //变速需要的步数
	unsigned char AccSL=10;  //变速持续步数
	unsigned char AccTmax;  //变速次数
	unsigned char AccTC;         //变速计数器
	unsigned int Nmin=200; //最低转速
	unsigned int Nmax=2000; //最高转速
    unsigned char AccN=20; //变转速
unsigned int AccStepEnd;  //加速结束时步数
unsigned int DccStepStart; //减速结束时步数	
	





void watchdog_init(void)
     {
	   WDR();
	   WDTCR=0x0F ;
	 }
	 
void Delay_1ms(void)
	{
	unsigned int i;

	for (i = 1; i<1140; i++)
		
			;
	}

void delayXms(unsigned int n)
     {
	   unsigned int i=0;
	   while(i<n)
	     {
		  Delay_1ms();
		  i++;
		 }
	 }
	 
	 
void port_init(void)
     {
	 // PORTA=0xF0;    //PA set to 1
	 // DDRA=0xF0;     //PA0-PA3:ADC PA4-PA6:KL0-KL2(OUT)
	                 //PA7:LCD-E  (OUTPUT)
					 
	  PORTB=0xff;    //PB set to 1
	  DDRB=0x13;     //PB0:DIR PB1:PULSE
	                 //PB2:SS PB3:MOSI PB4:MISO PB5:SCK
					 
	  PORTC=0xFF;    //PC set to 1
	  DDRC=0x0F;     //PC0-PC3:Q0-Q3
	      
	  PORTD=0xFF;    //PD set to 1
	  DDRD=0x00;     //PD0:RXD PD1:TXD PD2:DI0 PD3:DI1
	                 //PD4:DI2  PD5:DI3 
	  //OUTDEON;
	  
	SFIOR&=~(1<<PUD);  //OPEN UP LINK
	//MCUCR|=(1<<ISC11); //Down edge int1
	//GICR=(1<<INT1); //enable INT1
	  
	  delayXms(10); //delay 1s
	 }
	
void SPI_slaveInit(void)
     {
	  SPI_TranBuf[0]=MCaddress;
	  SPI_TranBuf[7]=SPIendMark;
	  SPDR=SPI_TranBuf[0];
	  SPCR=0xC1;
	 }
///////////////Timer init	 
void timer_init(void)
     {
	 /////timer0
	//TCCR0=0x00;    //stop T1	TCCR0=3; 1/64 TCNT0=125
	//TCNT0=125;
	//TIMSK|=(1<<TOIE0);   //enable T1 INT	 
    ////Timer1
	TCCR1B=0x00;    //stop T1	
	OCR1AH=0x00;    // no A match
	OCR1A=T1PulseWidth;
	//OCR1BH=0x00;    // no B match
	OCR1BL=0x00;
	TCCR1A=0x00;	
	//TCCR1A|=(1<<COM1A0);
	TCCR1A|=((1<<COM1A1)|(1<<WGM11));
	TCCR1B|=((1<<WGM12)|(1<<WGM13));
	TIMSK|=(1<<TOIE1);   //enable T1 INT	
	 }	 	 
	
#pragma interrupt_handler SPI_stc_isr:11
  void SPI_stc_isr(void)
     {
	  unsigned char i,summ;
	  unsigned int eev;
	   SPI_RecvBuf[SPI_Index]=SPDR;	   
	   SPDR=SPI_TranBuf[SPI_Index+1];
	   if(SPI_RecvBuf[0]==MCaddress)
	     {
	      SPI_Index++;
		  SPI_Work=1;  //spi is working
		  }
	   else
	     {
	      SPI_Index=0;
		  SPI_Work=0;  //spi stop
		  
		 } 
	   if(SPI_Index>SPI_Index_Max)
	     {
		  SPI_Index=0;
		  SPI_Work=0; //spi stop
		  SPDR=SPI_TranBuf[0];  //ready for recive
		  if(SPI_RecvBuf[1]>70 && MC_RDY==1 &&SPI_RecvBuf[7]==SPIendMark) 
		    {
			  summ=0;
		     for(i=1;i<6;i++)
			   {
			    summ=summ+SPI_RecvBuf[i];
			   }
			  if(summ==SPI_RecvBuf[6])
			   {
			    //OUTQN1ON;
			    SPI_TranBuf[3]=SPI_RecvBuf[2];
			    SPI_TranBuf[4]=SPI_RecvBuf[3];
			    Old_POS=Target_POS;
			    eev=SPI_RecvBuf[2];
	            eev=(eev<<8)+SPI_RecvBuf[3];
			    Target_POS=eev;
			    //Target_POS=100;
			    eev=SPI_RecvBuf[4];
	            eev=(eev<<8)+SPI_RecvBuf[5];
			    Move_Speed=eev;
			    MC_Command=SPI_RecvBuf[1];
			    SPI_RecvBuf[1]=0;
			    //SPDR=SPI_TranBuf[0];  //ready for recive
			   }
			 
			}//if(SPI_RecvBuf[1]>70  ) && MC_RDY==1
		 }
	 }//void SPI_stc_isr(void)
	
unsigned char HomeStop=1;
unsigned char KeepCR=0;
#pragma interrupt_handler timer1_ovf_isr:9
  void timer1_ovf_isr(void)
    {	
	   
	  
	  ICR1=T1cSet;	  //ICR1不能过小	  
	   PPsteps++;	 
	   OUTQN3Pulse;	   
	  
	   if(PPsteps==Msteps_Total)	
	    {		 
		 TCCR1B&=0xF8;     //Stop T1
		 MC_RDY=1;
		 PPsteps=0;
		 HomeStop=1;
		}//if(PPsteps==Msteps_Total)
	  KeepCR++;
	  if(!HomeOK)
	    {
		  if(!(PIND & INhomeSen))
		   {
		     TCCR1B&=0xF8;     //Stop T1
			 HomeStop=1;
		   }//if(!(PIND & INhomeSen))
		}
}//void timer1_ovf_isr(void)

void move_control(void)
 {
   if(PPsteps<AccStepEnd)
   //if(PPsteps<126)
     {
	  if(KeepCR>AccSL)
	    {
		 KeepCR=0;
		 AccTC++;
		 T1cSet=Timer1Set[AccTC];
		 
		}
	 }//if(PPsteps<AccStepEnd)
   else
     {
	 OUTQN2ON;
	  
	  if(PPsteps>DccStepStart)
	// if(PPsteps>875)
	    {
		 OUTQN2OFF;
		 
		 
		 if(KeepCR>AccSL)
	    {
		if(AccTC>0)
		 AccTC--;
		T1cSet=Timer1Set[AccTC];
		 KeepCR=0;
		 
		 
		}//if(KeepCR>AccSL)
		}//if(PPsteps>DccStepStart)
	 }//else
 }//void move_control(void)


void SPI_AnswerPOS(unsigned int aPOS)
     {
	  unsigned int eev;
	  unsigned char edh;
	  unsigned char edl;
	  edh=(aPOS>>8);
      edl=aPOS;
	  SPI_TranBuf[3]=edh;
	  SPI_TranBuf[4]=edl;
	 }
void MotorStart_Init(void)
   {
         
         MC_RDY=0;
		 SPI_TranBuf[2]=MC_RDY;
	     MC_Command=0;				     
		 PPsteps=0;
		 SPI_AnswerPOS(Old_POS);
   }//void MotorStart_Init(void)
   

 
unsigned int CalcT1cSet(unsigned int NSP)
 {
  return (480000/NSP-1);  //1.8度
  
  
 }  

void ACC_calc(void) 
{
 unsigned char i=0;
 unsigned int Nnowc;
  unsigned int HalfSteps;
 Move_Speed=6000;
 if(Move_Speed>Nmax)
    Move_Speed=Nmax;
 AccTmax=(Move_Speed-Nmin)/AccN;  //计算变速次数
 ////设置TIMER1的植
 //for( i=0;i<45;i++)
     //Timer1Set[i]=5000;
 
 Nnowc=Nmin;
 for(i=0;i<(AccTmax+1);i++)
    {	 
	 Timer1Set[i]=CalcT1cSet(Nnowc);
	 //CalcT1cSet(Nnowc);
	 //Timer1Set[i]=TSS;
	 Nnowc=Nnowc+AccN;
	}// for(i=0 to AccTmax)
//计算变速所需的步数

 HalfSteps=Msteps_Total/2;
 AccStepEnd=(AccTmax+1) * AccSL  ; 
 if(AccStepEnd>HalfSteps)  //总步数太小
   {
    
	DccStepStart=HalfSteps+AccSL;
	
    if(Msteps_Total<AccSL*3)
	  {	   
	   DccStepStart=Msteps_Total;   
	  }//if(Msteps_Total<AccSL*3)
	AccStepEnd=Msteps_Total-DccStepStart;
	}//if(AccSteps>Msteps_Total)
 else  //步数足够多
   {    
    DccStepStart=Msteps_Total-AccStepEnd-AccSL;
   }//else
 T1cSet=Timer1Set[0];
}//void ACC_calc(void)   

 
void MoveFun(void)
{
    unsigned int TarposStep;
	//STEPcode=10+PosID;
	  TarposStep=Target_POS;
	if(TarposStep != Old_POS)
	 {  
	  if(TarposStep>Old_POS)
	    {
		 Msteps_Total=TarposStep-Old_POS;//总运动步数
		 OUTmotorDirCCW;        //正向
		}//if Tar
	  else
	    {
		 Msteps_Total=Old_POS-TarposStep;//总运动步数
		 OUTmotorDirCW;
		}
	  	Delay_1ms();	   
	  ACC_calc();	 
	  //TCNT1=T1cSet;         //第一脉冲	在ACC_calc()中付初值
	  ICR1=T1cSet;
	  AccTC=0;             //Timer1Set[]下标计数器,move_control()中用
	  //TCCR1B=0x01;     //start T1, 8M  0.125us
	  TCCR1B|=0x1;     //start T1, 8M  0.125us		
	}//IF
	else
		 MC_RDY=1;   
}	// void MoveFun(void)
  
 
  
 unsigned int DelayCR=0; 
 
void main()
	{
	//delayXms(500); 
	port_init(); //IO初始化	
	
	timer_init();
	T1cSet=1000;
	TCNT1=T1cSet; 	
	SPI_slaveInit();
	SEI();	
	delayXms(100); 
	MV_Step=15;
	//MC_Command=81;
	Move_Speed=0;
	Target_POS=0;
	MC_RDY=1;
	//SPI_TranBuf[1]=MCaddress;
	SPI_TranBuf[2]=MC_RDY;
	
	///////
	Old_POS=0;
	Target_POS=TestSteps;
while(1)
  {
   switch(MV_Step)
    {
     case 10:  //home
   	  if(MC_Command==Com_HomeDF)//HOME
	    {
		 OUTQN0ON;
		 HomeOK=0;
		 MotorStart_Init();  //redy for start move	
		 T1cSet=CalcT1cSet(HomeSpeed);
		 ICR1=T1cSet;
		 Msteps_Total=Msteps_home_SP;
		 MV_Step=60;
		 HomeStop=0;
		 TCCR1B|=0x1;     //start T1, 8M/8  1us
	    }//if(MC_Command==Com_HomeDF)
	  break;
	  case 60:  //home
	     if(MC_RDY==1)
		   {
		    MV_Step=10;   //Home finish not OK!
			OUTQN0OFF;    //关闭驱动器
			HomeStop=0;
			break;
		   }//if(MC_RDY==1)
	     if(HomeStop==1)
		   {
		     
			 delayXms(10);
			 if(!(PIND & INhomeSen))
		      {		       
			   Target_POS=0;	
		       MC_RDY=1;
		       PPsteps=0;
			   HomeOK=1;
			   MV_Step=15;   //Home finish OK
		      }//if(!(PIND & INhomeSen))
			 else //research
			  {
			    HomeStop=0;
			    TCCR1B|=0x1;
			  }
		   }//  if(!(PIND & INhomeSen))
		 
	  break;
	  case 15:
   	  //if(MC_Command==Com_MoveDF && HomeOK==1)
	    {
		 //OUTQN2ON;
		 HomeOK=1;///////////
		 MotorStart_Init();  //redy for start move
		 OUTQN0ON;           //Enable motor driver
		 MoveFun();		
		 MV_Step=20;
		// TCCR1B=0x02;     //start T1, 8M/8  1us
	    }
	  break;
	
	case 20:	   
	   
		 //OUTQN2Pulse;
		 move_control();
	    
	   if(MC_RDY==1)
	     {
		  SPI_AnswerPOS(Target_POS);
	      //MV_Step=15;
		  MV_Step=50;
		  DelayCR=0;
		 // OUTQN3ON;
		 }
	break;
	case 50://测试程序
	     Delay_1ms();	 
	     DelayCR++;
		 if(DelayCR>5000)
		   {
		    if(Old_POS>0)
			  {
		       Old_POS=0;
	           Target_POS=TestSteps;
		       }//if(Old_POS>0)
			else
			  {
			    Old_POS=TestSteps;
	           Target_POS=0;
			  }//else
			 MV_Step=15;
		   }//if(DelayCR>10000)
	break;
   }//switch(MV_Step)
   //紧急停止命令,将关闭驱动器
   if(MC_Command==Com_StopDF)
     {
	  OUTQN0OFF;    //关闭驱动器
	  HomeOK=0;
	  MV_Step=10;
	 }
   //HOME OK 后收到HOME命令
   if(MC_Command==Com_HomeDF)// HOME
	 {
	  MV_Step=10;
	 }
	//刷新发送缓冲区的数据
    SPI_TranBuf[2]=MC_RDY;
	SPI_TranBuf[6]=PIND;   //Get INPUT status
  
   }//while
   
}//main

⌨️ 快捷键说明

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