两相三线无刷电机控制总结

1、代码


#include	"extern.h"

#define HALL_R()	pa.5

#define UN_H()		pa.7 = 1
#define UN_L()		pa.7 = 0
#define UP_H()		pa.4 = 1
#define UP_L()		pa.4 = 0
#define VN_H()		pa.6 = 1
#define VN_L()		pa.6 = 0
#define VP_H()		pa.3 = 1
#define VP_L()		pa.3 = 0

#define PWM_R()		pa.0

#define MIN_START_PWM	3
#define MAX_WAIT_TIME	50000
#define MIN_WAIT_TIME	5000

byte g_Pwm = 0; 
byte g_PwmCtl = MIN_START_PWM;
byte g_MotorFlg= 0; // 0正常转 1堵转
byte g_SmoothFlg = 0; //是否平滑 0 启动平滑
byte g_TurnCnt = 0;
byte g_MaxPwm = 100;
word g_MaxWaitTime = MAX_WAIT_TIME;

void Hall_Init()
{
	paph.5 = 0;
    pac.5 = 0;
}

void Motor_Stop()
{
	UN_L();
	UP_L();

	VN_L();
	VP_L();
}
void Motor_Init()
{
	paph.3 = 0;
    pac.3 = 1;
	paph.4 = 0;
    pac.4 = 1;
	paph.6 = 0;
    pac.6 = 1;
	paph.7 = 0;
    pac.7 = 1;

	Motor_Stop();

	pwmgclk = 0B10010000; //2M
	pwmgcubl = 0B10000000;
	pwmgcubh = 0B00001100;

	pwmg1c = 0B00000000;  //pwmg1c = 0B00000110; //PA4
	pwmg1dtl = 0B10000000;
	pwmg1dth = 0B00001100;

	pwmg2c = 0B00000000; //pwmg2c = 0B00000110; //PA3
	pwmg2dtl = 0B10000000;
	pwmg2dth = 0B00001100;
}

void Motor_Task()
{
	word wait = 0;
	
	if(0 == g_Pwm)
	{
		Motor_Stop();
		g_PwmCtl = MIN_START_PWM;
		g_SmoothFlg = 0;
	}else
	{ 
		g_MotorFlg = 0;

		UN_H();
		VP_H();

		pwmg2dtl = (g_PwmCtl&0x07)<<5;
		pwmg2dth = (g_PwmCtl&0xf8)>>3;
		pwmg2c = 0B00000110; //PA3
		
		wait = 0;
		while(!HALL_R())
		{
			.Delay 4*20; //这个地方减小有利于降低震动
			
			wait++;
			if(wait > g_MaxWaitTime)
			{
				g_MotorFlg = 1; //堵转
				break;
			}
		}
		
		pwmg2c = 0B00000000;
		VP_L();
		.Delay 4*60; //启动放电
		UN_L();

		if (g_MotorFlg == 1)
		{
			return;
		}

		VN_H();
		UP_H();
		
		pwmg1dtl = (g_PwmCtl&0x07)<<5;
		pwmg1dth = (g_PwmCtl&0xf8)>>3;
		pwmg1c = 0B00000110; //PA4
		
		wait = 0;
		while(HALL_R())
		{
			.Delay 4*20;

			wait++;
			if(wait > g_MaxWaitTime)
			{
				g_MotorFlg = 1; //堵转
				break;
			}
		}
		pwmg1c = 0B00000000;
		UP_L();
		.Delay 4*60; //启动放电
		VN_L();	


		g_TurnCnt += 1;
	}
}
/*
void Motor_Restart()
{
	word wait = 0;

	if(g_MotorFlg == 1)
	{
		g_PwmCtl = 0;
		g_SmoothFlg = 0; //再次启动采用平滑启动

		g_MotorFlg = 0;
		wait = 0;
		if(!HALL_R())
		{
			VN_H();
			UP_H();

			pwmg1dtl = (30&0x07)<<5;
			pwmg1dth = (30&0xf8)>>3;
			pwmg1c = 0B00000110; //PA4

			while(!HALL_R())
			{
				.Delay 4*100;

				wait++;
				if(wait > 10000)
				{
					g_MotorFlg = 1;
					break;
				}
			}
			pwmg1c = 0B00000000;
			UP_L();
			.Delay 4*20;
			VN_L();
		}else
		{
			UN_H();
			VP_H();

			pwmg2dtl = (30&0x07)<<5;
			pwmg2dth = (30&0xf8)>>3;
			pwmg2c = 0B00000110; //PA3

			while(HALL_R())
			{
				.Delay 4*100;

				wait++;
				if(wait > 10000)
				{
					g_MotorFlg = 1;
					break;
				}
			}

			pwmg2c = 0B00000000;
			VP_L();
			.Delay 4*20;
			UN_L();
		}

		Motor_Stop();
	}
}
*/
void Pwm_Init()
{
	paph.0 = 0;
    pac.0 = 0;
	padier = 0B1111_1000;

	adcrgc = 0B0_0000000;
	//adcm = 0B0000_0100;
	$ ADCM /8;
	adcc = 0B10_1010_00;
}

