📄 isrs.c
字号:
/**********************************************************************
* *
* 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: 4/21/04 *
* File Version: 4.00 *
* Project: 53 *
* Drawing: 2 *
* *
* Tools used: MPLAB C30 Compiler v 1.20.01 *
* *
* Linker File: p30f4012.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 and drive LED4 at 100% Duty
while(1)
{
ClrWdt();
}
return;
}
void __attribute__((__interrupt__)) _StackError(void)
{
unsigned char i;
DISABLE_FIRING;
// Clear WDT and drive LED4 at 50% Duty
while(1)
{
ClrWdt();
}
return;
}
void __attribute__((__interrupt__)) _MathError(void)
{
unsigned char i;
DISABLE_FIRING;
// Clear WDT and drive LED4 at 33% Duty
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;
}
#ifdef DEVELOPMODE
//UART interrupts
//---------------------------------------------------------------------
void __attribute__((__interrupt__)) _U1TXInterrupt(void)
{
IFS0bits.U1TXIF = 0; // clear interrupt flag
}
void __attribute__((__interrupt__)) _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0; // clear interrupt flag
*RXPtr = U1RXREG;
if (*RXPtr == CR)
{control_flags2.CheckRX = 1;RXPtr = &InData[0];}
else *RXPtr++;
}
#endif
// 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;
#ifdef DEBUG
asm("bclr LATD,#15");
asm("bclr LATG,#3");
asm("bclr LATG,#1");
indx=0;
#endif
}
// 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;
}
#ifdef DEBUG
// These diagnostic signals re-create the Halls
switch (sector)
{
case 0: asm(" bclr LATD,#14");
break;
case 1: asm(" bset LATD,#12");
break;
case 2: asm(" bclr LATD,#6");
break;
case 3: asm(" bset LATD,#14");
break;
case 4: asm(" bclr LATD,#12");
break;
case 5: asm(" bset LATD,#6");
break;
default : sector=0;
}
#endif
// 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -