📄 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, Jorge Zambada, Alex Dumais *
* *
* Filename: ISRs.c *
* Date: 07/23/07 *
* File Version: 5.10 *
* Project: 53 *
* Drawing: 2 *
* *
* Tools used: MPLAB v7.61 C30 Compiler v 3.01 *
* *
* Linker File: p33FJ256MC710.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"
int hall_state, old_hall_state, hall_timestamp, old_hall_timestamp;
int hall_velocity, hall_velocity_overflow;
int acquire2_delay;
void check_zero_crossing(void);
static void current_control(void);
static void acquire_position(void);
extern int ADCBuffer[];
void __attribute__((__interrupt__, no_auto_psv)) _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__, no_auto_psv)) _AddressError(void)
{
DISABLE_FIRING;
// Clear WDT and drive LED4 at 100% Duty
while(1)
{
ClrWdt();
LED4=1;
}
return;
}
void __attribute__((__interrupt__, no_auto_psv)) _StackError(void)
{
unsigned char i;
DISABLE_FIRING;
// Clear WDT and drive LED4 at 50% Duty
while(1)
{
ClrWdt();
LED4=0;
for (i=0;i<255;i++);
LED4=1;
for (i=0;i<255;i++);
}
return;
}
void __attribute__((__interrupt__, no_auto_psv)) _MathError(void)
{
unsigned char i;
DISABLE_FIRING;
// Clear WDT and drive LED4 at 33% Duty
while(1)
{
ClrWdt();
LED4=0;
for (i=0;i<255;i++);
LED4=1;
for (i=0;i<127;i++);
}
return;
}
void __attribute__((__interrupt__, no_auto_psv)) _PWMInterrupt(void)
{
slow_event_count++;
medium_speed_event_count++;
IFS3bits.PWMIF = 0;
return;
}
void __attribute__((__interrupt__, no_auto_psv)) _FLTAInterrupt (void)
{
DISABLE_FIRING;
run_state=FAULT;
if (!trip_state) trip_state=HARDWARE_TRIP;
IFS3bits.FLTAIF = 0;
return;
}
void __attribute__((__interrupt__, no_auto_psv)) _DMA0Interrupt (void)
{
// Clear off interrupt flag
IFS0bits.DMA0IF = 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 (AD1CHS0)
{
case VPH_RED : vph_red=ADCBuffer[0];
AD1CHS0=VPH_YELLOW;
break;
case VPH_YELLOW : vph_yellow=ADCBuffer[0];
AD1CHS0=VPH_BLUE;
break;
case VPH_BLUE : vph_blue=ADCBuffer[0];
AD1CHS0=VPH_RED;
break;
default : AD1CHS0=VPH_RED;
break;
}
}
else
{
vph=ADCBuffer[0];
}
vdc=ADCBuffer[1];
ibus=ADCBuffer[2];
pot=ADCBuffer[3];
// 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))
{
Nop();
Nop();
Nop();
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)
{
AD1CHS0 = 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__, no_auto_psv)) _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__, no_auto_psv)) _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 acquisiton 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -