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

📄 isrs.c

📁 dsPIC30F在无传感器BLDC控制中的应用AN901(中文) 源代码1
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********************************************************************
 *                                                                     *
 *                        Software License Agreement                   *
 *                                                                     *
 *    The software supplied herewith by Microchip Technology           *
 *    Incorporated (the "Company") for its dsPIC controller            *
 *    is intended and supplied to you, the Company's customer,         *
 *    for use solely and exclusively on Microchip dsPIC                *
 *    products. The software is owned by the Company and/or its        *
 *    supplier, and is protected under applicable copyright laws. All  *
 *    rights are reserved. Any use in violation of the foregoing       *
 *    restrictions may subject the user to criminal sanctions under    *
 *    applicable laws, as well as to civil liability for the breach of *
 *    the terms and conditions of this license.                        *
 *                                                                     *
 *    THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION.  NO           *
 *    WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING,    *
 *    BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND    *
 *    FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE     *
 *    COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL,  *
 *    INCIDENTAL OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.  *
 *                                                                     *
  **********************************************************************/

 /**********************************************************************
 *                                                                     * 
 *    Author: Smart Power Soutions, LLP                                * 
 *                                                                     *
 *    Filename:       ISRs.c          	                                *
 *    Date:           7/6/05                                         *
 *    File Version:   5.00                                             *
 *    Project:        53                                               *
 *    Drawing:        2                                                *
 *                                                                     *
 *    Tools used:    MPLAB C30 Compiler v 1.30                      *
 *                                                                     *
 *    Linker File:    p30f3010.gld                                   *
 *                                                                     *
 *                                                                     *
 ***********************************************************************
 *	Code Description
 *  
 *  This file contains all the interrupt service routines (ISRs)
 *
 **********************************************************************/

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

void check_zero_crossing(void);
static void current_control(void);
static void acquire_position(void);



void __attribute__((__interrupt__)) _DefaultInterrupt(void)
{
// This is the default interrupt handler.  If an interrupt
// vector is not defined, then we will go here and wait
// in an infinite loop!
DISABLE_FIRING;
while(1);	
}

void __attribute__((__interrupt__)) _AddressError(void)
{
	DISABLE_FIRING;
	
	// Clear WDT 
	while(1)
	{
		ClrWdt();
	}
	return;
}

void __attribute__((__interrupt__)) _StackError(void)
{
	unsigned char i;

	DISABLE_FIRING;
	
	// Clear WDT 
	while(1)
	{
		ClrWdt();
	}
	return;
}

void __attribute__((__interrupt__)) _MathError(void)
{
	unsigned char i;

	DISABLE_FIRING;

	// Clear WDT 
	while(1)
	{
		ClrWdt();

	}
	return;
}

void __attribute__((__interrupt__)) _PWMInterrupt(void)
{
	slow_event_count++;
	medium_speed_event_count++;
	IFS2bits.PWMIF = 0;
	return;
}

void __attribute__((__interrupt__)) _FLTAInterrupt (void)
{
	if (run_state == STARTING)
		{IFS2bits.FLTAIF = 0; return;}
	if (fault_count++ < MAXFAULT)
		{IFS2bits.FLTAIF = 0; return;}
	DISABLE_FIRING;
	run_state=FAULT;
	if (!trip_state)	trip_state=HARDWARE_TRIP;
	IFS2bits.FLTAIF = 0;
	return;
}

