Forum: Compiler & IDEs Zu großer Code, obwohl winziges Programm


von Daniel B. (inox5) Benutzerseite


Lesenswert?

1
#include <avr/io.h>      //Grundfunktionen
2
#ifndef F_CPU        //Vordefinieren für delay.h
3
#define F_CPU 1000000UL    //Definition von F_CPU in Herz
4
#endif      
5
#include <util/delay.h>    //Warteschleifen
6
#include <stdint.h>
7
8
int main (void)        //Hauptfunktion
9
{              //Anfang der Hauptfuktion
10
DDRB=0b11111111;      //Alles Ausgänge
11
uint16_t a;          //Variable 16Bit
12
char i;            //Zählvariable für die Schleife
13
a=1000;            //Der Impuls soll 1ms lang sein
14
  while(1)      
15
  {
16
  i=50;          //Durch diese Definierung ist die While(i) Schleife immer 1s (50*0,02s) lang
17
    while(i)
18
    {
19
    PORTB=0b11111111;
20
    _delay_us(a);    //Impulslänge
21
    PORTB=0b00000000;
22
    _delay_us(20000-a);  //Hierdurch wird erreicht, dass das Gesamtsignal genau 20ms lang ist
23
    i--;
24
    }
25
  a=a+100;        //Ich will aber das die Impulse länger werden
26
    if(a==2000)      //Da aber ab einer Impulslänge von über 2ms der Servo kaputt gehen kann, wird hier nun die Notbremse gezogen
27
    {
28
    a=1000;
29
    }
30
}
31
return 0;
32
}

Hallo,
Dieser Code hat die Funktion 11 verschiedene Pulslängen an PORTB eines 
Attiny2313 zu bilden. Das Problem ist aber, dass der Code eine Größe 
erreicht die etwa doppelt so groß ist, wie der Speicherplatz eines 
Attiny2313. Die Optimierung 0s ist eingestellt.
Vielleicht könnte mir ja jemand helfen. Danke schonmal im Vorraus.

MfG
Inox

von Uhu U. (uhu)


Lesenswert?

Dein Flashfresser dürfte die float-Arithmetik sein, die von _delay_us 
benötigt wird.

Es wäre besser, wenn du einen Timer programmierst und aus der 
Interruptroutine heraus dem Hauptprogramm signalisierst, daß soundsoviel 
Zeit vergangen ist.

Das geht dann mit reiner int-Arithmetik...

von Ralf W. (Gast)


Lesenswert?

Hallo,

vielleicht wegen diesen Zeilen:
> _delay_us(20000-a);
>a=a+100;

Soweit ich weiss mag die AVR Lib C dies nicht. Dort steht,
das für die _delay_us Funktionen möglichst Konstanten benutzt
werden sollen.
Quote AVR LibC Reference:

In order for these functions to work as intended, compiler optimizations 
must be enabled, and the delay time must be an expression that is a 
known constant at compile-time. If these requirements are not met, the 
resulting delay will be much longer (and basically unpredictable), and 
applications that otherwise do not use floating-point calculations will 
experience severe code bloat by the floating-point library routines 
linked into the application.

Vielleicht solltest du dich mit den Timern der Avr beschäftigen.
Die Tutorials bieten hier einen guten Einstieg.

gruß ralf

von ... (Gast)


Lesenswert?

kenne die Optimierungsstufen nicht, aber kännte es sein, dass in der 
gewähten die Schleifen "abgerollt" werden?

von Kachel - Heinz (Gast)


Lesenswert?

Mit Timer sollte das einfacher gehen.

KH

von Ralf W. (Gast)


Lesenswert?

Hallo,

nö da werden Floating Point Routinen hinzugelinkt.

experience severe code bloat by the floating-point library routines
linked into the application.

gruß ralf

von Daniel B. (inox5) Benutzerseite


Lesenswert?

Ich werde es wohl mit den Timern lösen.
Ich werde wahrscheinlich mit einem Timer eine 100µs Pause schreiben und 
diese einsetzen.

