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

📄 medium_event.c

📁 用C语言写的用于微新公司数字信号控制器30F6014的
💻 C
字号:
/**********************************************************************
 *	程序说明
 *  
 *  该文件包含中等速率事件处理程序及其相关得函数,中等速率事件每10毫秒
 *	执行一次电压和速度控制循环在这里完成。
 **********************************************************************/

#include "general.h"
#include "hardware.h"
#include "defs.h"
#include "extern_globals.h"


void medium_event_handler(void);
void speed_loop(void);
void voltage_control(void);
void starting_code(void); 

extern void debounce_switches(void);

//中等事件处理
void medium_event_handler(void)
{
	long	ltemp;
	int		itemp;
	// MED_EVENT_RATE设为10mSec,参见defs.h
	if (medium_speed_event_count > MED_EVENT_RATE)
	{

		medium_speed_event_count=0;
		debounce_switches();
			
		//判断从获取(acquistion)到无刷(sensorless)转换后是否处于锁定周期,
		//如是(check_counter>0)则假定速度与最后的速度相同
		if (check_counter)
			rpm=user_parameters[7];
		else

			{				
			asm("disi  #5");
			ltemp=((unsigned long)user_parameters[25] \
					*(unsigned long)period_measurement);

			if (ltemp < (COUNTER_RATE*60/65535))
				rpm=65535;
				
			else
				rpm = COUNTER_RATE*60/ltemp;
			}				

 		if (run_state!=RUNNING) stall_counter=0;

		// 检测是否超速
		if (!trip_state)
		{
			if ((rpm>user_parameters[14]) && (control_flags.SENSORLESS))
			{
				DISABLE_FIRING;
				run_state=FAULT;
				trip_state=OVER_SPEED;
			}
		
			if (stall_counter>user_parameters[13])
				
			{
				DISABLE_FIRING;
				run_state=FAULT;
				trip_state=STALLED;
			}
			else
				stall_counter++;
		}

		// 计算相位超前
		if (rpm < user_parameters[11])
		{
			phase_advance=TIME_CORRECTION;
		}	
		else
		{

			ltemp=(long)(rpm-user_parameters[11])*user_parameters[12];
			phase_advance=((ltemp*period_measurement)/180000)+TIME_CORRECTION;
		}
						
		if (control_flags.SENSORLESS==TRUE) speed_loop();

		voltage_control();

		if (run_state==STARTING)	starting_code();


	}
	return;
}