void __attribute__((__interrupt__)) _ADCInterrupt (void)
{
	// Clear off interrupt flag
	IFS0bits.ADIF = 0;

	
	// Get Results from ADC Buffer and put them into relevant variables
	// When in normal running we get one phase voltage, dc bus voltage
	// dc bus current and VR2 as simultaneous samples every pwm
	// When acquiring we need to see all three phase voltages so 
	// we continuously cycle ADC CH0 between the three phase voltages
	if (control_flags.ACQUIRE2==TRUE)
	{
		switch (ADCHS)
		{
			case VPH_RED :		vph_red=ADCBUF0;
									ADCHS=VPH_YELLOW;
									break;

			case VPH_YELLOW : vph_yellow=ADCBUF0;
									ADCHS=VPH_BLUE;
									break;

			case VPH_BLUE	 : vph_blue=ADCBUF0;
									ADCHS=VPH_RED;
									break;

			default :			ADCHS=VPH_RED;
									break;
		}
	}
	else
	{
		vph=ADCBUF0;
	}
	vdc=ADCBUF1;  
	ibus=ADCBUF2;
	pot=ADCBUF3;
	
	// If a fault condition exists ensure run_state is set to FAULT
	// and return at this point.
	if (trip_state)	
	{
		run_state=FAULT;
		return;
	}

	// Do over voltage and over current trip checks if not already in fault
	if ((ibus>current_trip) && (run_state != INITIALIZING))
	{
		DISABLE_FIRING;
		run_state=FAULT;
		trip_state=OVER_CURRENT;
		return;
	}

	if ((vdc>voltage_trip) && (run_state != INITIALIZING))
	{
		DISABLE_FIRING;
		run_state=FAULT;
		trip_state=OVER_VOLTAGE;
		return;
	}
	
	// Now do current control with most up to date current sample
	// If current control is not active routine initialises some
	// variables and returns
	current_control();
	
	// Now reconfigure adc if required to sample different 
	// phase voltage feedback channel

	if (control_flags.ADCCONFIG==TRUE)
	{
		ADCHS = adc_channel_config;
	}

	if ((control_flags.ACQUIRE2==TRUE) && (run_state!=INITIALIZING))
	{
		acquire_position();
	}

	if ((control_flags.SENSORLESS) || (control_flags.ACQUIRE1))
	{
			check_zero_crossing();
	}
	
	
	return;
}

// Timer 1 is used as a guard timer to catch missed zero
// crossing events due to excessive demag time/insufficient
// phase advance for instance. Every zero crossing detected,
// PR1 is written with double the latest time delta between
// zero crossings and TIMER1 is reset to zero. If the timer
// ever reaches PR1 causing an interrupt, then the system is
// assumed to have missed a zero crossing and enters the LOST
// trip state.

void __attribute__((__interrupt__)) _T1Interrupt(void)
{
	DISABLE_FIRING;
	run_state=FAULT;
	if (!trip_state)	trip_state=LOST;
	IEC0bits.T1IE = 0;	// Disable interrupt so don't get
								// unnecessary calls
	IFS0bits.T1IF = 0;	// Clear off interrupt flag
	return;
}

// Timer 2 used as an output compare but not associated with
// an I/O line. It indicates time for a commutation.
// The ISR therefore actually does the commutation and also
// reconfigures voltage sensing channel and zero_crossing