MfG
Inox

von Thomas W. (thomas100)


Lesenswert?

Hi,

du kannst dir ja mal das Assemblerlisting oder das map-file angucken. Da 
siehst du, was dein Programm so aufbläst.

_delay_us ist so deklariert:
1
void _delay_us(double __ms)
und macht auch float-Berechnungen während der Laufzeit, die nicht weg 
optimiert werden können, wenn du keine Konstante übergibst.
Alternativ kannst du mal versuchen, eine eigene for-Schleife zu 
schreiben und _delay_loop_1() oder _delay_loop_2() aufzurufen. Die sind 
in der "delay_basic.h" deklariert.

Oder du nimmst einen Timer und wartest, bis das Overflow-Bit gesetzt 
wird.

Gruß
Thomas

von Andreas K. (ergoproxy)


Lesenswert?

Nimm ne For Schleife und schreib in den Schleifenkörper delay_us(1); und 
lass dann die schleife sooft ablaufen, wie du es brauchst, dann hat das 
delay eine Konstante als Parameter und alle sind happy oder nimm gleich 
den Timer.

von Gast (Gast)


Lesenswert?

Mehr oder weniger sinnvoll. Die for() muss erst bei jedem Durchlauf 
geprüft werden, was auch wieder Zeit braucht. Somit wird das ganze in 
längeren Wartezeiten doch ziemlich ungenau.

von Daniel B. (inox5) Benutzerseite


Lesenswert?

hm aber die idee mit dem "loopen" der delay_us(1) ist gar nicht 
schlecht.
Werde es jetzt vorerst auch mal so machen, mal schaun wie genau das 
wird...

Danke für diesen Tipp!

von Uhu U. (uhu)


Lesenswert?

Wenn du mit delay_us(1) einen Aufruf von _delay_us mit Parameter int 1 
meinst, wirst du wenig Glück haben. _delay_us braucht selbst 
Fließkommaarithmetik.

Aber du könntest die Routinen aus delay_basic.h verwenden...

von yalu (Gast)


Lesenswert?

> hm aber die idee mit dem "loopen" der delay_us(1) ist gar nicht
> schlecht.
> Werde es jetzt vorerst auch mal so machen, mal schaun wie genau das
> wird...

Da die Delay-Zeiten immer Vielfache von 100µs sind, würde ich eine
Schleife um einen _delay_us(100) machen. Das macht die Sache genauer.
Reicht die Genauigkeit immer noch nicht, machst du die 100 um so viel
kleiner, wie es dem Schleifen-Overhead entspricht. Das Argument von
_delay_us darf dabei durchaus auch eine gebrochene Zahl, also z.B.
97.4 sein, wichtig ist nur, dass es konstant ist.

Aber früher oder später solltest du es auch mit Timern versuchen, den
dafür sind diese da, und du hast ja schließlich auch Geld dafür bezahlt.
Der Hauptvorteil ist, dass damit der komplette Zeitbedarf des restlichen
Codes der in den Schleifen deines obigen Programms steht, weitgehend
kompensiert wird. Und solltest du irgendwann noch irgendwelche
Interrupts verwenden, stimmen die Zeiten der _delay_xx-Funktionen
überhaupt nicht mehr, da jede Unterbrechung durch einen Interrupts ihre
Ausführungszeit um den Rechenzeitbedarf des Interrupthandlers
verlängert.

Uhu Uhuhu schrieb:
> Wenn du mit delay_us(1) einen Aufruf von _delay_us mit Parameter int 1
> meinst, wirst du wenig Glück haben. _delay_us braucht selbst
> Fließkommaarithmetik.

Aber nur zur Compilezeit, nicht zur Laufzeit, deswegen stört es nicht.

von Frank S. (Firma: HSCS) (linuxerr)


Lesenswert?

