f4..chabu,,zhixian chegnxu timer8 ch1 ch2 togglepulse

#ifndef __STEPMOTOR_H 
#define __STEPMOTOR_H 

#include "sys.h" 
#include "stm32f4xx_tim.h" 
#include "usart.h" 


//使用定时器8 C6、C7/C8/C9
//端口定义 

//xpul====c6
//xdir====g5
//xena====g6

//ypul====c7
//ydir====g7
//yena====g8

#define STEPMOTOR1_DIR PGout(5)  // DS0 
#define STEPMOTOR1_ENA PGout(6)// DS1   
 

#define STEPMOTOR2_DIR PGout(7)  // DS0 
#define STEPMOTOR2_ENA PGout(8)// DS1   
/*---------------------- 配置宏 ------------------------*/
//===========x电机
#define STEPMOTOR1_DIR_PIN           GPIO_Pin_5       		 // KEY 引脚      
#define STEPMOTOR1_DIR_PORT          GPIOG                    // KEY GPIO端口     
#define STEPMOTOR1_DIR_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define STEPMOTOR1_DIR_CLK_ENA()    {RCC_AHB1PeriphClockCmd(STEPMOTOR1_DIR_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

#define STEPMOTOR1_ENA_PIN           GPIO_Pin_6       		 // KEY 引脚      
#define STEPMOTOR1_ENA_PORT          GPIOG                    // KEY GPIO端口     
#define STEPMOTOR1_ENA_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define STEPMOTOR1_ENA_CLK_ENA()    {RCC_AHB1PeriphClockCmd( STEPMOTOR1_ENA_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

//=========y电机
#define STEPMOTOR2_DIR_PIN           GPIO_Pin_7       		 // KEY 引脚      
#define STEPMOTOR2_DIR_PORT          GPIOG                    // KEY GPIO端口     
#define STEPMOTOR2_DIR_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define STEPMOTOR2_DIR_CLK_ENA()    {RCC_AHB1PeriphClockCmd( STEPMOTOR2_DIR_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

#define STEPMOTOR2_ENA_PIN           GPIO_Pin_8       		 // KEY 引脚      
#define STEPMOTOR2_ENA_PORT          GPIOG                    // KEY GPIO端口     
#define STEPMOTOR2_ENA_CLK           RCC_AHB1Periph_GPIOG	    // KEY GPIO端口时钟
#define STEPMOTOR2_ENA_CLK_ENA()    {RCC_AHB1PeriphClockCmd( STEPMOTOR2_ENA_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能

//两个电机都是一样
#define CW 0  //正转
#define CCW 1 //反转
//+++++++++速度变量
extern u32 Toggle_Pulse[4];

extern u8 pwmflag;

void stepmotor1234_gpio_Init(void);//初始化  
void stepmotor1234_timer8_Init(u32 arr,u32 psc);//初始化 
#endif 

step.c




#include "stepmotor.h" 

//翻转点,决定速度
u32 Toggle_Pulse[4]={900,500,500,500};   
int32_t xend=0;//x终点坐标
int32_t yend=0;//x终点坐标
u32 steptotalnum=0;//总步长
int32_t fi=0;//偏差
u8 moveaxisflag=0;//=0,x轴,=1,y轴
u8 movingstatus=0;//运动标记位,=0停止,=1正在运动

void stepmotor1234_gpio_Init(void)//初始化 
{
	GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
	//xdir
	STEPMOTOR1_DIR_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Pin   = STEPMOTOR1_DIR_PIN;	 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz 
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 
	GPIO_Init(STEPMOTOR1_DIR_PORT, &GPIO_InitStructure);	
	
	//xena
	STEPMOTOR1_ENA_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Pin   = STEPMOTOR1_ENA_PIN;	 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz 
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 
	GPIO_Init(STEPMOTOR1_ENA_PORT, &GPIO_InitStructure);	
	
	//ydir
	STEPMOTOR2_DIR_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Pin   = STEPMOTOR2_DIR_PIN;	 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz 
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 
	GPIO_Init(STEPMOTOR2_DIR_PORT, &GPIO_InitStructure);	
	
	
	//yena
	STEPMOTOR2_ENA_CLK_ENA(); 	//初始化KEY时钟	
	GPIO_InitStructure.GPIO_Pin   = STEPMOTOR2_ENA_PIN;	 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz 
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 
	GPIO_Init(STEPMOTOR2_ENA_PORT, &GPIO_InitStructure);	
	
}


//(1)    TIM_OCMode:比较输出模式选择,总共有八种,常用的为PWM1/PWM2。它设定CCMRx寄存器OCxM[2:0]位的值。

//(2)    TIM_OutputState:比较输出使能,决定最终的输出比较信号OCx是否通过外部引脚输出。它设定TIMx_CCER寄存器CCxE/CCxNE位的值。

