Technik > Tech-Talk Design & Konzepte
Digitale Steuerung
Sebastian:
Hallo,
Also, das Ganze wird so nicht gehen, da ich die PWM nicht schnell genug kriege. Die Interrupt-Routine hält schon alles auf, obwohl da nicht viel passiert. Werde mal versuche, den Teil in ASM zu machen, der C Compiler macht jedenfalls zu viele anscheinend unnütze Befehle daraus. Unter 555Hz komme ich nicht bei 4,19MHz. Eine PWM Periode dauert 100 Interrupts (womit die Auflösung schon stark eingeschränkt wäre).
Wäre gut, wenn da einer weiterhelfen könnte...
M f G (und frohes Fest)
Sebastian
Stephan G.:
Hi, Folks!
Wie sieht Dein Programm denn aus?
Viel passieren muss eigentlich auch gar nicht. Der Timer-Interrupt könnte auch nur wie ein TICK verarbeitet werden - bzw. eigentlich muss er ja nur einen Zähler beeinflussen, der die Zeitschlitze nummeriert ...
Wichtig ist, dass die normalen Routinen in der Zeit zwischen 2 Timer-Interrupts komplett abgearbeitet werden.
Das ist am Besten in Assembler hinzukriegen!
PLAY LOUD!! :guitar:
Sebastian:
Hallo,
So sieht die Interrupt-Routine aus. Wie man sieht, passiert auch nicht viel. Jedes 100. Mal wird einfach der Zähler hochgezählt und entsprechend dem Wert von "an" das Puls-Pausen-Verhältnis geändert. Kann man auch schön aufm Oszi sehen, das geht also soweit. Der Timer läuft ohne Vorteiler und der Interrupt löst aus, sobald der Timer-Wert von 0x4B erreicht ist (geringere Werte bringen nichts, da es nicht schneller wird).
4,19 Mhz / 0x4b / 100 = 559 Hz
ISR (TIMER0_COMP_vect)
{
zaehler ++;
if (zaehler == 100) //100 => 1 Periode
{
zaehler = 0;
}
if (an > zaehler)
{
PORTB |= (1 << PB3);
}
else
{
PORTB &= ~(1 << PB3);
}
}
Aus dem bisschen Code macht der Compiler 56 ASM Befehle, wobei mehr als die Hälfte davon aus zeitraubenden Pushs und Pops besteht, alles also suboptimal.
M f G
Sebastian
Stephan G.:
Hi, Folks!
Kannste mal zeigen, was der Compiler draus macht?
Die Struktur des Programms kann man noch etwas effizienter gestalten, wenn man auf die ELSE verzichtet.
Ich würde zu Beginn der Periode den Ausgang einschalten und mit dem PWM-Wert wieder ausschalten. Die IF muss dann eigentlich nur "Vergleichen" und nicht "Verzweigen"...
Interessant wäre auch, wie die Funktion aufgerufen wird und wo die "Hauptschleife" läuft ...
PLAY LOUD!! :guitar:
Sebastian:
ISR (TIMER0_COMP_vect)
{
zaehler ++;
if (zaehler == 100) //100 => 1 Periode
{
zaehler = 0;
}
if (an > zaehler)
{
PORTB |= (1 << PB3);
}
else
{
PORTB &= ~(1 << PB3);
}
}
void init(void)
{
DDRB = 0xff; //PORTA Ausgang
OCR0 = 0x4B; //Compare-Wert
TCCR0 = 0x09; //Prescaler
TIMSK = (1 << OCIE0); //Timer0 Interrupt an
}
int main (void)
{
init ();
sei(); //globaler Interrupt an
an = 50; //50% Helligkeit
for (;;){}
}
Hallo, so sieht der Rest aus, also nicht viel dran.
21: {
+00000047: 921F PUSH R1 Push register on stack
+00000048: 920F PUSH R0 Push register on stack
+00000049: B60F IN R0,0x3F In from I/O location
+0000004A: 920F PUSH R0 Push register on stack
+0000004B: 2411 CLR R1 Clear Register
+0000004C: 932F PUSH R18 Push register on stack
+0000004D: 933F PUSH R19 Push register on stack
+0000004E: 938F PUSH R24 Push register on stack
+0000004F: 939F PUSH R25 Push register on stack
+00000050: 93CF PUSH R28 Push register on stack
+00000051: 93DF PUSH R29 Push register on stack
+00000052: B7CD IN R28,0x3D In from I/O location
+00000053: B7DE IN R29,0x3E In from I/O location
22: zaehler ++;
+00000054: 91800060 LDS R24,0x0060 Load direct from data space
+00000056: 5F8F SUBI R24,0xFF Subtract immediate
+00000057: 93800060 STS 0x0060,R24 Store direct to data space
23: if (zaehler == 100) //100 => 1 Periode
+00000059: 91800060 LDS R24,0x0060 Load direct from data space
+0000005B: 3684 CPI R24,0x64 Compare with immediate
+0000005C: F411 BRNE PC+0x03 Branch if not equal
25: zaehler = 0;
+0000005D: 92100060 STS 0x0060,R1 Store direct to data space
27: if (an > zaehler)
+0000005F: 91800060 LDS R24,0x0060 Load direct from data space
+00000061: 2F28 MOV R18,R24 Copy register
+00000062: 2733 CLR R19 Clear Register
+00000063: 91800061 LDS R24,0x0061 Load direct from data space
+00000065: 91900062 LDS R25,0x0062 Load direct from data space
+00000067: 1728 CP R18,R24 Compare
+00000068: 0739 CPC R19,R25 Compare with carry
+00000069: F434 BRGE PC+0x07 Branch if greater or equal, signed
29: PORTB |= (1 << PB3);
+0000006A: 91800038 LDS R24,0x0038 Load direct from data space
+0000006C: 6088 ORI R24,0x08 Logical OR with immediate
+0000006D: 93800038 STS 0x0038,R24 Store direct to data space
+0000006F: C005 RJMP PC+0x0006 Relative jump
33: PORTB &= ~(1 << PB3);
+00000070: 91800038 LDS R24,0x0038 Load direct from data space
+00000072: 7F87 ANDI R24,0xF7 Logical AND with immediate
+00000073: 93800038 STS 0x0038,R24 Store direct to data space
+00000075: 91DF POP R29 Pop register from stack
+00000076: 91CF POP R28 Pop register from stack
+00000077: 919F POP R25 Pop register from stack
+00000078: 918F POP R24 Pop register from stack
+00000079: 913F POP R19 Pop register from stack
+0000007A: 912F POP R18 Pop register from stack
+0000007B: 900F POP R0 Pop register from stack
+0000007C: BE0F OUT 0x3F,R0 Out to I/O location
+0000007D: 900F POP R0 Pop register from stack
+0000007E: 901F POP R1 Pop register from stack
+0000007F: 9518 RETI Interrupt return
Das macht der Compiler aus der Interruptroutine.
Ich gebs zumindest mal im Moment auf mit PWM. Wenn man sich den Triaxis anguckt, dann sieht man vorne 10 ICs mit verschiedenen Rs. Das sieht für mich nach Latches / DAs aus.
http://www.student.oulu.fi/~kemppaja/Triaxis%20001.jpg
Leider ist genau der Teil im Plan von tubefreak.com nicht dokumentiert, der Rest des Plans deutet aber auch darauf hin.
Ich werde es auf jedem Fall auch mal so probieren. Ein PCF8574 kostet gerade mal 1,7€. Paar Rs dabei und das wars. Das sind vll 2,5€ mehr pro LDR, dafür kann ich mir aber viel Aufwand im Programm sparen und kann mir sicher sein, dass ich damit nie Zeitprobleme kriege... einfach nen Wert reinschreiben und nicht mehr drum kümmern.
M f G
Sebastian
Navigation
[0] Themen-Index
[#] Nächste Seite
[*] Vorherige Sete
Zur normalen Ansicht wechseln