nimm assembler!
so kleine controller sind effektiv nur in assembler zu programmieren. 
nutze den timer wenn er noch zur verfügung steht, das ist sinnvoller als 
zeitschleifen. der code wird dann nicht mehr als 10% des flashs 
beanspruchen.

von Daniel der D. (druesendieb)


Lesenswert?

Halte ich für ein Gerücht. Man kann auch den Maschinencode, den der 
Compiler erzeugt hat, untersuchen und den Code so modifizieren, daß 
möglichst wenig unnötiger Code entsteht.

Das ist weniger Gefummel, als wenn man alles in ASM schreibt und man 
lernt dabei, sehr effizienten C-Code zu schreiben und nebenbei noch den 
Assembler.

von Daniel B. (inox5) Benutzerseite


Lesenswert?

Mein Problem mit dem Timer ist aber im Moment folgendes und zwar bekommt 
mein Timer0 (8Bit) 1000000 Impulse in der Sekunde (kein Vorteiler), das 
heißt wiederum das mein Timer 3906,25 pro Sekunde überläuft und das ist 
schon zu langsam, weil der Timer folglich dann nur alle 0,256ms 
überläuft. Der Timer müsste aber alle 0,1ms überläufen.

Mach ich nur en Denkfehler oder besteht die Lösung darin dem µC einen 
höheren Takt zu geben? Oder ließe sich das noch ganz anders lösen?

MfG
Inox

PS: Frohe Weihnachten! :-)

von Gast (Gast)


Lesenswert?

Ich kenne zwar die Tinys nicht,
aber Du kannst doch das Maximum von TCNT bestimmen bei dem die ISR 
ausgelöst und TCNT zurückgesetzt wird... ?!

Frohe Weihnachten

von Daniel B. (inox5) Benutzerseite


Lesenswert?

Nein ich kann lediglich auswerten, dass der Timer übergelaufen ist mehr 
nicht. Und das passiert nach 256 Impulsen

von Gast (Gast)


Lesenswert?

Dann kannst du TCNT aber mit einem Wert Vorladen !

So das der Timer von z.B. 128 bis 255(überlauf) Zählt, oder ?

Ich glaube das was ich meinte war der CTC Modus...

von Frank S. (Firma: HSCS) (linuxerr)


Lesenswert?

das was du da machen willst, kann der timer ganz allein! benutze den 
pwm-modus und stelle den vorteiler so ein, dass der timer nach 20ms 
überläuft und einen interrupt auslöst. mit dem compare-register stellst 
du dann die breite der impule ein, die du haben willst. wenn der 
interrupt 50mal durchgelaufen ist, änderst du den wert der in das 
compare-register geladen wird. trenne dich von deinen zeitschleifen, das 
ist nonsens, die hardware kann das viel besser und effizienter und der 
code wird viel kürzer.

von Gast (Gast)


Lesenswert?

Im Datenblatt auf Seite 68 im Absatz "Clear Timer on Compare Match Mode"

Im CTC Modus Zählt der Counter (TCNT++) hoch bis zu einem Vergleichswert 
der in OCR0A (TCNT==OCR0A) gespeichert ist.

Der hat den Modus also doch.

Das Vorladen des TCNT im Normalen Modus sollte aber auch gehen.

von Frank S. (Firma: HSCS) (linuxerr)


Lesenswert?

Gast wrote:
> Im Datenblatt auf Seite 68 im Absatz "Clear Timer on Compare Match Mode"
>
wenn er sich nun mit dem timer ein delay zaubern will, dann macht das 
sinn. so wie sein programm aussieht will er eine pwm und das kann der 
timer auch, dass einzige was sein programm tun muss ist die 
compare-werte für das tastverhältnis nachzuladen, den rest macht der 
timer selbst.

von Daniel B. (inox5) Benutzerseite


Lesenswert?

das is natürlich gut, werd ich sofort ausprobieren. Weil wenn ich mit 
dem Timer alleine meine PWM bekommen kann, ist das natürlich wesentlich 
präziser und einfacher.

von pumpkin (Gast)