#if 0
void Pwm_Task()
{
#if 0
	byte cnt = 8;
	word Ad = 0;

	while(cnt--)
	{
		AD_START = 1;
		while(!AD_DONE)
		{

		}
		Ad += ADCR;
	}

	Ad >>= 3;
#endif

	word Ad = 0;

	AD_START = 1;
	while(!AD_DONE)
	{
	}
	Ad += ADCR;

	Ad >>= 1;
	if(Ad > 12)
	{
		g_Pwm = Ad - 12;
		if(g_Pwm < 20)
		{
			g_Pwm = 20;
		}
		if(g_Pwm > 100)
		{
			g_Pwm = g_MaxPwm;
		}
	}else
	{
		g_Pwm = 0;
		g_MotorFlg = 0;
	}
}
#endif

void t16_init(void)
{
	t16m = 0B100_11_111;  //262ms
	inten.T16 = 1;
}
void Pwm_Ctrl(void)
{
	if(0 != g_Pwm
		&& 0 == g_MotorFlg)
	{
		//平滑启动
		if(0 == g_SmoothFlg)
		{
			g_PwmCtl += 4;

			if(g_PwmCtl < MIN_START_PWM)
			{
				g_PwmCtl = MIN_START_PWM;
			}

			if(g_PwmCtl >= g_Pwm)
			{
				g_PwmCtl = g_Pwm;

				g_SmoothFlg = 1;
				g_MaxWaitTime = MIN_WAIT_TIME;
			}
		}else
		{
			g_PwmCtl = g_Pwm;
		}
	}
}
void	FPPA0 (void)
{
	.ADJUST_IC	SYSCLK=IHRC/4		//	SYSCLK=IHRC/2

	//	Insert Initial Code

	Hall_Init();
	Motor_Init();
	Pwm_Init();
	t16_init();
	ENGINT;
	g_Pwm = g_MaxPwm; //不用调速

	while (1)
	{
//		...
//		wdreset;

		if(g_MotorFlg == 0)
		{
			Motor_Task();
		}else if(g_MotorFlg == 1)
		{
			.Delay 4*1000*3000;
			g_MaxWaitTime = MAX_WAIT_TIME;
			g_PwmCtl = MIN_START_PWM; //堵转启动速度
			g_SmoothFlg = 0;
			Motor_Task();
			//Motor_Restart();
		}
		//Pwm_Task();
	}
}

static byte g_1SCnt = 5;
void	Interrupt (void)
{
	pushaf;

	if (Intrq.T16)
	{	//	T16 Trig
		//	User can add code
		Intrq.T16	=	0;
		//...
		Pwm_Ctrl();

		g_1SCnt += 1;

		if(g_1SCnt >= 4) {
			g_1SCnt = 0;
			//Pwm_Task();
#if 1
			if(g_TurnCnt > 105) {
				g_MaxPwm -= 3;
				g_Pwm = g_MaxPwm; //不用调速
			} else if(g_TurnCnt < 100) {
				g_MaxPwm += 3;
				if (g_MaxPwm >= 100) {
					g_MaxPwm = 100;
				}
				g_Pwm = g_MaxPwm; //不用调速
			}

			g_TurnCnt = 0;
#endif
		}

	}

	popaf;
}

 

2、总结

1)两相在切换的时候,需要稍微延时来将电机上的电流损耗掉,避免转相产生大的毛刺。这个可以看电机线上的波形来判断是不是有毛刺或者尖峰。

2)电机要做堵转检测。

3)电机从静止启动要做平滑升速。

4)电机要做过压超速检测。这个可以根据转相的频率来计算。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值