// 速度控制子程序,当速度控制模式是开环是,不考虑PI.
// 如果是OPEN_VOLTS模式,PWM波的占空比直接由电位器控制
// 如果是OPEN_CURRENT模式,电流控制来自电位器
// 如果是CLOSED_VOLTS模式,PWM波的占空比直接由速度环输出控制
// 如果是CLOSED_CURRENT模式,速度环输出即是电流控制输入环
void speed_loop(void)
{

	static long speed_integral;
	int speed_error;
	long proportional_term, pos_wloop_limit, neg_wloop_limit;
	int control_output,scaled_demand;
	long temp;

	#ifdef DEBUG
		asm("bset	LATG,#2");
	#endif

	if ((run_state != RUNNING) || (check_counter))
	{
		speed_integral=0;

		return;
	}
	switch (user_parameters[1])
	{
		case OPEN_VOLTS:	speed_integral=0;

								//禁止PWM刷新
								PWMCON2bits.UDIS=1;
								scaled_demand=filtered_pot/user_parameters[37];
								//做补偿
								if (scaled_demand > FULL_DUTY) 	PDC1=0;
								else	PDC1=FULL_DUTY-scaled_demand;
								PDC2=PDC1;
								PDC3=PDC1;
								//使能PWM刷新
								PWMCON2bits.UDIS=0;
								return;
								break;

		case OPEN_CURRENT:speed_integral=0;
								scaled_demand=filtered_pot/user_parameters[38];
								if (scaled_demand >= (current_trip-ibus_offset))
									current_demand=current_trip-ibus_offset;
								else
									current_demand=scaled_demand;
								return;
								break;

		case CLOSED_VOLTS:
								//电流循环用到占空比缩放比例为*512,这里要*16384,比例为32,故*32
								pos_wloop_limit=pos_duty_limit*32;
								neg_wloop_limit=neg_duty_limit*32;
								break;
		case CLOSED_CURRENT:
								pos_wloop_limit=pos_current_limit;
								neg_wloop_limit=neg_current_limit;
								break;
	}
	
	speed_demand=filtered_pot*user_parameters[39];
	control_flags.TORQUE_LIMIT=FALSE;

	speed_error=speed_demand-rpm;

	proportional_term=((long)speed_error*(long)wloop_p_gain);

	if (proportional_term > pos_wloop_limit)
	{
		control_flags.TORQUE_LIMIT=TRUE;
		control_output=pos_wloop_limit/16384;
		if (user_parameters[1]==CLOSED_VOLTS)
			control_output+=ZERO_DUTY;

		speed_integral=0;
	}
	else
	{
		if (proportional_term < neg_wloop_limit)
		{
			control_flags.TORQUE_LIMIT=TRUE;
			control_output=neg_wloop_limit/16384;
			if (user_parameters[1]==CLOSED_VOLTS)
				control_output+=ZERO_DUTY;
		
			speed_integral=0;
		}
	}
	
	//计算I项
	if (control_flags.TORQUE_LIMIT==FALSE)
	{
		speed_integral+=((long)speed_error * (long)wloop_i_gain);
		temp=speed_integral+proportional_term;

		if (temp > pos_wloop_limit)
		{
			control_flags.TORQUE_LIMIT=TRUE;
			control_output=pos_wloop_limit/16384;
			if (user_parameters[1]==CLOSED_VOLTS)
				control_output+=ZERO_DUTY;
			
			//计算I项的限制
			speed_integral = pos_wloop_limit - proportional_term;
		}
		else
		{			
			if (temp < neg_wloop_limit)
			{
				control_flags.TORQUE_LIMIT=TRUE;
				control_output=(neg_wloop_limit/16384);
				if (user_parameters[1]==CLOSED_VOLTS)
					control_output+=ZERO_DUTY;
				
				speed_integral=neg_wloop_limit - proportional_term;
			}
			else

			//基于P、I项计算输出
			{
				control_output=(temp/16384);
				if (user_parameters[1]==CLOSED_VOLTS)
					 control_output+=ZERO_DUTY;
			}
		}
	}
	if (user_parameters[1]==CLOSED_VOLTS)
	{

		if (control_output < 0) control_output=0;

		//禁止PWM占空比寄存器刷新
		PWMCON2bits.UDIS=1;

		//把值放入占空比寄存器刷新
		control_output=FULL_DUTY-control_output;		
		PDC1=(unsigned int)control_output;
		PDC2=(unsigned int)control_output;
		PDC3=(unsigned int)control_output;
		//允许PWM占空比寄存器刷新
		PWMCON2bits.UDIS=0;
	}
	else
	{
		current_demand=control_output;
	}

	return;
}

// 电压控制子程序,TIMER3用于产生PWM
void voltage_control(void)
{
	static long voltage_integral;
	int voltage_error;
	long proportional_term;
	long temp;

	if ((run_state != RUNNING) && (run_state != STARTING))
	{
		voltage_integral=0;
		return;
	}

	if(IEC0bits.T3IE)	
	{
		IEC0bits.T3IE=0;
//		BRAKE_FIRE=0;
	}
  //计算电压误差和比例
	voltage_error=filtered_vdc-voltage_demand;
	proportional_term=((long)voltage_error*(long)vloop_p_gain);

	if (proportional_term > POS_V_LIMIT)
	{
		voltage_integral=0;
		return;
	}
	else
	{

		// 电压误差负饱和值为-10,即满度的1%
		if (voltage_error < -10)
		{
			voltage_integral=0;
			return;
		}
	}
	
	// 更新I项
	voltage_integral+=((long)voltage_error * (long)vloop_i_gain);
	temp=voltage_integral+proportional_term;

	//P+I大于正极限
	if (temp > POS_V_LIMIT)
	{
		voltage_integral = POS_V_LIMIT - proportional_term;
		return;
	}
	else
	{

		//P+I小于负极限
		if (temp <= 0)
		{
			voltage_integral = 0 - proportional_term;
			return;
		}
		else

		//计算输出
		{

			PR3=(unsigned int)(temp/512);
			TMR3=0;

			//允许 Timer3运行,当TMR3=PR3时触发中断
			IFS0bits.T3IF=0;
			IEC0bits.T3IE=1;
		}
	}
	return;
}