Lesenswert?

Zu groß? Kein Wunder. _delay wird nicht mit einer Konstanten aufgerufen.

Ralf W. wrote:
1
In order for these functions to work as intended, compiler 
2
optimizations must be enabled, and the delay time must be an expression 
3
that is a known constant at compile-time. If these requirements are not 
4
met, the resulting delay will be much longer (and basically unpredictable),
5
and applications that otherwise do not use floating-point calculations will 
6
experience severe code bloat by the floating-point library routines linked 
7
into the application.

von Daniel B. (inox5) Benutzerseite


Lesenswert?

Guten Abend,
Ich hab mir gedacht ich berichte euch mal was ich nun gemacht habe:
1
#include <avr/io.h>      //Grundfunktionen
2
#ifndef F_CPU        //Vordefinieren für delay.h
3
#define F_CPU 1000000UL            //Definition von F_CPU in Herz
4
#endif      
5
#include <util/delay.h>            //Warteschleifen
6
#include <stdint.h>
7
#include <avr/interrupt.h> 
8
9
ISR(TIMER1_COMPA_vect)
10
{
11
OCR1A=2500-OCR1A;   //Im ISR wird das Steuersignal für den Servo, aus der Differenz der Periodenlänge und des vorherigen Vergleichswert gebildet
12
}
13
14
15
int main (void)        //Hauptfunktion
16
{        
17
DDRB=0b11111100;      //Alles Ausgänge bis auf PB0 und PB1
18
PORTB=0b00000011;      //Pullup für PB0 und PB1
19
TCCR1A=0b01010000;      //Tooglen von PB3
20
TCCR1B=0b00001010;      //CTC-Mode und Prescaler 8; Prozessortakt
21
TIMSK=0b01000000;      //Interrupt bei Timer1 Comp.Match A
22
OCR1A=2375;    //das bringt den Servo in Neutrallage (1,5ms)
23
sei();         //Interrupts an
24
while(1)      //Programmschleife
25
{
26
  if ( !(PINB & (1<<PINB0)) )     //Abfrage eines Schalters
27
  {
28
  OCR1A=OCR1A+3;
29
  _delay_ms(50);                  //Verlangsamung der Veränderung
30
  }
31
  if ( !(PINB & (1<<PINB1)) )     //Abfrage eines Schalters
32
  {
33
  OCR1A=OCR1A-3;
34
  _delay_ms(50);                  //Verlangsamung der Veränderung
35
  }
36
}
37
return 0;  //C-Standard
38
}

Letzendlich bin ich am CTC-Modus hängengeblieben ;), nie gedacht, dass 
es so simpel ist, auch mit den Interrupts...
Dieses Programm erzeugt mit Erfolg meine gewünschte PWM, die ich für den 
Servo brauche. Zusätzlich kann man das PWM Signal in 0,024ms Stufen 
verändern, d.h. den Servo aus der Neutralposition links oder rechts 
drehen lassen. Dies geschieht durch die 2 angeschlossenen Schalter.
Mehr dazu bald unter Modellbauservo Ansteuerung im wiki.

Danke nochmal für eure Hilfe,

MfG
Inox

von B e r n d W. (smiley46)


Lesenswert?

Hallo Daniel

Die Timer-Version ist natürlich die sauberere Lösung.