//(3)    TIM_OutputNState:比较互补输出使能,决定OCx的互补信号OCxN是否通过外部引脚输出。它设定CCER寄存器CCxNE位的值。

//(4)    TIM_Pulse:比较输出脉冲宽度,实际设定比较寄存器CCR的值,决定脉冲宽度。可设置范围为0至65535。

//(5)    TIM_OCPolarity:比较输出极性,可选OCx为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定CCER寄存器的CCxP位的值。

//(6)    TIM_OCNPolarity:比较互补输出极性,可选OCxN为高电平有效或低电平有效。它设定TIMx_CCER寄存器的CCxNP位的值。

//(7)    TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出1或输出0,即在空闲状态(BDTR_MOE位为0)时,经过死区时间后定时器通道输出高电平或低电平。它设定CR2寄存器的OISx位的值。

//(8)    TIM_OCNIdleState:空闲状态时互补通道输出电平设置,可选输出1或输出0,即在空闲状态(BDTR_MOE位为0)时,经过死区时间后定时器互补通道输出高电平或低电平,
//设定值必须与TIM_OCIdleState相反。它设定是CR2寄存器的OISxN位的

void stepmotor1234_timer8_Init(u32 arr,u32 psc)//初始化 
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);  	//TIM1时钟使能    
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 	//使能PORTA时钟	
	
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM8); //GPIOA8复用为定时器1
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM8); //GPIOA8复用为定时器1

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 |GPIO_Pin_7;           //GPIOA8--
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        //上拉  GPIO_PuPd_DOWN;      //下拉
	GPIO_Init(GPIOC,&GPIO_InitStructure);              //初始化PA8
	//-------------------
//选择定时器模式
  
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频0
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值  65535最大值
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //    ((uint16_t)0x0000)
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;  //20201020
	TIM_TimeBaseInit(TIM8,&TIM_TimeBaseStructure);//初始化定时器8
	

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
	//输出极性:TIM输出比较极性低TIM_OCPolarity_High
	TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_Low; 
	TIM_OCInitStructure.TIM_OCNPolarity= TIM_OCNPolarity_Low;
 
 // TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出1或输出0
	 TIM_OCInitStructure.TIM_OCIdleState=  TIM_OCIdleState_Reset ;//      ((uint16_t)0x0000) 
		TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Set;//((uint16_t)0x0000)
	
	 
		TIM_OCInitStructure.TIM_Pulse        =Toggle_Pulse[0];
	 	TIM_OCInitStructure.TIM_OutputState  = TIM_OutputState_Enable; //比较输出使能
	  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;//	
	 	TIM_OC1Init(TIM8, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 4OC1
		TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable);  
		//禁止使能TIM1在CCR1上的预装载寄存器
    TIM_OC1FastConfig(TIM8,  TIM_OCFast_Disable); 
		
		
	 	TIM_OCInitStructure.TIM_Pulse=Toggle_Pulse[1];
	 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;//	
	 	TIM_OC2Init(TIM8, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 4OC1
		TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);  //使能TIM1在CCR1上的预装载寄存器
 

// 
//	 不对定时器做任何分频,并且让它满计数,即计数周期为65535。接下去再设置个
//	 通道的的工作模式为输出比较翻转模式,设置通道1的比较值为CCR1_Val、CCR3_Val、CCR3_Val、CCR4_Val,
//	 它们的值在OCToggle.h中定义。然后打开个通道的输出比较事件的中断。最后在打开定时器。这样的话,
//	 定时器这段就配置完成了。
  //主函数NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	    NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn;  //TIM8中断
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级1级
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级1级
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
      NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
			 
			TIM_ARRPreloadConfig(TIM8,ENABLE);//ARPE使能 
			TIM_ClearITPendingBit(TIM8, TIM_IT_CC1);//清除标志位TIM_IT_CC1
			TIM_ClearITPendingBit(TIM8, TIM_IT_CC2);//清除标志位TIM_IT_CC1
						
       //中断标志
	    
      
		//打开定时器8,先不打开,后面需要的时候再打开,ENABLE
			TIM_Cmd(TIM8, DISABLE);
	    TIM_CtrlPWMOutputs(TIM8, DISABLE);    //ENABLE,这个语句智能关闭pwm输出,但是还是能够产生中断
			TIM_ITConfig(TIM8, TIM_IT_CC1 | TIM_IT_CC2 , DISABLE);
			
			movingstatus=0;
}
//以当前为原点,移动到终点坐标xendtemp,yendtemp,相对移动
void Interpolation_move(u32 xendtemp,u32 yendtemp,u16 speed)
{
	//一开始,偏差=0
	fi=0;
	//设置终点坐标
	xend=xendtemp;
	yend=yendtemp;
	//总步长
	steptotalnum=xendtemp+yendtemp;
	moveaxisflag=0;//一开始是x轴运动=0是x轴,=1是y轴;
	//第一步的偏差计算
//	fi = fi - yendtemp;
	//设置速度
	TIM_SetCompare1(TIM8, speed);
	TIM_SetCompare2(TIM8, speed);
	TIM_SetAutoreload(TIM8, speed);
	TIM_ARRPreloadConfig(TIM8, ENABLE);
	
		TIM_ITConfig(TIM8, TIM_IT_CC1 | TIM_IT_CC2 , ENABLE);
	TIM_Cmd(TIM8, ENABLE);//打开定时器8,
	TIM_CtrlPWMOutputs(TIM8, ENABLE);    //关闭所有
	TIM_CCxCmd(TIM8,TIM_Channel_1, ENABLE);//开启x轴
	TIM_CCxCmd(TIM8,TIM_Channel_2, DISABLE);

   movingstatus=1;
}