//起动代码子程序
void starting_code(void)
{
	unsigned int temp;
	unsigned long ltemp;
	static unsigned int rotation_timer=0;

	// 检查马达是否已经旋转
	if (control_flags2.ROTATION_CHECK==TRUE)
	{
		DISABLE_INTERRUPTS;
		control_flags.ACQUIRE2=TRUE;
		control_flags.ADCCONFIG=TRUE;
		control_flags2.ROTATION_CHECK=FALSE;
		ENABLE_INTERRUPTS;
		rotation_timer=user_parameters[36];
		return;
	}
	
	if ((control_flags.ACQUIRE2==TRUE) && (rotation_timer))
	{
		rotation_timer--;
		return;
	}
	else
	{
		control_flags.ACQUIRE2=FALSE;
	}

	// 检查自转
	if (control_flags2.WINDMILLING==TRUE)
	{
		if (new_PR2 < BRAKING_PR2_LIMIT)
		{
			new_PR2+=windmilling_decel_rate;
			return;
		}
		else
		{
			DISABLE_INTERRUPTS;
			control_flags2.WINDMILLING=FALSE;
			control_flags.DIR=user_parameters[0];
			IEC0bits.T2IE=0;
			control_flags.RAMP=FALSE;
			control_flags.LOCK1=FALSE;
			control_flags.LOCK2=FALSE;
			ENABLE_INTERRUPTS;
		}
	}
	
	// 进入加速区
	if (control_flags.RAMP==TRUE)
	{

    // 下面的语句用汇编写,主要是为了mul.us和div.sd指令,由于与ANSI C兼容问题编译器没有提供
    //  要做的计算是:
    //  new_speed= ramp_start_speed + (ramp_speed_delta*(starting_timer/ramp_time)^2)
		//	temp = ramp_start_demand + (ramp_demand_delta*starting_timer/ramp_time)
		// 首先把w0-w5压栈,以便编译器用来保存立即数,在后面的C程序中调用。
#define  V120	1	
		
#ifdef ORIG
		asm("	push.d	w0");
		asm("	push.d	w2");
		asm("	push.d	w4");
		asm("	mov.w	_starting_timer,w1");
		asm("	mov.w	_starting_timer,w0");
		asm("	mul.uu w0,w1,w4");
		asm("	mov.w _ramp_time,w2");
		asm("	repeat	#17");
		asm("	div.ud	w4,w2");
		asm("	mov.w _ramp_speed_delta,w1");
		asm("	mul.uu w0,w1,w4");
		asm("	repeat	#17");
		asm("	div.ud	w4,w2");
		asm("	mov.w	_ramp_start_speed,w1");
		asm("	add	w0,w1,w0");
		asm("	mov.w	w0,_new_speed");
		asm("	mov.w _ramp_demand_delta,w1");
		asm("	mov.w _starting_timer,w0");
		asm("	mul.us w0,w1,w4");
		asm("	mov.w _ramp_time,w2");
		asm("	repeat	#17");
		asm("	div.sd	w4,w2");
		asm("	mov.w	w0,_stemp");
		asm("	pop.d	w4");
		asm("	pop.d	w2");
		asm("	pop.d	w0");
#elif V120
                { unsigned long mul_result;
                  register unsigned int div_result asm("w0");
                  /* asm("instruction(s)" : outputs : inputs :
                                            clobbered registers ); */
 
                  asm volatile("mul.uu %1, %1, %0" : "=r"(mul_result) : 
                                            "r"(starting_timer));
                  asm volatile("repeat #17\n\t"
                      "div.ud %0, %1" : /* implied outputs */ : "r"(mul_result),
                                                                "r"(ramp_time) :
                                       "w0", "w1" );
                  asm volatile("mul.uu %1, %2, %0":"=r"(mul_result) : "r"(div_result),
                                                         "r"(ramp_speed_delta));
                  asm volatile("repeat #17\n\t"
                      "div.ud %0, %1" : /* implied outputs */ : "r"(mul_result),
                                                                "r"(ramp_time) :
                                       "w0", "w1" );
                  asm volatile("add %1, %2, %0" : "=r"(new_speed): "r"(ramp_start_speed),
                                                          "r"(div_result));
                  asm volatile("mul.us %1, %2, %0":"=r"(mul_result): "r"(starting_timer),
                                                        "r"(ramp_demand_delta));
                  asm volatile("repeat #17\n\t"
                      "div.ud %0, %1" : /* implied outputs */ : "r"(mul_result),
                                                                "r"(ramp_time) :
                                       "w0", "w1" );
                  stemp = div_result;
                }
#elif V130
                { unsigned long mul_result;
                  unsigned int div_result;

                  mul_result = __builtin_muluu(starting_timer, starting_timer);
                  div_result = __builtin_divud(mul_result, ramp_time);
                  mul_result = __builtin_muluu(div_result, ramp_speed_delta);
                  div_result = __builtin_divud(mul_result, ramp_time);
                  new_speed = div_result + ramp_start_speed;
                  mul_result =__builtin_mulus(starting_timer,ramp_demand_delta);
                  stemp = __builtin_divud(mul_result, ramp_time);
                }
#else
#error Which version
#endif
		temp=ramp_start_demand+stemp;
		

		//使用电压控制,还是电流控制
		if (user_parameters[40])
		{								

			temp=FULL_DUTY-temp;

			PWMCON2bits.UDIS=1;
			PDC1=temp;
			PDC2=temp;
			PDC3=temp;

			PWMCON2bits.UDIS=0;
		}
		else
			current_demand=temp;
		
		//计算新的PR2值
		ltemp=(COUNTER_RATE*20) / \
		((unsigned long)new_speed*(unsigned long)user_parameters[25]);

		if (ltemp>65535)
			new_PR2=65535;
		else
			new_PR2=ltemp;

		// 检查用何种探测方法,如果用方法1,则new step rate < step rate 
		if ((user_parameters[43]==FALSE) && \
			(new_PR2<=acquire1_enable_rate) && \
			(control_flags.ACQUIRE1==FALSE))
		{
			control_flags2.ACQUIRE1_REQUEST=TRUE;
			acquire_counter=0;
		}
		
		// 判断加速是否结束
		if (new_PR2 <=ramp_end_rate)
		{

			DISABLE_INTERRUPTS;
			control_flags.RAMP=FALSE;		
			DISABLE_FIRING;
			IEC0bits.T2IE = 0;

			// 检查用何种探测方法,如果用方法2,则关闭acquire_position函数 
			if (user_parameters[43]==TRUE)
			{
				control_flags.ACQUIRE2=TRUE;
				control_flags.ADCCONFIG=TRUE;
				control_flags2.RETRY_FLAG=FALSE;
				run_state=RUNNING;
			}
			else 	//如是方法1,前面已经执行,结束加速,进入错误状态
			{	
				run_state=FAULT;
				trip_state=FAILED_TO_START;
			}

			ENABLE_INTERRUPTS;
			return;
		}
	}	

  //进入锁存子程序
	if ((control_flags.LOCK1==FALSE) && (control_flags.LOCK2==FALSE))
	{
		if (control_flags.RAMP==FALSE)
		{
			starting_timer=0;
			control_flags.LOCK1=TRUE;
			
			// 判断是用电流还是电压控制
			if (user_parameters[40])
			{
	
				PWMCON2bits.UDIS=1;

				PDC1=(FULL_DUTY-hold1_demand);
				PDC2=PDC1;
				PDC3=PDC1;

				PWMCON2bits.UDIS=0;
			}
			else
				current_demand=hold1_demand;

			OVDCON=SECTOR0_OVERRIDE;

			ENABLE_FIRING;
		}
	}	
	
	// LOCK1时间结束
	if ((starting_timer >= user_parameters[2]) \
		&& (control_flags.LOCK1==TRUE))
	{
		starting_timer=0;
		control_flags.LOCK1=FALSE;
		control_flags.LOCK2=TRUE;

		//使用电压控制
		if (user_parameters[40])
		{

			PWMCON2bits.UDIS=1;

			PDC1=(FULL_DUTY-hold2_demand);
			PDC2=PDC1;
			PDC3=PDC1;

			PWMCON2bits.UDIS=0;
		}
		else
			current_demand=hold2_demand;

		if (control_flags.DIR==FORWARDS)
			OVDCON=SECTOR1_OVERRIDE;
		else
			OVDCON=SECTOR5_OVERRIDE;
	}

	// LOCK2时间结束
	if ((starting_timer > user_parameters[3]) \
		&& (control_flags.LOCK2==TRUE))
	{
		control_flags.LOCK2=FALSE;
		control_flags.RAMP=TRUE;

		starting_timer=0;

		// 采用电压控制
		if (user_parameters[40])
		{

			PWMCON2bits.UDIS=1;

			PDC1=(FULL_DUTY-ramp_start_demand);
			PDC2=PDC1;
			PDC3=PDC1;

			PWMCON2bits.UDIS=0;
		}
		else
			current_demand=ramp_start_demand;

		// 检查用何种探测方法,如果用方法1,则ramp speed > speed
		if ((user_parameters[43]==FALSE) && \
			(ramp_start_rate<=acquire1_enable_rate))
		{
			control_flags2.ACQUIRE1_REQUEST=TRUE;
			acquire_counter=0;
		}
		
		//写sector值,保证正确换向
		sector=3;

		//给new_PR2赋新值,使能中断
		new_PR2=ramp_start_rate;
		IFS0bits.T2IF=TRUE;
		IEC0bits.T2IE=TRUE;
	}
	starting_timer++;
	return;
}

⌨️ 快捷键说明

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