Wenn ich ein Feintunning für eine Zeitverzögerungsschleife brauche, also
die Verzögerungszeit in 1/F_CPU Inkrementen genau einstellbar sein soll,
hätte ich das in 8051-Assembler etwa so geschrieben:
1
ANL A,#00000111b ;ACC = ACC modulo 8
2
MOV DPTR,#My_Jump_Tab
3
JMP @A + DPTR
4
My_Jump_Tab:
5
NOP ;0
6
NOP ;1
7
NOP ;2
8
NOP ;3
9
NOP ;4
10
NOP ;5
11
NOP ;6
12
RET ;7
Wie würde ich das in C für einen AVR programmieren?
Wenn dus genau haben willst, dann machs mit einem Timer und schick den
µC in einen Sleep Modus solange nichts zu tun ist. Alles andere
vergeudet nur Strom. Im AVR-GCC-Tutorial sollte alles stehen was du
brauchst
Uwe schrieb:
>In C würdest du die fertigen Delay-Funktionen aus der avr-libc nehmen.
Im Im AVR-GCC-Tutorial steht:
>_delay_ms() kann mit einem Argument bis 6553,5 ms (= 6,5535 Sekunden) >benutzt
werden. Wird die früher gültige Grenze von 262,14 ms/F_CPU (in MHz)
>überschritten, so arbeitet _delay_ms() einfach etwas ungenauer und zählt >nur
noch mit einer Auflösung von 1/10 ms. Eine Verzögerung von 1000,10 ms >ließe sich
nicht mehr von einer von 1000,19 ms unterscheiden. Ein Verlust, >der sich *im
Allgemeinen* verschmerzen lässt.
Ein Verlust der im Speziellen sich nicht verschmerzen lässt.
Christopher G. (cbg) schrieb:
>Wenn dus genau haben willst, dann machs mit einem Timer
Der leider nur ein 8-Bit-Typ ist...
MarioT (Gast) schrieb:
* AVRdelayloop3.zip (267 KB, 5 Downloads)
>>Wie würde ich das in C für einen AVR programmieren?>Hab ich leider keine Ahnung.>ASM sehe Dir das mal an.
Die gewünschte Verzögerung ist erst zur Laufzeit bekannt.
>Die gewünschte Verzögerung ist erst zur Laufzeit bekannt.
Man müßte etwas genauer wissen was Du vorhast. Was es für Möglichkeiten
gibt. Wo kommt die Entscheidung her wie lange Verzögert werden muß. Das
dürfte doch kein Problem sein die Register dementsprechend zu
setzen(oder so ähnlich). Wie lang sollen die Verzögerungen sein
(min-max).
Schnurzelpurzel schrieb:
> Der leider nur ein 8-Bit-Typ ist...
was hindert dich daran bei jeden überlauf eine Variable hochzuzählen und
schon kannst du auch bis 2^64 zählen.
Rainer Unsinn schrieb:
> Kann man denn in C keinen Assembler-Code (der so funktioniert wie oben)> einbinden..?
Klar kann man. Such mal weiter unter dem Stichwort "Inline assembler" -
ich hab das noch nicht gemacht, kann dir daher nicht weiterhelfen damit.
Rainer Unsinn schrieb:
> das "variable hochzählen" dauert ggf. viel zu lange...?
Wenn man das im Overflow-IRQ macht, zählt der Timer doch solange weiter?
MfG, Heiko
Heiko schrieb:
> Rainer Unsinn schrieb:>> Kann man denn in C keinen Assembler-Code (der so funktioniert wie oben)>> einbinden..?>> Klar kann man. Such mal weiter unter dem Stichwort "Inline assembler" -> ich hab das noch nicht gemacht, kann dir daher nicht weiterhelfen damit.
Oder Schnurzelpurzel schaut endlich mal ins
AVR-GCC-Tutorial: Assembler und Inline-Assembler.
Schnurzelpurzel hat wohl noch zu tun um die speziellen Anforderungen zu
formulieren. (Was ja ueblicherweise mindestens schon 50% der Loesung
ist.)
Gast
Also ich habe an meinem (geplanten) Ticky-Tool-Gerät zwei solche
Switch_Boards.
Es soll eine Rechteckschwingung erzeugt werden.
Eingestellt wird die High-Zeit und die Low-Zeit.
Sekunden 000..999, ms 000...999, us 000...999
ns 000...900 (hier nur in 100ns Schrittweite)
Also insgesamt 10-Stellen => 10MHz Frequenznormal an XTAL-In
CPU ist ATtiny25, die Kommunikation mit den Switchboards ist SPI.
da die interruptlatenzzeit schwankt, ist nix mit Interrupt.
Da es Zeit braucht, die Switchboards auszulesen ist die kleinste
Einstellbare Zeit 1ms oder eher größer!
Wichtig ist mir nur, das die Schrittweite 100ns ist.
Leider sind meine C-Kenntnisse zu gering um das 8051-Assembler-Beispiel
in C zu übersetzen.
1
ANL A,#00000111b ;ACC = ACC modulo 8
2
MOV DPTR,#My_Jump_Tab
3
JMP @A + DPTR
4
My_Jump_Tab:
5
NOP ;0
6
NOP ;1
7
NOP ;2
8
NOP ;3
9
NOP ;4
10
NOP ;5
11
NOP ;6
12
RET ;7
Dieses 8051-Programmbeispiel macht eine Verzögerung in 1/XTAL
Schrittweite.
Schnurzelpurzel schrieb:
> CPU ist ATtiny25, die Kommunikation mit den Switchboards ist SPI.> da die interruptlatenzzeit schwankt, ist nix mit Interrupt.> Da es Zeit braucht, die Switchboards auszulesen ist die kleinste> Einstellbare Zeit 1ms oder eher größer!> Wichtig ist mir nur, das die Schrittweite 100ns ist.
Und dein Quarz ist tatsächlich temperaturkompensiert und aufs Herz
genau?
>> Leider sind meine C-Kenntnisse zu gering um das 8051-Assembler-Beispiel> in C zu übersetzen.>
1
> ANL A,#00000111b ;ACC = ACC modulo 8
2
> MOV DPTR,#My_Jump_Tab
3
> JMP @A + DPTR
4
> My_Jump_Tab:
5
> NOP ;0
6
> NOP ;1
7
> NOP ;2
8
> NOP ;3
9
> NOP ;4
10
> NOP ;5
11
> NOP ;6
12
> RET ;7
13
>
> Dieses 8051-Programmbeispiel macht eine Verzögerung in 1/XTAL> Schrittweite.
Schön.
Und wie gehts dann weiter? Eine auf den einzelnen Takt genau Verzögerung
ist wunderbar aber nur die halbe Miete. Da spielt sich ja auch Code
davor ab. Da spielt sich Code dahinter ab. All das braucht auch seine
Zeit. Zeit die je nach Compilereinstellung unterschiedlich sein kann.
Wenn du bei C bleiben willst, ist deine beste Option der Einsatz eines
Timers, wobei der Timer den Pin umschaltet. Dann bist du auf den
Taktzyklus genau und das auch noch ziemlich trivial, solange High und
Low Zeit in etwa in der gleichen Größenordnung sind.
Schnurzelpurzel schrieb:
> CPU ist ATtiny25, die Kommunikation mit den Switchboards ist SPI.> da die interruptlatenzzeit schwankt, ist nix mit Interrupt.
Dann schau einfach mal ins Datenblatt.
Der Timer kann zyklusgenau einen Pin umschalten, die 10ns sind also mit
Interrupt kein Problem.
Und das Main kann derweil in Ruhe die Schalter abfragen und bei ner
Änderung die Comparewerte umdefinieren.
Etwas tricky wirds mit der Aufteilung der Compareereignise. Wenn der
Puls 257 Takte lang sein soll kannst du ihn nicht in 256 + 1 Takte
zerlegen, da ein Interrupthandler schon etwa 50 Takte Zeit haben sollte.
Also 257 zerlegen in 128 + 129 usw.
Du kannst aber auch nen ATtiny24 nehmen, der hat nen 16Bit Timer.
Peter
Hier jetzt meine Delay-Routine.
Die Verzögerungszeit ist (53 + unsigned long int Zeit) / F_CPU
Die 53 ist die Anzahl an Taktzyklen die das Programm braucht, wenn
Zeit=0 ist. Da meine Taktfrequenz im Moment vom ATtiny25 selber kommt,
habe ich dies noch nicht ganz exakt gemessen!!!
1
//***********************************************
2
// (c) 08.03.2010 by Schnurzelpurzel
3
voidDelay(unsignedlongintZeit)
4
{
5
PINB=(1<<PIN4);//Nur zu Testzwecken an Portleitung klappern!
6
7
if(Zeit&0x00000001)
8
{
9
asmvolatile("NOP");
10
asmvolatile("NOP");1
11
}
12
if(Zeit&0x00000002)
13
{
14
asmvolatile("NOP");
15
asmvolatile("NOP");1
16
asmvolatile("NOP");2
17
}
18
if(Zeit&0x00000004)
19
{
20
asmvolatile("NOP");
21
asmvolatile("NOP");1
22
asmvolatile("NOP");2
23
asmvolatile("NOP");3
24
asmvolatile("NOP");4
25
}
26
if(Zeit&0x00000008)
27
{
28
asmvolatile("NOP");
29
asmvolatile("NOP");1
30
asmvolatile("NOP");2
31
asmvolatile("NOP");3
32
asmvolatile("NOP");4
33
asmvolatile("NOP");5
34
asmvolatile("NOP");6
35
asmvolatile("NOP");7
36
asmvolatile("NOP");8
37
}
38
39
Zeit>>=4;
40
while(Zeit>0)
41
{
42
asmvolatile("NOP");1
43
asmvolatile("NOP");2
44
asmvolatile("NOP");3
45
asmvolatile("NOP");4
46
asmvolatile("NOP");5
47
asmvolatile("NOP");6
48
Zeit--;
49
}
50
51
PINB=(1<<PIN4);//Nur zu Testzwecken an Portleitung klappern!
52
}
53
//***********************************************
Ist das nicht toll?
Meine Mama sagt immer "Schnurzelpurzel, du bist der beste"
Ihr dürft diese Routine gern verwenden, wenn ihr das Copyright drin
lässt.
Wenn nicht, sag ich das mein Onkel, der ist Jäger und schießt euch mit'm
Schrotgewehr in Hintern!
Ja, man kanns natürlich umständlich machen.
Es geht aber auch einfacher.
Ich hatte mal was gemacht, bevor die AVRs Compareregister hatten:
Beitrag "AVR: Delay 7 ... 65542 Zyklen"
Mit der set/cear/toggle on Compare Funtion lasse ich das aber den Timer
selber machen. Dann kann man nebenbei noch anderes machen, ohne den Puls
zu stören. Und Assembler ist auch nicht mehr nötig.
Peter
Peter Dannegger schrieb:
> Warum so umständlich?>> Beitrag "AVR: Delay 7 ... 65542 Zyklen">>> Peter
Ich wollte ein Routine haben die 1 / F_CPU Auflösung hat und bis zu 2^32
Zyklen verzögern kann.
Habe jetzt zwei Varianten, dank an Karl heinz Buchegger.
Kann einer der Moderatoren hier bitte ein bischen aufräumen?
Sorry, ist irgendwie schiefgegeangen, habe dreimal den selben Beitrag
gepostet :-(