在HVACI_Sensorless.C程序中定义了一下这些状态机函数
// State Machine function prototypes
//————————————
// Alpha states
void A0(void); //state A0
void B0(void); //state B0
void C0(void); //state C0
// A branch states
void A1(void); //state A1
void A2(void); //state A2
void A3(void); //state A3
// B branch states
void B1(void); //state B1
void B2(void); //state B2
void B3(void); //state B3
// C branch states
void C1(void); //state C1
void C2(void); //state C2
void C3(void); //state C3
// Variable declarations
void (*Alpha_State_Ptr)(void); // Base States pointer
void (*A_Task_Ptr)(void); // State pointer A branch
void (*B_Task_Ptr)(void); // State pointer B branch
void (*C_Task_Ptr)(void); // State pointer C branch
// Timing sync for background loops// Timer period definitions found in device specific PeripheralHeaderIncludes.h
CpuTimer0Regs.PRD.all = mSec1; // A tasks
CpuTimer1Regs.PRD.all = mSec5; // B tasks
CpuTimer2Regs.PRD.all = mSec50; // C tasks
// Tasks State-machine init
Alpha_State_Ptr = &A0;// ;
A_Task_Ptr = &A1;
B_Task_Ptr = &B1;
C_Task_Ptr = &C1;
//=================================================================================
// STATE-MACHINE SEQUENCING AND SYNCRONIZATION FOR SLOW BACKGROUND TASKS
//=================================================================================
//——————————— FRAMEWORK ————————————-
void A0(void)
{
// loop rate synchronizer for A-tasks
if(CpuTimer0Regs.TCR.bit.TIF == 1)
{
CpuTimer0Regs.TCR.bit.TIF = 1; // clear flag
//———————————————————–
(*A_Task_Ptr)(); // jump to an A Task (A1,A2,A3,…)
//———————————————————–
VTimer0[0]++; // virtual timer 0, instance 0 (spare)
SerialCommsTimer++;
}
Alpha_State_Ptr = &B0; // Comment out to allow only A tasks
}
void B0(void)
{
// loop rate synchronizer for B-tasks
if(CpuTimer1Regs.TCR.bit.TIF == 1)
{
CpuTimer1Regs.TCR.bit.TIF = 1; // clear flag
//———————————————————–
(*B_Task_Ptr)(); // jump to a B Task (B1,B2,B3,…)
//———————————————————–
VTimer1[0]++; // virtual timer 1, instance 0 (spare)
}
Alpha_State_Ptr = &C0; // Allow C state tasks
}
void C0(void)
{
// loop rate synchronizer for C-tasks
if(CpuTimer2Regs.TCR.bit.TIF == 1)
{
CpuTimer2Regs.TCR.bit.TIF = 1; // clear flag
//———————————————————–
(*C_Task_Ptr)(); // jump to a C Task (C1,C2,C3,…)
//———————————————————–
VTimer2[0]++; //virtual timer 2, instance 0 (spare)
}
Alpha_State_Ptr = &A0; // Back to State A0
}
//=================================================================================
// A – TASKS (executed in every 1 msec)
//=================================================================================
//——————————————————–
void A1(void) // SPARE (not used)
//——————————————————–
{
if(EPwm1Regs.TZFLG.bit.OST==0x1)
TripFlagDMC=1; // Trip on DMC (halt and IPM fault trip )
//——————-
//the next time CpuTimer0 'counter' reaches Period value go to A2
A_Task_Ptr = &A2;
//——————-
}
//—————————————————————–
void A2(void) // SPARE (not used)
//—————————————————————–
{
//——————-
//the next time CpuTimer0 'counter' reaches Period value go to A3
A_Task_Ptr = &A3;
//——————-
}
//—————————————–
void A3(void) // SPARE (not used)
//—————————————–
{
//—————–
//the next time CpuTimer0 'counter' reaches Period value go to A1
A_Task_Ptr = &A1;
//—————–
}
//=================================================================================
// B – TASKS (executed in every 5 msec)
//=================================================================================
//———————————– USER —————————————-
//—————————————-
void B1(void) // Toggle GPIO-00
//—————————————-
{
//—————–
//the next time CpuTimer1 'counter' reaches Period value go to B2
B_Task_Ptr = &B2; //—————–
}
//—————————————-
void B2(void) // SPARE
//—————————————-
{
//—————–
//the next time CpuTimer1 'counter' reaches Period value go to B3
B_Task_Ptr = &B3;
//—————–
}
//—————————————-
void B3(void) // SPARE
//—————————————-
{
//—————–
//the next time CpuTimer1 'counter' reaches Period value go to B1
B_Task_Ptr = &B1; //—————–
}
//=================================================================================
// C – TASKS (executed in every 50 msec)
//=================================================================================
//——————————— USER ——————————————
//—————————————-
void C1(void) // Toggle GPIO-34//—————————————-
{
if(EPwm1Regs.TZFLG.bit.OST==0x1) // TripZ for PWMs is low (fault trip)
{ TripFlagDMC=1; }
GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // Turn on/off LD3 on the controlCARD
//—————–
//the next time CpuTimer2 'counter' reaches Period value go to C2
C_Task_Ptr = &C2; //—————–
}
//—————————————-
void C2(void) // SPARE
//—————————————-
{
//—————–
//the next time CpuTimer2 'counter' reaches Period value go to C3
C_Task_Ptr = &C3; //—————–
}
//—————————————–
void C3(void) // SPARE
//—————————————–
{
//—————–
//the next time CpuTimer2 'counter' reaches Period value go to C1
C_Task_Ptr = &C1; //—————–
}
之后在main函数的死循环中跳转到Alpha state (A0,B0,…)
// IDLE loop. Just sit and loop forever: for(;;) //infinite loop
{
// State machine entry & exit point
//===========================================================
(*Alpha_State_Ptr)(); // jump to an Alpha state (A0,B0,…)
//===========================================================
}
问题是
1.该程序设置了这么多状态机(ABC三组共12个)是干什么用的?程序员的目的是什么,在最早2812的电机控制程序中只有主中断interrupt void MainISR(void)程序,没有这些状态机。
2.状态机跳转的次数太多跟不上,不知道在有没有文档对其进行说明,在改程序的doc文件夹中没有发现对于状态机的说明,只有一个PDF文档对于电机控制部分的主中断进行了说明
3.这些状态机的表现是在控制28335control card 上的一个红色LED灯的闪烁,但是当我提高主中断的中断频率,增加主中断的运算量时,LED不再闪烁,是为什么?
4.如何判断主中断(PieVectTable.EPWM1_INT = &MainISR;)中的程序代码是否被完全执行?
例如:将PWM1的主中断频率定为20K,#define ISR_FREQUENCY 20
主中断里的电机控制程序进行了大量的增幅,运算量较大,如何证明PWM1的主中断内的代码在0.05ms内全部执行完
HH Y:
状态机其实就是多任务分时,比如要闪烁LED,要监视按键操作,要检测温度,要控制散热风扇转速,要刷液晶屏显示……一般这些东西不需要很快的运行速度,甚至一些还要延时,那么就分成多个独立函数入口,每个入口就是一个状态机,CPU在大循环中轮询这些状态机,比如有的状态机正在延时中,如LED闪烁,此时CPU绝对不能在状态机中简单的用死循环等待,如果LED1秒闪一次,你难道能在那里死循环1秒,其他事都不干了?所以,如果发现LED还在延时中,CPU就直接跳到其他状态机去。
TI的例程预留了很多状态机,但根据例程的复杂性,一些没用到是正常的,为保持所有例程代码的一致性,留空一些状态机也是正常的,不用去纠结。
状态机就是在主进程中运行的,随时可能被各种中断打断。如果你的中断频率很高,中断处理时间很长,那么基本上所有的时间都在处理中断,状态机没有机会执行是必然的。
判断中断是否被完整执行,应该有中断溢出标志之类的吧?这个不大清楚,反正TI的例程是不能直接用的,他的中断频率居然是PWM频率,而控制步进电机的PWM频率我需要16K以上,需要DAC转换的,则设置为100K以上,而电机处理过程极其复杂,而且有多个电机要处理,根本不可能那么快完成,所以我把电机处理程序放在主循环中,其他状态机采用分时方式,主循环大概能实现8k的频率,即电机运行速度可以按8K计算,而状态机则分时,比如有10个状态机,则每个状态机的频率是0.8k。当然,如果对时间准确度要求高,则还是要考虑用其他中断源。比如一组PWM用于控制电机,另一组PWM用于产生中断
在HVACI_Sensorless.C程序中定义了一下这些状态机函数
// State Machine function prototypes
//————————————
// Alpha states
void A0(void); //state A0
void B0(void); //state B0
void C0(void); //state C0
// A branch states
void A1(void); //state A1
void A2(void); //state A2
void A3(void); //state A3
// B branch states
void B1(void); //state B1
void B2(void); //state B2
void B3(void); //state B3
// C branch states
void C1(void); //state C1
void C2(void); //state C2
void C3(void); //state C3
// Variable declarations
void (*Alpha_State_Ptr)(void); // Base States pointer
void (*A_Task_Ptr)(void); // State pointer A branch
void (*B_Task_Ptr)(void); // State pointer B branch
void (*C_Task_Ptr)(void); // State pointer C branch
// Timing sync for background loops// Timer period definitions found in device specific PeripheralHeaderIncludes.h
CpuTimer0Regs.PRD.all = mSec1; // A tasks
CpuTimer1Regs.PRD.all = mSec5; // B tasks
CpuTimer2Regs.PRD.all = mSec50; // C tasks
// Tasks State-machine init
Alpha_State_Ptr = &A0;// ;
A_Task_Ptr = &A1;
B_Task_Ptr = &B1;
C_Task_Ptr = &C1;
//=================================================================================
// STATE-MACHINE SEQUENCING AND SYNCRONIZATION FOR SLOW BACKGROUND TASKS
//=================================================================================
//——————————— FRAMEWORK ————————————-
void A0(void)
{
// loop rate synchronizer for A-tasks
if(CpuTimer0Regs.TCR.bit.TIF == 1)
{
CpuTimer0Regs.TCR.bit.TIF = 1; // clear flag
//———————————————————–
(*A_Task_Ptr)(); // jump to an A Task (A1,A2,A3,…)
//———————————————————–
VTimer0[0]++; // virtual timer 0, instance 0 (spare)
SerialCommsTimer++;
}
Alpha_State_Ptr = &B0; // Comment out to allow only A tasks
}
void B0(void)
{
// loop rate synchronizer for B-tasks
if(CpuTimer1Regs.TCR.bit.TIF == 1)
{
CpuTimer1Regs.TCR.bit.TIF = 1; // clear flag
//———————————————————–
(*B_Task_Ptr)(); // jump to a B Task (B1,B2,B3,…)
//———————————————————–
VTimer1[0]++; // virtual timer 1, instance 0 (spare)
}
Alpha_State_Ptr = &C0; // Allow C state tasks
}
void C0(void)
{
// loop rate synchronizer for C-tasks
if(CpuTimer2Regs.TCR.bit.TIF == 1)
{
CpuTimer2Regs.TCR.bit.TIF = 1; // clear flag
//———————————————————–
(*C_Task_Ptr)(); // jump to a C Task (C1,C2,C3,…)
//———————————————————–
VTimer2[0]++; //virtual timer 2, instance 0 (spare)
}
Alpha_State_Ptr = &A0; // Back to State A0
}
//=================================================================================
// A – TASKS (executed in every 1 msec)
//=================================================================================
//——————————————————–
void A1(void) // SPARE (not used)
//——————————————————–
{
if(EPwm1Regs.TZFLG.bit.OST==0x1)
TripFlagDMC=1; // Trip on DMC (halt and IPM fault trip )
//——————-
//the next time CpuTimer0 'counter' reaches Period value go to A2
A_Task_Ptr = &A2;
//——————-
}
//—————————————————————–
void A2(void) // SPARE (not used)
//—————————————————————–
{
//——————-
//the next time CpuTimer0 'counter' reaches Period value go to A3
A_Task_Ptr = &A3;
//——————-
}
//—————————————–
void A3(void) // SPARE (not used)
//—————————————–
{
//—————–
//the next time CpuTimer0 'counter' reaches Period value go to A1
A_Task_Ptr = &A1;
//—————–
}
//=================================================================================
// B – TASKS (executed in every 5 msec)
//=================================================================================
//———————————– USER —————————————-
//—————————————-
void B1(void) // Toggle GPIO-00
//—————————————-
{
//—————–
//the next time CpuTimer1 'counter' reaches Period value go to B2
B_Task_Ptr = &B2; //—————–
}
//—————————————-
void B2(void) // SPARE
//—————————————-
{
//—————–
//the next time CpuTimer1 'counter' reaches Period value go to B3
B_Task_Ptr = &B3;
//—————–
}
//—————————————-
void B3(void) // SPARE
//—————————————-
{
//—————–
//the next time CpuTimer1 'counter' reaches Period value go to B1
B_Task_Ptr = &B1; //—————–
}
//=================================================================================
// C – TASKS (executed in every 50 msec)
//=================================================================================
//——————————— USER ——————————————
//—————————————-
void C1(void) // Toggle GPIO-34//—————————————-
{
if(EPwm1Regs.TZFLG.bit.OST==0x1) // TripZ for PWMs is low (fault trip)
{ TripFlagDMC=1; }
GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // Turn on/off LD3 on the controlCARD
//—————–
//the next time CpuTimer2 'counter' reaches Period value go to C2
C_Task_Ptr = &C2; //—————–
}
//—————————————-
void C2(void) // SPARE
//—————————————-
{
//—————–
//the next time CpuTimer2 'counter' reaches Period value go to C3
C_Task_Ptr = &C3; //—————–
}
//—————————————–
void C3(void) // SPARE
//—————————————–
{
//—————–
//the next time CpuTimer2 'counter' reaches Period value go to C1
C_Task_Ptr = &C1; //—————–
}
之后在main函数的死循环中跳转到Alpha state (A0,B0,…)
// IDLE loop. Just sit and loop forever: for(;;) //infinite loop
{
// State machine entry & exit point
//===========================================================
(*Alpha_State_Ptr)(); // jump to an Alpha state (A0,B0,…)
//===========================================================
}
问题是
1.该程序设置了这么多状态机(ABC三组共12个)是干什么用的?程序员的目的是什么,在最早2812的电机控制程序中只有主中断interrupt void MainISR(void)程序,没有这些状态机。
2.状态机跳转的次数太多跟不上,不知道在有没有文档对其进行说明,在改程序的doc文件夹中没有发现对于状态机的说明,只有一个PDF文档对于电机控制部分的主中断进行了说明
3.这些状态机的表现是在控制28335control card 上的一个红色LED灯的闪烁,但是当我提高主中断的中断频率,增加主中断的运算量时,LED不再闪烁,是为什么?
4.如何判断主中断(PieVectTable.EPWM1_INT = &MainISR;)中的程序代码是否被完全执行?
例如:将PWM1的主中断频率定为20K,#define ISR_FREQUENCY 20
主中断里的电机控制程序进行了大量的增幅,运算量较大,如何证明PWM1的主中断内的代码在0.05ms内全部执行完
xin qi1:
回复 HH Y:
感谢大侠的讲解,我只是控制一个感应电机调速,测试些奇怪的算法,任务极为单一,所以TI的程序还是很合适的,本身也不需要其他的监视操作,那我就把那些状态机关了算了,只留下TI的PWM中断,把算法放在这个PWM主中断里面算了。
以前用MEGA16单片机确实是用TIMER的中断精确采样,每次中断改变PWM的比较寄存器。