📄 isrs.c
字号:
/**********************************************************************
* 程序说明
*
* 该文件包含所有的中断服务程序(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)
{
// 该中断为缺省中断,如果中断向量没有定义,则程序跳转到这里执行
DISABLE_FIRING;
while(1);
}
void __attribute__((__interrupt__)) _AddressError(void)
{
DISABLE_FIRING;
//清看门狗WDT
while(1)
{
ClrWdt();
}
return;
}
void __attribute__((__interrupt__)) _StackError(void)
{
unsigned char i;
DISABLE_FIRING;
//清看门狗WDT
while(1)
{
ClrWdt();
}
return;
}
void __attribute__((__interrupt__)) _MathError(void)
{
unsigned char i;
DISABLE_FIRING;
//清看门狗WDT
while(1)
{
ClrWdt();
}
return;
}
//PWM中断服务程序
void __attribute__((__interrupt__)) _PWMInterrupt(void)
{
slow_event_count++;
medium_speed_event_count++;
IFS2bits.PWMIF = 0;
return;
}
//故障A中断服务程序
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;
}
//ADC中断服务程序
void __attribute__((__interrupt__)) _ADCInterrupt (void)
{
//清中断标志
IFS0bits.ADIF = 0;
// 从ADC缓冲取得结果,并把它们付给相应的变量;
// 可以得到测量值为单相电压,DC总线电压,DC总线电流和VR2的值;
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;
// 如果存在故障,则设定run_state为FAULT,并返回。
if (trip_state)
{
run_state=FAULT;
return;
}
//如果有故障,检查是否是过压和过流
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;
}
//根据最新的采样值作电流控制
current_control();
//若须采样不同相的电压,要重新配置ADC
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 中断服务子程序
void __attribute__((__interrupt__)) _U1TXInterrupt(void)
{
IFS0bits.U1TXIF = 0; //清中断标志
}
void __attribute__((__interrupt__)) _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0; //清中断标志
*RXPtr = U1RXREG; //取值
if (*RXPtr == CR)
{control_flags2.CheckRX = 1;RXPtr = &InData[0];}
else *RXPtr++;
}
#endif
// Timer 1中断服务程序,用于检测过零事件
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中断服务程序,用于作输出比较,配置电压测量和过零
void __attribute__((__interrupt__)) _T2Interrupt(void)
{
// 采用方法1获得
if (control_flags.ACQUIRE1)
{
//设定ADCCONFIG标志位,以便过零程序初始化
control_flags.ADCCONFIG=TRUE;
//如果在上一次sector没有侦测到合法得过零点,重新初始化acquire和check
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--;
}
}
}
//ACQUIRE1模式使用后得首次中断
if (control_flags2.ACQUIRE1_REQUEST)
{
control_flags2.ACQUIRE1_REQUEST=FALSE;
control_flags.ACQUIRE1=TRUE;
//设定ADCCONFIG标志位,以便下一次过零程序初始化
control_flags.ADCCONFIG=TRUE;
check_counter=8;
acquire_counter=0;
#ifdef DEBUG
asm("bclr LATD,#15");
asm("bclr LATG,#3");
asm("bclr LATG,#1");
indx=0;
#endif
}
//从获取模式2到无刷模式(sensorless),设定无刷标志并给check_counter赋值。
if (control_flags.SWAP==TRUE)
{
control_flags.SENSORLESS=TRUE;
control_flags.SWAP=FALSE;
check_counter=6;
}
//如果check_counter大于0,check_counter减1
if (check_counter) check_counter--;
//如果不是正常无刷状态运行,给PR2赋值。
if (control_flags.SENSORLESS==FALSE)
{
//给PR2赋新值
PR2=new_PR2;
//清TMR2,以保证在写PR2时不会忽略TMR2=PR2事件产生
TMR2=0;
}
#ifdef DEBUG
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
//设定下一个vph通道并查看过零
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;
}
//确定sector值,以使系统能正确转向
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--;
}
}
}
//设定ADCCONFIG标志位,以便配置ADC找到正确得vph通道,并初始化相应得变量;然后禁止T2中断
else
{
control_flags.ADCCONFIG=TRUE;
IEC0bits.T2IE = 0;
}
IFS0bits.T2IF = 0;
return;
}
//Timer 3 中断服务程序,用作制动开关,中断产生时开关关闭
void __attribute__((__interrupt__)) _T3Interrupt(void)
{
IFS0bits.T3IF = 0;
IEC0bits.T3IE = 0;
return;
}
//过零检测子程序,用于检测相电压过零(当BEMF过vdc/2)
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;
// 如果有换向发生,须清以前得采样(previous_sample)和幅值数(level_counter)
// 同时清相应得标志位;放置新的blanking counter值,确定是否是上升(RISING)还是下降(FALLING)沿
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[32];
//是否是上升(RISING)还是下降(FALLING)沿
if (control_flags.DIR==FORWARDS)
{
if ((sector % 2) == 0) control_flags2.FALLING_EDGE=TRUE;
else control_flags2.FALLING_EDGE=FALSE;
}
else
{
if ((sector % 2) == 0) control_flags2.FALLING_EDGE=FALSE;
else control_flags2.FALLING_EDGE=TRUE;
}
return;
}
if (blanking_counter > 0)
{
blanking_counter--;
return;
}
// 防止产生第二次过零
if (control_flags.ZERO_CROSS==TRUE)
return;
half_vdc = ((half_vdc + (vdc>>1)) >> 1);
// 用level_counter变量及标志位保证过零侦测准确,
// 在实际的过零检测之前,vph必须是在上面(下降沿)或下面(上升沿)
if (level_counter==(unsigned char)user_parameters[33])
{
control_flags.LEVEL=TRUE;
}
if (control_flags2.FALLING_EDGE)
{
if ((level_counter < (unsigned char)user_parameters[33]) && (vph > half_vdc))
{
level_counter++;
}
if ((level_counter > 0) && (vph <= half_vdc))
{
level_counter--;
}
}
else
{
if ((level_counter < (unsigned char)user_parameters[33]) && (vph < half_vdc))
{
level_counter++;
}
if ((level_counter > 0) && (vph >= half_vdc))
{
level_counter--;
}
}
//三相定义如下:
// Index 0 = 红
// Index 1 = 黄
// Index 2 = 蓝
// Sector 0,3 = 蓝相过零
// Sector 1,4 = 黄相过零
// Sector 2,5 = 红相过零
if (control_flags.LEVEL==TRUE)
{
//合法得过零点
if (((control_flags2.FALLING_EDGE) && (previous_sample <= half_vdc)\
&& (vph <= half_vdc)) || \
((control_flags2.FALLING_EDGE==FALSE) && (previous_sample >= half_vdc)\
&& (vph >= half_vdc)))
{
//取得QEI的值
new_timestamp=POSCNT;
if (control_flags.DIR == FORWARDS)
{
switch (sector)
{
case 0:
case 3: latest_delta=new_timestamp-previous_timestamps[0];
break;
case 1:
case 4: latest_delta=new_timestamp-previous_timestamps[2];
break;
case 2:
case 5: latest_delta=new_timestamp-previous_timestamps[1];
break;
}
}
else
{
switch (sector)
{
case 0:
case 3: latest_delta=new_timestamp-previous_timestamps[1];
break;
case 1:
case 4: latest_delta=new_timestamp-previous_timestamps[0];
break;
case 2:
case 5: latest_delta=new_timestamp-previous_timestamps[2];
break;
}
}
//计算测量周期,用于速度反馈。
if (sector==0)
{
period_measurement=new_timestamp-previous_timestamps[2];
stall_counter=0;
}
commutation_time=((latest_delta)/2) - phase_advance;
if (commutation_time < 1) commutation_time=1;
check_value=(latest_delta*100)/previous_delta;
if (((check_value > upper_tol) \
|| (check_value < lower_tol)) \
&& (check_counter==0))
{
//如果无刷模式失败,进入获取模式2
DISABLE_FIRING;
IEC0bits.T2IE=FALSE;
control_flags.SENSORLESS=FALSE;
if (user_parameters[31])
{
control_flags.ACQUIRE2=TRUE;
control_flags.ADCCONFIG=TRUE;
control_flags2.RETRY_FLAG=FALSE;
}
else
{
run_state=FAULT;
trip_state=LOST;
}
return;
}
else//合法过零检测
{
//更新sector
if (control_flags.DIR==FORWARDS)
{
if (sector==5) sector=0;
else sector++;
}
else
{
if (sector==0) sector=5;
else sector--;
}
if (control_flags.ACQUIRE1==FALSE)
{
PR2 = (unsigned int) commutation_time;
TMR2=0;
IFS0bits.T2IF = 0;
IEC0bits.T2IE = 1;
PR1=latest_delta<<1;
TMR1=0;
IFS0bits.T1IF = 0;
IEC0bits.T1IE = 1;
}
else
{
// acquire counter加1表示合法得零点产生
acquire_counter++;
#ifdef DEBUG
asm("btg LATD,#15");
#endif
if (acquire_counter > 1)
{
IEC0bits.T2IE = 0;
//设置标志位表明运行于无刷状态
control_flags.ACQUIRE1=FALSE;
control_flags.SENSORLESS=TRUE;
run_state=RUNNING;
check_counter=6;
//设置T2使中断在合适得时候产生
PR2 = (unsigned int) commutation_time;
TMR2=0;
//清中断标志并使能中断
IFS0bits.T2IF = 0;
IEC0bits.T2IE = 1;
#ifdef DEBUG
asm("btg LATG,#1");
#endif
}
}
}
if (control_flags.DIR==FORWARDS)
{
switch (sector)
{
case 0:
case 3: previous_timestamps[0] = new_timestamp;
break;
case 1:
case 4: previous_timestamps[2] = new_timestamp;
break;
case 2:
case 5: previous_timestamps[1] = new_timestamp;
break;
}
}
else
{
switch (sector)
{
case 0:
case 3: previous_timestamps[1] = new_timestamp;
break;
case 1:
case 4: previous_timestamps[0] = new_timestamp;
break;
case 2:
case 5: previous_timestamps[2] = new_timestamp;
break;
}
}
previous_delta=latest_delta;
control_flags.ZERO_CROSS=TRUE;
level_counter=0;
control_flags.LEVEL=FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -