Ich habe eine Problem mit einem Xmega128A4U.
Ich habe einen Servoport definiert,
Servoport = PortB, 0, iData;
ServoChans = 2, Positive;
ServoNeutral = 1.5, Timer_D0;
ServoSwing = 0.5;
Dazu nutze ich noch den Timer TCE0 um alle 5ms einen Interrupt aufzurufen:
TCE0PERL := $40;
TCE0PERH := $9C;
TCE0CTRLA := $03;
TCE0INTCTRLA := $02;
Alle 5ms wird so
Interrupt TCE0_INTOVF; aufgerufen
Das klappt auch, aber sobald ich in den Timer aktiviere spinnen die Servos, sie zittern heftig, fahren langsam auf eine Endstellung um dann schnell wieder zurück zu fahren. Ca. alle 5 Sekunden wiederholt sich das.
Ich habe alle möglichen Kombinationen von Timern hier schon probiert, ohne Erfolg.
Die Servos hängen an PB.0 und PB.1
Ich habe mal ein Minimalprogramm geschrieben, dass dieses Verhalten auslöst.
Es konfiguriert die Ports, setzt einen Timer in Gang und ruft im Interrupt ein paar Bytes über SPI_C ab. Das bringt die Servos schon durcheinander.
Schalte ich den Timer ab, stehen die Servos ruhig.
Ohne Timer kann ich über SPI soviel abrufen wie ich will, das beeinflusst die Servos nicht.
program testxmega;
{$NOSHADOW}
Device = xmega128A4U, VCC=3.3;
Import SysTick, ServoPort, SPI_C;
Define
OSCtype = int32MHz, PLLmul=4, prescB=1, prescC=1;
SysTick = 10; {msec}
StackSize = $0064, iData;
FrameSize = $0064, iData;
ServoPort = PortB, 0, iData; {use Portx, startbit n, RAMpage}
ServoChans = 2, positive; {channel count, pulse polarity}
ServoNeutral = 1.5, Timer_D0; {msec zero pulse width, Timer used}
SPIorderC = MSB;
SPImodeC = 0; //3;
SPIprescC = 3; // presc = 0..3 -> 4/16/64/128
SPI_SSC = none; // don’t use SS pin as chipselect
Implementation
{$IDATA}
var
LED1[@PORTD, 5] : Bit;
MMA655X_CS[@PORTD, 2] : Bit; // Anpassen!
b1, b2: Byte;
function MMA655x_VALUE : Word;
var w1, temp : word;
begin
b1:= %00110000;
b2:= %00001101;
excl(MMA655X_CS);
spioutbyteC(b1);
spioutbyteC(b2);
incl(MMA655X_CS);
udelay(2);
excl(MMA655X_CS);
b1:= spiinoutbyteC($80); // Dummy read, Adress 0 mit Parity Bit 7 gesetzt
b2:= spiinoutbyteC(0);
incl(MMA655X_CS);
// Ein Word draus machen...
temp:= word(b1);
temp:= (temp shl 8) + word(b2);
// Bits sortieren...
w1:= (temp shl 2) AND $0FFF; //%0000111111111111;
w1:= w1 OR word(b1 shr 6);
return(w1);
end;
Interrupt TCE0_INTOVF;
begin
toggle(led1);
MMA655x_VALUE;
end;
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
DDRA:= %11100000; // 0= input, 1= Output
PortA:= %00000000; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
DDRB:= %00000011; // 0= input, 1= Output
PortB:= %00000000; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
DDRC:= %11110000; // 0= input, 1= Output
PortC:= %00000000; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
DDRD:= %00111111; // 0= input, 1= Output
PortD:= %00011110; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
// Timer setzen für 5 ms Overflow
TCE0PERL := $40;
TCE0PERH := $9C;
TCE0CTRLA := $03;
TCE0INTCTRLA := $02;
EnableInts($87);
loop
nop;
nop;
endloop;
end testxmega.
Ich habe einen Servoport definiert,
Servoport = PortB, 0, iData;
ServoChans = 2, Positive;
ServoNeutral = 1.5, Timer_D0;
ServoSwing = 0.5;
Dazu nutze ich noch den Timer TCE0 um alle 5ms einen Interrupt aufzurufen:
TCE0PERL := $40;
TCE0PERH := $9C;
TCE0CTRLA := $03;
TCE0INTCTRLA := $02;
Alle 5ms wird so
Interrupt TCE0_INTOVF; aufgerufen
Das klappt auch, aber sobald ich in den Timer aktiviere spinnen die Servos, sie zittern heftig, fahren langsam auf eine Endstellung um dann schnell wieder zurück zu fahren. Ca. alle 5 Sekunden wiederholt sich das.
Ich habe alle möglichen Kombinationen von Timern hier schon probiert, ohne Erfolg.
Die Servos hängen an PB.0 und PB.1
Ich habe mal ein Minimalprogramm geschrieben, dass dieses Verhalten auslöst.
Es konfiguriert die Ports, setzt einen Timer in Gang und ruft im Interrupt ein paar Bytes über SPI_C ab. Das bringt die Servos schon durcheinander.
Schalte ich den Timer ab, stehen die Servos ruhig.
Ohne Timer kann ich über SPI soviel abrufen wie ich will, das beeinflusst die Servos nicht.
Code
program testxmega;
{$NOSHADOW}
Device = xmega128A4U, VCC=3.3;
Import SysTick, ServoPort, SPI_C;
Define
OSCtype = int32MHz, PLLmul=4, prescB=1, prescC=1;
SysTick = 10; {msec}
StackSize = $0064, iData;
FrameSize = $0064, iData;
ServoPort = PortB, 0, iData; {use Portx, startbit n, RAMpage}
ServoChans = 2, positive; {channel count, pulse polarity}
ServoNeutral = 1.5, Timer_D0; {msec zero pulse width, Timer used}
SPIorderC = MSB;
SPImodeC = 0; //3;
SPIprescC = 3; // presc = 0..3 -> 4/16/64/128
SPI_SSC = none; // don’t use SS pin as chipselect
Implementation
{$IDATA}
var
LED1[@PORTD, 5] : Bit;
MMA655X_CS[@PORTD, 2] : Bit; // Anpassen!
b1, b2: Byte;
function MMA655x_VALUE : Word;
var w1, temp : word;
begin
b1:= %00110000;
b2:= %00001101;
excl(MMA655X_CS);
spioutbyteC(b1);
spioutbyteC(b2);
incl(MMA655X_CS);
udelay(2);
excl(MMA655X_CS);
b1:= spiinoutbyteC($80); // Dummy read, Adress 0 mit Parity Bit 7 gesetzt
b2:= spiinoutbyteC(0);
incl(MMA655X_CS);
// Ein Word draus machen...
temp:= word(b1);
temp:= (temp shl 8) + word(b2);
// Bits sortieren...
w1:= (temp shl 2) AND $0FFF; //%0000111111111111;
w1:= w1 OR word(b1 shr 6);
return(w1);
end;
Interrupt TCE0_INTOVF;
begin
toggle(led1);
MMA655x_VALUE;
end;
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
DDRA:= %11100000; // 0= input, 1= Output
PortA:= %00000000; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
DDRB:= %00000011; // 0= input, 1= Output
PortB:= %00000000; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
DDRC:= %11110000; // 0= input, 1= Output
PortC:= %00000000; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
DDRD:= %00111111; // 0= input, 1= Output
PortD:= %00011110; // 1 = Pullup!! // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro
// Timer setzen für 5 ms Overflow
TCE0PERL := $40;
TCE0PERH := $9C;
TCE0CTRLA := $03;
TCE0INTCTRLA := $02;
EnableInts($87);
loop
nop;
nop;
endloop;
end testxmega.