void Linear_move(int32_t xendtemp,int32_t yendtemp,u16 speedtemp)
{
	//判断当前是否在插补运动
	if(movingstatus!=0)//如果正在运动,那么就退出,刚进来需要在停止状态
			return;
	//判断坐标正负,决定第几象限,然后决定每个轴的运动方向;
	//第二第四象限
	if(xendtemp<0)//
	{
		//xdir=CCW;
		STEPMOTOR1_DIR=CCW;
		xendtemp= -xendtemp;	
	}
	else
	{
		STEPMOTOR1_DIR=CW;
	}
	
		//第二第四象限
	if(yendtemp<0)//
	{
		//xdir=CCW;
		STEPMOTOR2_DIR=CCW;
		yendtemp= -yendtemp;	
	}
	else
	{
		STEPMOTOR2_DIR=CW;
	}
 printf("xendtemp=%d, yendtemp=%d。\r\n",xendtemp,yendtemp);
	Interpolation_move(xendtemp,yendtemp, speedtemp);
		
}

void TIM8_CC_IRQHandler(void)
{  
  	static xi=0,yi=0;
		u8 last_axis=0;
	  static u8 ii=0;
	static u8 calflag=0;
	  last_axis = moveaxisflag;//记录上一次进给的活动轴

		if(TIM_GetFlagStatus(TIM8,TIM_FLAG_CC1)!=RESET)
				{
					TIM_ClearFlag(TIM8, TIM_FLAG_CC1);
						//TIM_SetCompare1(TIM8, 1500);
					//	STEPMOTOR1_DIR=!	STEPMOTOR1_DIR;
					ii=ii+1;
					if(ii%2==0)
					{
						//完整一个脉冲,两次反转
						calflag=1;
						ii=0;
					}

				}
				if(TIM_GetFlagStatus(TIM8,TIM_FLAG_CC2)!=RESET)
				{
					TIM_ClearFlag(TIM8, TIM_FLAG_CC2);
					//	TIM_SetCompare2(TIM8, 1500);
				//	STEPMOTOR2_DIR=!	STEPMOTOR2_DIR;
						ii=ii+1;
					if(ii%2==0)
					{
						//完整一个脉冲,两次反转,一个脉冲,进行一次fi
						calflag=1;
						ii=0;
					}
				}

	
	
	if(calflag==1)
	{
	  //根据上一步偏差,判断进给方向,计算下一步偏差

	  if(fi<0)//偏差xiao于0,在直线下方,进给y轴,计算偏差
		{ 
			moveaxisflag=1;
			fi=fi+xend;
			if(STEPMOTOR2_DIR==CW)
			{yi=yi+1;}
			else
				yi=yi-1;
			xi=xi;
			printf("y轴运动,第%d步。fi=%d,xi=%d, yi=%d\r\n",steptotalnum,fi,xi,yi);
		}
		else		//偏差大于0,在直线上方,进给x轴,计算偏差
		{
			moveaxisflag=0;
			fi=fi-yend;
			if(STEPMOTOR1_DIR==CW)
				xi=xi+1;
			else
				xi=xi-1;
			yi=yi;
			printf("x轴运动,第%d步。fi=%d,xi=%d, yi=%d\r\n",steptotalnum,fi,xi,yi);
		}
	
		//下一步活动轴和上一步不一致,需要更换运动轴

			//如果运动轴是x轴,上一次轴是y轴,不一致,更换成x轴
			if(moveaxisflag==0)
			{
				TIM_CCxCmd(TIM8,TIM_Channel_1, ENABLE);//x轴开启
				TIM_CCxCmd(TIM8,TIM_Channel_2, DISABLE);//y轴关闭
			}
				//上一个轴关闭
			//如果运动轴是y轴,上一次轴是x轴,不一致,更换成y轴
			else if(moveaxisflag==1)
			{
				TIM_CCxCmd(TIM8,TIM_Channel_1, DISABLE);//x轴关闭
				TIM_CCxCmd(TIM8,TIM_Channel_2, ENABLE);//y轴开启
			}		
		
		
				//进给步数-1
			steptotalnum=steptotalnum-1;
			//判断是否完成插补,完成之后,x/y都关闭
			if(steptotalnum==1)
			{
				TIM_CCxCmd(TIM8,TIM_Channel_1, DISABLE);//x轴关闭
				TIM_CCxCmd(TIM8,TIM_Channel_2, DISABLE);//y轴
				movingstatus=0;
				printf("结束运动\r\n");
      //中断标志
	      TIM_ITConfig(TIM8, TIM_IT_CC1 , DISABLE);
				TIM_ITConfig(TIM8, TIM_IT_CC2 , DISABLE);
				//关闭中断
			  TIM_CtrlPWMOutputs(TIM8, DISABLE);    //关闭所有
	     TIM_Cmd(TIM8, DISABLE);//打开定时器8,先不打开,后面需要的时候再打开,ENABLE
    
			}
			calflag=0;
		}
			
}