Aber wie Kürbis schon sagte, so wärs auch gegangen:
AVR Memory Usage
Device:  attiny2313
Program: 198 bytes (9.7% Full)
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
void 
5
my_delay_us(unsigned int ms)                          // delay ms
6
{
7
   while(ms) {
8
      _delay_us(0.96);
9
      ms--;
10
   }
11
}
12
13
int 
14
main(void)
15
{
16
   DDRB=0b11111111;     //Alles Ausgänge
17
   uint16_t a;          //Variable 16Bit
18
   char i;              //Zählvariable für die Schleife
19
20
   a=1000;                 //Der Impuls soll 1ms lang sein
21
   while(1)      
22
   {
23
      i=50;                //Durch diese Definierung ist die While(i)
24
                           //Schleife immer 1s (50*0,02s) lang
25
      while(i)
26
      {
27
         PORTB=0b11111111;
28
         my_delay_us(a);   //Impulslänge
29
         PORTB=0b00000000;
30
         my_delay_us(20000-a);  //Hierdurch wird erreicht, dass das
31
                           //Gesamtsignal genau 20ms lang ist
32
         i--;
33
      }
34
      a=a+100;             //Ich will aber das die Impulse länger werden
35
      if(a==2000)          //Da aber ab einer Impulslänge von über 2ms 
36
                           //der Servo kaputt gehen kann, 
37
                           //wird hier nun die Notbremse gezogen
38
      {
39
         a=1000;
40
      }
41
   }
42
   return 0;
43
}

von Daniel B. (inox5) Benutzerseite


Lesenswert?

Stimmt so wärs auch gegangen, aber auf die zahlreichen Anregungen hier 
Richtung Timer + ISR hab ich beschlossen, dann doch mal Neuland zu 
betreten. Will ja schließlich was lernen.^^

Letzendlich erfüllen beide Programme den gleichen Zweck und welche nun 
die bessere ist, finde ich, muss jeder selbst wissen.

MfG
Inox

von Sven P. (Gast)


Lesenswert?

Dashier:
1
void 
2
my_delay_us(unsigned int ms)                          // delay ms
3
{
4
   while(ms) {
5
      _delay_us(0.96);
6
      ms--;
7
   }
8
}

ist unbestreitbar ein krasser Widerspruch zu demhier:
1
my_delay_us(20000-a);  //Hierdurch wird erreicht, dass das
2
                       //Gesamtsignal genau 20ms lang ist

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Daniel B. wrote:
>   OCR1A=OCR1A+3;

Auch wenn dein Programm funktioniert, so hat es noch ein paar Fußangeln.

Sehr versteckt im Tutorial findest du dazu das hier:

http://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff

OCR1A ist ein 16-Bit Register, das nicht atomav verändert werden kenn. 
Wenn während des Inkrementierens um 3 eine IRQ auftritt, kann das 
zuProblemen führen (reca condition) und das Servo macht nen Sprung.

von Daniel B. (inox5) Benutzerseite


Lesenswert?

Stimmt, das stellt ein Problem dar. Nur wenn gerade just ein Interrupt 
während des in-das-Register-Schreibens passiert fehlt eine Periode 
einfach und noch viel schlimmer: Die Perioden würden ihre Polarität 
ändern! Fragt sich was das geringere Übel ist...

von T. H. (pumpkin) Benutzerseite


Lesenswert?


von Daniel B. (inox5) Benutzerseite


Lesenswert?

1
int main (void)        //Hauptfunktion
2
{              //Anfang der Hauptfuktion
3
DDRB=0b11111100;      //Alles Ausgänge bis auf PB0
4
PORTB=0b00000011;      //Pullup für PB2
5
TCCR1A=0b01010000;      //Tooglen von PB3
6
TCCR1B=0b00001010;      //CTC-Mode und; Prescaler 8; Prozessortakt
7
TIMSK=0b01000000;      //Interrupt
8
OCR1A=2375;          //Neutralposition (2375*0,008=1,5ms)
9
sei();            //Interrupt an
10
while(1)
11
{
12
  if ( !(PINB & (1<<PINB0)) )  //Abfrage eines Schalters
13
  {
14
        cli();
15
  OCR1A=OCR1A+3;
16
        sei();
17
  _delay_ms(50);        //Verlangsamung der Veränderung
18
  }
19
  if ( !(PINB & (1<<PINB1)) )  //Abfrage eines Schalters
20
  {
21
        cli();
22
  OCR1A=OCR1A-3;
23
        sei();
24
  _delay_ms(50);        //Verlangsamung der Veränderung
25
  }
26
}
27
return 0;
28
}