void __attribute__((__interrupt__)) _T2Interrupt(void)
{

	// If we are acquiring using method1
	if (control_flags.ACQUIRE1)
	{
		// Set ADCCONFIG flag so that zero_crossing routine is correctly 
		// initialized next call.
		control_flags.ADCCONFIG=TRUE;
		// If we did not detect a valid zero crossing in the last
		// sector then need to initialize acquire and check counters
		// and also update the sector as this has not been done
		// by zero_crossing routine.
		if (control_flags.ZERO_CROSS==FALSE)
		{
			acquire_counter=0;
			check_counter=8;
			if (control_flags.DIR==FORWARDS)
			{
				if (sector==5) sector=0;
				else 				sector++;
			}
			else
			{
				if (sector==0) sector=5;
				else 				sector--;
			}
		}
	}

	// If this is first interrupt after ACQUIRE1 mode to be used
	if (control_flags2.ACQUIRE1_REQUEST)
	{
		control_flags2.ACQUIRE1_REQUEST=FALSE;
		control_flags.ACQUIRE1=TRUE;
		// Set ADCCONFIG flag so that zero_crossing routine is correctly 
		// initialized next call.
		control_flags.ADCCONFIG=TRUE;
		check_counter=8;	//This is 8 so that 1 elec cycle (6)
								//of tolerance checks after transition
								//to sensorless operation are ignored.
		acquire_counter=0;

	}
	// If swapping from acqisision mode 2 to sensorless
	// set sensorless flag and load check_counter
	// so that sensorless tolerance checks are disabled
	// for first electrical cycle as first few zero crossings
	// may violate tolerance checks due to change over transient
	if (control_flags.SWAP==TRUE)
	{
		control_flags.SENSORLESS=TRUE;
		control_flags.SWAP=FALSE;
		check_counter=6;
	}

	// Decrement the check_counter if > 0
	if (check_counter)	check_counter--;

	// If not in normal running then need to reload PR2 with
	// a new value calculated elsewhere.
	// When running sensorless the detection of a zero crossing
	// reloads PR2 and enables interrupt
	if (control_flags.SENSORLESS==FALSE)
	{
		// Load New Value Into PR2
		PR2=new_PR2;
		// Clear off TMR2 to ensure don't have issue with occasional
		// miss of TMR2=PR2 event when PR2 is written to.
		TMR2=0;
	}

	// This is the main switch statement that actually
	// does the commutation. It also sets up which is the
	// next vph channel to look at for zero crossing. This
	// is used to configure CH0 S+H input channel.
	switch (sector)
	{
		case 0: 	OVDCON=SECTOR0_OVERRIDE;
					adc_channel_config=VPH_BLUE;
					break;

		case 1: 	OVDCON=SECTOR1_OVERRIDE;
					adc_channel_config=VPH_YELLOW;
					break;

		case 2: 	OVDCON=SECTOR2_OVERRIDE;
					adc_channel_config=VPH_RED;
					break;

		case 3: 	OVDCON=SECTOR3_OVERRIDE;
					adc_channel_config=VPH_BLUE;
					break;

		case 4: 	OVDCON=SECTOR4_OVERRIDE;
					adc_channel_config=VPH_YELLOW;
					break;

		case 5: 	OVDCON=SECTOR5_OVERRIDE;
					adc_channel_config=VPH_RED;
					break;
	}
	// When running sensorless, the zero_crossing
	// routine actually moves on the sector number
	// in response to a zero crossing. Otherwise
	// need to increment sector in the correct direction
	// to ensure that the next time the routine is called
	// the system commutates.
	
	if (control_flags.SENSORLESS==FALSE)
	{
		if (control_flags.ACQUIRE1==FALSE)
		{
			if (control_flags.DIR==FORWARDS)
			{
				if (sector==5) sector=0;
				else 				sector++;
			}
			else
			{
				if (sector==0) sector=5;
				else 				sector--;
			}
		}
	}

	// When running sensorless need to reconfigure ADC to 
	// look at correct vph channel and initialize several 
	// variables in zero_crossing routine. 
	// This is triggered by ADCCONFIG flag being set.
	// Also need to disable T2 interrupt as zero crossing
	// routine to load up next commutation instant.

	else
	{
		control_flags.ADCCONFIG=TRUE;
		IEC0bits.T2IE = 0;
	}
	IFS0bits.T2IF = 0;
	return;
}

// check_zero_crossing is used to detect and act upon phase voltage
// zero crossings (when BEMF crosses vdc/2)
// It is called during normal running and when starting using 
// acqusition method1.

void check_zero_crossing(void)
{
	static unsigned int previous_sample;
	static unsigned char level_counter;
	static unsigned char blanking_counter;

	static unsigned int half_vdc=0;
	
	unsigned int new_timestamp;
	
	// If a commutation just occured which reconfigured
	// ADC to look at next vph feedack, need to clear
	// previous sample and level counter as well as
	// returning without checking for crossing and clearing
	// the relevant flags.
	// Also load up blanking counter to ignore first 
	// few samples to reject false crossings due to 
	// diode action at the end of the demag period
	// Finally determine whether looking for RISING or FALLING X

	if (control_flags.ADCCONFIG==TRUE)
	{
		control_flags.ADCCONFIG=FALSE;
		previous_sample=0;
		level_counter=0;
		control_flags.LEVEL=FALSE;
		control_flags.ZERO_CROSS=FALSE;
		blanking_counter=(unsigned char)user_parameters_RAM[32];
		// Decide whether rising or falling edge detect
		if (control_flags.DIR==FORWARDS)
		{
			if ((sector % 2) == 0)	control_flags2.FALLING_EDGE=TRUE;
			else							control_flags2.FALLING_EDGE=FALSE;
		}
		else

⌨️ 快捷键说明

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