main



#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "oled.h"
#include "key.h"
#include "EXTI.h"
#include "timer.h"
#include "pwm.h"
#include "dcmotor.h"
#include "linesensor.h"
#include "stepmotor.h" 

extern u32 Toggle_Pulse[4];

//全局变量,存储按键键码
u8 GLOKEYVAL=0;
u8 pwmflag=0;
u8 pwmaddsubflag=0;

int main(void)
{
	int shuzi=987;
	u8 keyval=0;
	float aa=123.456;
	float vvtemp=0.2;
	delay_init(168); 
  LED_Init();
	OLED_Init();
	//TIMER14_CH1_PWM1_Init(500-1,84-1);//初始化  2khz F9
	uart_init(115200);
	KEY_Init();
	//EXTIX_Init();
	//TIMER13_Init(200-1,8400-1);
	//定时器时钟 84M,分频系数 8400,所以 84M/8400=10Khz ===0.1MS
  //的计数频率,计数 5000 次为 500ms   
	// TIM1_PWM_Init(500-1,84-1);//1US*500=500US====实际250us  300/500=0.6

	delay_ms(30);
	OLED_Clear();
	//LineSensor_Init();
	//TIM1_PWM_Init(600-1,84-1);
//	 DCMotor1Init();
//	  DCMotor2Init();
//		 DCMotor3Init();
//		  DCMotor4Init();
	//TIM_Cmd(TIM13,ENABLE);
//	//TIM_Cmd(TIM14, DISABLE);
//	
//	Toggle_Pulse[0]=100;
//		Toggle_Pulse[1]=1000;

	stepmotor1234_gpio_Init();
	stepmotor1234_timer8_Init(65535,168-1);//
	//168分频,168MHz/168=1Mhz,1us计算一次,那么计算Toggle_Pulse[0]=100次,100*1us=100us
	//反转一次电平。那么得到周期是100+100=200us
//	TIM_SetCompare1(TIM8, 1500);
//	TIM_SetCompare2(TIM8, 1500);
//	TIM_SetAutoreload(TIM8, 1500);
//	TIM_ARRPreloadConfig(TIM8, ENABLE);
//	TIM_Cmd(TIM8, ENABLE);//打开定时器8,
//	TIM_CtrlPWMOutputs(TIM8, ENABLE);    //关闭所有
//	TIM_CCxCmd(TIM8,TIM_Channel_1, ENABLE);//开启x轴
//	TIM_CCxCmd(TIM8,TIM_Channel_2, ENABLE);
	printf("逐点比较法\r\n");
	delay_ms(10);
	while(1)
	{
//		LED0=!LED0;
//		STEPMOTOR1_DIR=!STEPMOTOR1_DIR;
//		STEPMOTOR2_DIR=!STEPMOTOR2_DIR;
//		delay_ms(500);
		
//		//printf("逐点比较法??????\r\n");
 keyval=KEY_Scan();
//		if(keyval==10)
//		{
//				printf("k1(10,20)\r\n");
//		  //Linear_move(1000,2000,10000);
//		}
//			if(keyval==20)
//		{
//				printf("k2\r\n");
//		  //Linear_move(1000,2000,10000);
//		}
		if(keyval==30)
		{
				printf("k3(x,y)\r\n");
			   // TIM_CtrlPWMOutputs(TIM8, ENABLE);    //ENABLE,这个语句智能关闭pwm输出,但是还是能够产生中断
		//	STEPMOTOR2_DIR=!	STEPMOTOR2_DIR;
		  Linear_move(5,-8,1500);
		}
//			if(keyval==40)
//		{
//				printf("k4\r\n");
//		  //Linear_move(1000,2000,10000);
//		}
//		

			
	} 
}


		

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值