Ich hab das jetzt so gemacht. Geht auch oder?

MfG
Inox

von Stefan K. (_sk_)


Lesenswert?

Hi Daniel,

die Idee mit dem atomaren Zugriff ist zwar im Prinzip richtig, beim 
Zugriff auf die Timerregister (ausnahmsweise) überflüssig: den atomaren 
Zugriff regelt die Timer-Hardware selber (siehe ATtiny Manual S. 88: 
accessing 16 Bit registers).

Ein anderes, noch wichtigeres Problem regelt die Timerhardware im 
PWM-Modus aus selbstständig:

angenommen, Dein OCR1A steht auf 15 und Dein Counter zählt hoch:
10, 11, 12, 13, 14, 15, 16, 17, 18, ....
Zum Zeitpunkt, an dem der Counter auf 13 steht, liest Du OCR1A aus 
(=15), ziehst 3 ab und schreibst das Ergebnis (=12) zurück nach OCR1A.

Das Ergebnis ist:
Dein Counter hat den Match mit OCR1A verpasst!

Um das zu vermeiden, ist OCRnA doppelt-gepuffert (siehe auch Man. S. 
95):
Wenn Du OCRnA änderst, änderst Du nur ein Schattenregister. Dessen Wert 
wird immmer dann in das "richtige" OCRnA übernommen, wenn der Timer 
überläuft bzw. NULL erreicht (genaueres steht im Man. bei den 
verschiedenen PWM-Modi beschrieben).

Fazit:
Dein erstes Hardware-PWM Programm war korrekt.

Viel Spass noch, Stefan

von Falk B. (falk)


Lesenswert?

@  Stefan Kleinwort (sk)

>die Idee mit dem atomaren Zugriff ist zwar im Prinzip richtig, beim
>Zugriff auf die Timerregister (ausnahmsweise) überflüssig: den atomaren
>Zugriff regelt die Timer-Hardware selber (siehe ATtiny Manual S. 88:
>accessing 16 Bit registers).

Das reicht nicht!

MFG
Falk

von Stefan (Gast)


Lesenswert?

WAS reicht nicht?

Gruß, Stefan

von Frank S. (Firma: HSCS) (linuxerr)


Lesenswert?

also ich verstehe das alles nicht. warum werden hier komische 
zeitschleifen programmiert, wenn der timer einen pwm-modus hat und es 
ganau das ist worum es hier geht. ich habe das ganz zum anfang schon 
gesagt. der threadersteller hat dann ja den ctc-modus genutzt und sich 
wieder ein delay gebastelt. warum macht man sowas?? nur weil das auch 
gehen muss??? ich kapiers nicht, gibt es da einen wichtigen grund für??
das ist doch so, als wenn ich mir sage: "mensch eine tür müsste man in 
autos einbauen und dann könnte man sogar einsteigen und mitfahren." und 
danach wird tagelang darüber diskutiert, wie man fenster so verändern 
könnte, dass man dadurch bequem einsteigen kann, dabei gibt es die tür 
längst!

ich versteh es nicht!

von Stefan (Gast)


Lesenswert?

Hallo Frank,

der TS benutzt doch mittlerweile den PWM, und das ist immerhin Dein 
Verdienst!
Die Delays, die noch in dem Programm sind, sin ja für die 
"Bedienoberfläche", das ist ne andere Baustelle und ich denke, so nur 
zum Testen gedacht.

Viele Grüße, Stefan

von Daniel B. (inox5) Benutzerseite


Lesenswert?

@Frank
In der Programmschleife ist nur en delay drin, weil ich dafür net auch 
noch extra nen Timer verwenden will und es somit auch einfacher bleibt. 
Meine PWM (auch der eigentliche Threadgegenstand) hab ich nun ja (dank 
dir) mit dem CTC-Modus gelöst.

@Stefan
Genau so hab ich es gemeint.

MfG
Inox

von Falk B. (falk)


Lesenswert?

@ Stefan (Gast)

