Ich bin neu in der C-Programmierung. Ich brauche Ihre Hilfe, um einige bestimmte Zeilen in einem Codesegment für die sensorgesteuerte Steuerung eines bürstenlosen Gleichstrommotors zu verstehen. Es wurde für eine 16-Bit-MCU (dsPIC33FJ32MC710) geschrieben. Dieser bestimmte Abschnitt stammt aus der Interrupt-Service-Routine und enthält zwei ISRs. Können Sie mir bitte in einfachen Worten die mit gekennzeichneten Zeilen erklären //???
? Was wird dort gemacht und warum? Auch andere Kommentare sind willkommen.
int DesiredSpeed;
int ActualSpeed;
int SpeedError;
long SpeedIntegral = 0, SpeedIntegral_n_1 = 0, SpeedProportional = 0;
long DutyCycle = 0;
unsigned int Kps = 20000; // Proportional gain
unsigned int Kis = 2000; // Integral gain
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt (void)
{
#ifdef CLOSEDLOOP
ActualSpeed = SPEEDMULT/timer3avg;
SpeedError = DesiredSpeed - ActualSpeed;
SpeedProportional = (int)(((long)Kps*(long)SpeedError) >> 15); // ???
SpeedIntegral = SpeedIntegral_n_1 + (int)(((long)Kis*(long)SpeedError) >> 15); //???
SpeedIntegral_n_1 = SpeedIntegral;
DutyCycle = SpeedIntegral + SpeedProportional;
PDC1 = (int)(((long)(PTPER*2)*(long)DutyCycle) >> 15); // ??? PWM duty cycle
1PDC2 = PDC1;
PDC3 = PDC1;
#endif // in closed loop algorithm
IFS0bits.T1IF = 0;
}
void __attribute__((interrupt, no_auto_psv)) _IC1Interrupt (void)
{
int Hall_Index;
IFS0bits.IC1IF = 0; // Clear interrupt flag
HallValue = (unsigned int)((PORTB >> 1) & 0x0007); // Read halls
if (Flags.Direction)
{
OVDCON = StateTableFwd[HallValue];
Hall_Index = HALL_INDEX_F;
}
else
{
OVDCON = StateTableRev[HallValue];
Hall_Index = HALL_INDEX_R;
}
// The code below is uses TMR3 to calculate the speed of the rotor
if (HallValue == Hall_Index) // has the same position been sensed?
if (polecount++ == POLEPAIRS) //has one mech rev elasped? // ???
{ // yes then read timer 3
timer3value = TMR3;
TMR3 = 0;
timer3avg = ((timer3avg + timer3value) >> 1); // ???
polecount = 1;
}
}
Um in C (und anderen Sprachen, die keine gebrochene Mathematik unterstützen) gebrochene ganze Zahlen zu berechnen, ist es notwendig, solche Tricks anzuwenden. Was Sie wirklich gerne tun würden, ist, zwei 16-Bit-Zahlen zu multiplizieren und die hohen Bits des Produkts beizubehalten.
Der erste Satz von Ausdrücken wandelt 16-Bit-Zahlen in vorzeichenbehaftete 32-Bit-Zahlen um und berechnet dann das 32-Bit-Produkt. Sie verschieben es dann um 15 Bits nach rechts und verwerfen die niedrigstwertigen Bits. Es ist ein bisschen wie bei der Gleitkomma-Mathematik, wenn Sie zwei Mantissen multiplizieren (obwohl die Gleitkomma-Mathematik effizienter durchgeführt werden würde, da nicht berechnet werden muss, was verworfen wird).
Der zweite Ausdruck (polecount++ == POLEPAIRS) hat einen booleschen Wert basierend auf dem Vergleich des Werts der Variablen polecount mit POLEPAIRS. Die Variable polecount wird nachinkrementiert (inkrementiert nach dem Vergleich).
if
Aussage wahr ist?(long)Kis
die Bits der Variablen Kis , die ursprünglich als unsigned int als LSBs definiert waren, und füllt Nullen als die oberen 16 MSBs auf?Diese Linien repräsentieren den Proportional- und Integralanteil der Motorsteuerung.
Der SpeedError wird direkt mit der Kps-Verstärkung multipliziert, und die Kis-Verstärkung multipliziert den SpeedError und addiert ihn zum integralen Ausgang SpeedIntegral_n_1 der letzten Zyklen.
Es sollte später einige Codezeilen geben, die die proportionalen und integralen Terme summieren, um die Motoreingabe zu bestimmen.
Dieses Regelverfahren versucht sicherzustellen, dass die Motordrehzahlregelung stabil ist und nicht schwingt. Das Einstellen der Proportional- und Integralverstärkung wirkt sich auf die Geschwindigkeit und Stabilität der Motorsteuerung aus.
Der >>-Operator ist eine bitweise Verschiebung nach rechts. Das Verschieben aller Bits nach links oder rechts innerhalb einer Binärzahl multipliziert oder dividiert die Zahl mit 2 (pro Verschiebung). Es kann auch vorkommen, dass bestimmte Bits an bestimmte Positionen verschoben werden sollen, möglicherweise um Bits an einem E/A-Port oder die Bits in einem speziellen internen Datenregister auszurichten.
Außerdem werden in einigen dieser Formeln eine oder mehrere Variablen in einen bestimmten Datentyp konvertiert (unter Verwendung eines Präfixes wie (int) oder (long) direkt vor der Zahl).
Für Bitverschiebungsoperatoren siehe: http://www.cprogramming.com/tutorial/bitwise_operators.html
timer3avg = ((timer3avg + timer3value) >> 1);
der Durchschnitt nach der Formel (x+y)/2 berechnet ?int
in a long
zur Multiplikation umwandeln und dann wieder in das Original umwandeln int
?
Adam Lawrence