>WAS reicht nicht?

Den atomaren Zugriff auf die 16 Bit Timerregister per Hardware zu 
sichern.
cli() und sei() bzw. bei neueren AVR GCC Versionen ein atomic block sind 
notwendig.

MFG
Falk

von Stefan (Gast)


Lesenswert?

@Falk:

Manual ATmega32, S.89:
"When the low byte of a 16-bit register is written by the CPU, the high 
byte stored in the temporary register, and the low byte written are both 
copied into the 16-bit register in the same clock cycle. When the low 
byte of a 16-bit register is read by the CPU, the high byte of the 
16-bit register is copied into the temporary register in the same clock 
cycle as the low byte is read".

Solange ein IR nicht das temporary register ändert, ist ein atomarer 
Zugriff nicht notwendig - diesen erledigt in diesem Fall die 
Timer-Hardware (beide 8-Bit-Register werden von der HW gleichzeitig [in 
the same clock cycle] in die 16-Bit Timer-Register geschrieben).

Gruß, Stefan

von Falk B. (falk)


Lesenswert?

@  Stefan (Gast)

>Solange ein IR nicht das temporary register ändert, ist ein atomarer
>Zugriff nicht notwendig

Das tut sie in diesem Beispiel aber.

1
OCR1A=2500-OCR1A;

> - diesen erledigt in diesem Fall die
>Timer-Hardware (beide 8-Bit-Register werden von der HW gleichzeitig [in
>the same clock cycle] in die 16-Bit Timer-Register geschrieben).

Du verwechselt den atomaren Zugriff auf Hardwareregister mit dem 
atomaren Zugriff auf normale Variabeln im RAM. Bei BEIDEN muss man 
aufpassen und mit cli/sei arbeiten, wenn auf die selbe Variable/Register 
im Hauptprogramm UND einer ISR zugegriffen wird. Der Mechanismus mit dem 
temp-Register ermöglicht "nur" den atomren zugriff auf 16 Bit 
Hardwareregister mit einer 8 Bit CPU. cli/sei würden dort gar nicht 
nützen, das beeinflusst die 16 Bit Register keine Nanosekunde.

MFG
Falk

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Falk Brunner wrote:
> @  Stefan (Gast)
>
>>Solange ein IR nicht das temporary register ändert, ist ein atomarer
>>Zugriff nicht notwendig
>
> Das tut sie in diesem Beispiel aber.

Zudem handelt es sich im Hauptprogramm bei ... OCR1A = OCR1A+3 nicht nur 
um einen Zugriff, sondern um zwei, nämlich ein Lese- und ein 
Schreibzugriff.

von Stefan (Gast)


Lesenswert?

@Falk, @Johann:
Ok, ich bin vom Source des TS von 12:50 ausgegangen, dort ist kein 
Interrupt vorhanden. (wahrscheinlich ist er aber einfach nicht 
mitgepostet worden).
Mit IR, jedenfalls so, wie er um 00:54 gepostet wurde, habt Ihr 
natürlich Recht.

@Daniel:
Warum benutzt Du den CTC-Mode? Der Timer hat so viele schöne PWM-Modi, 
die komplett in der Timer-Hardware, ohne einen Software-Eingriff laufen.

Gruß, Stefan

von Daniel B. (inox5) Benutzerseite


Lesenswert?

@Stefan
Tut mir leid, hab da nur die Hauptfunktion gepostet. Wollte aus 
Platzgründen nicht den Rest noch dazu posten.

Ja zudem war das mein erstes Programm, das den Timer nutzt. Warum hab 
ich nicht einen anderen Modus genutzt? Gute Frage, mir wurde der 
CTC-Modus schonmal vorgeschlagen und naja da hab ich mir gedacht, der 
wird wohl mehr Ahnung ham als ich, also machst du es mit dem CTC-Modus^^
Nunja fürs nächstemal werd ich genauer schaun, welcher Modus für mein 
Problem passend ist.

MfG
Inox

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.