Forum: Mikrocontroller und Digitale Elektronik Falsche Ausgangsfrequenz


von Guy N. (Firma: Student) (lechristiano)


Lesenswert?

Hallo,
ich benutze eine Atmega644 mit einem externen Quarz von 8MHz auf einem 
selbstgebauten Board. ich versuche 4MHz auf einen Pin rauszukriegen, 
indem ich einfach seinen Wert zwischen 0 und 1 umschalte. ich bekomme 
aber maximal 89kHz.
- ich weiß zuerst nicht, wie man die Fuse einstellt. liegt es daran?
- was mache ich falsch? Die Timer Einstellung müsste ok sein.
- oder was könnten Sie mir vorschlagen, durch Interrupt die 4MHz 
rauszukriegen?

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//#define F_CPU 8000000UL // 8 MHz

#define ZAEHLER PORTD
#define ZAEHLER_DDR DDRD
#define ZAEHLER_PIN PIND


 ////Timer/Counter1 Interrupt Routine
 ISR (TIMER1_OVF_vect)
 {
  ZAEHLER = ~ZAEHLER_PIN;

  TCNT1 = 0xFFFF;
 }

int main(void)
{
  cli();

  //timer config
  TCCR1A = 0; //mode normal
  TCCR1B = 0x01;  //prescaler = 1
  TCNT1 = 0xFFFF;
  TIMSK1 = 0x01; //TOIE1 enabled

  ZAEHLER_DDR = 0xFF; // alle Ausgänge
  ZAEHLER = 0x00;
  // Enable Interrupts
  sei();

    while(1)
    {
    }
}


Danke!
Christian

von Dr. Sommer (Gast)


Lesenswert?

Guy Ngamy schrieb:
> ISR (TIMER1_OVF_vect)
>  {
>   ZAEHLER = ~ZAEHLER_PIN;
>
>   TCNT1 = 0xFFFF;
>  }
Du glaubst also, der Aufruf dieser Routine, das umschalten des Pins, und 
das setzen des Timer-Registers geschieht alles in einem Takt?

von Düsendieb (Gast)


Lesenswert?

Guy Ngamy schrieb:
> Interrupt die 4MHz
> rauszukriegen?

4Mhz sind nie und nimmer möglich. Das Programm braucht schließlich eine 
gewisse Abarbeitungszeit

von spess53 (Gast)


Lesenswert?

Hi

Die einzige Möglichkeit wäre:

Timer im CTC-Mode mit Pintoggle initialisieren
Prescaler 1
OCR1A=0
Ausgang: OC1A-Pin

MfG Spess

von Guy N. (Firma: Student) (lechristiano)


Lesenswert?

Danke!
Mit CTC Mode klappt's. mich wundert aber noch etwas:
mit der folgenden Initialisierung habe ich den gewünschten 4MHz am 
OC1A(PD5). am TEST_PORT habe ich aber nur 117kHz und nicht 4MHz. sollten 
die nicht gleich sein, so finde ich trotzdem 117kHz zu wenig.
Mit   OCR1A = 0xFFFF;  // => 61 Hz am Ausgang
bekomme ich auch 61Hz am Ausgang von TEST_PORT.
Was ist das Problem?
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
#define F_CPU 8000000UL // 8 MHz Atmega644
7
8
#define TEST_PORT  PORTA
9
#define TEST_DDR  DDRA
10
#define TEST_PIN  PINA
11
#define SYNC_PORT PORTD
12
#define SYNC_PIN  PIND
13
#define SYNC_DDR  DDRD
14
15
#define SYNC_OUT  5  //OC1A am Pin5
16
17
ISR(TIMER1_COMPA_vect) 
18
{
19
  TEST_PORT = ~TEST_PIN;
20
}
21
22
int main(void)
23
{
24
  cli();
25
  //IO
26
  TEST_DDR = 0xff;
27
  TEST_PORT = 0x00;
28
  
29
  SYNC_DDR  |=(1<<SYNC_OUT); //PD5 als Ausgang einstellen (OC1A)
30
  SYNC_PORT &= ~(1<<SYNC_OUT);
31
32
   //Timer/Counter 0 initialization
33
   //Clock source: T0 pin Rising Edge
34
   //Compare Output Mode: Toggle OC0A on Compare Match
35
   // Waveform Generation Mode: CTC (Clear Timer on Compare Match)
36
   //clkI/O (No prescaling)
37
  TCCR1A = (1<<COM1A0);
38
  TCCR1B = (1<<CS10)|(1<<WGM12);
39
  TCNT1 = 0;
40
  OCR1A = 0;  // => 4MHz am Ausgang
41
  TIMSK1 = (1<<OCIE1A); //enable OCIE0A
42
  TIFR1 = (1<<OCF1A); 
43
  
44
  sei();
45
  
46
    while(1)
47
    {
48
    }
49
}

von Karl H. (kbuchegg)


Lesenswert?

Guy Ngamy schrieb:
> Danke!
> Mit CTC Mode klappt's. mich wundert aber noch etwas:
> mit der folgenden Initialisierung habe ich den gewünschten 4MHz am
> OC1A(PD5). am TEST_PORT habe ich aber nur 117kHz und nicht 4MHz. sollten
> die nicht gleich sein, so finde ich trotzdem 117kHz zu wenig.

Es dauert ein paar Takte, bis die ISR dann auch tatsächlich aufgerufen 
wird. Das geschieht ja nicht instantan, sondern der gerade laufende 
Befehl muss erst fertig gemacht werden, ehe der Interrupt unterbrechen 
darf.
Und selbst dann gibt es da noch eine Vorlaufzeit vom Beginn der 
Interruptbehandlung, bis dann endlich dein Code in der ISR zum Zug 
kommt. Genau dasselbe am anderen Ende der ISR. Ist dein Code fertig, 
muss unter Umständen noch eine Nachbehandlung her (gesicherte 
Registerinhalte wieder restaurieren) der Rücksprung aus der ISR 
durchgeführt werden und nachdem das Programm wieder an der 
unterbrochenen Stelle angelangt ist, wird der nächste Befehl auf jeden 
Fall ausgeführt, ehe dann die nächste Unterbrechung durch einen 
Interrupt angeleiert wird.

von Karl H. (kbuchegg)


Lesenswert?

> Mit   OCR1A = 0xFFFF;  // => 61 Hz am Ausgang
> bekomme ich auch 61Hz am Ausgang von TEST_PORT.

Der Unterschied zwischen
OCR1A = 0xFFFF;
und
OCR1A = 0x00;
besteht darin, dass im ersten Fall genügend Zeit zur Verfügung steht um 
all die Aktionen von einem Interrupt zum nächsten durchführen zu können. 
Im zweiten Fall aber nicht.

Wenn dir dein Chef alle 2 Tage eine Akte auf den Schreibtich knallt, 
kommst du locker hinterher. Tut er das aber alle 10 Sekunden, ertrinkst 
du in Arbeit.

von spess53 (Gast)


Lesenswert?

Hi

> am TEST_PORT habe ich aber nur 117kHz und nicht 4MHz. sollten
>die nicht gleich sein, so finde ich trotzdem 117kHz zu wenig.

117kHz an dem Pin heißt, das der Interrupt mit 234kHz aufgerufen wird. 
Das sind 34 Takte.

Datenblatt:

The interrupt execution response for all the enabled AVR interrupts is 
five clock cycles minimum. After five clock cycles the program vector 
address for the actual interrupt handling routine is executed. During 
these five clock cycle period, the Program Counter is pushed onto the 
Stack. The
vector is normally a jump to the interrupt routine, and this jump takes 
three clock cycles.
...
A return from an interrupt handling routine takes five clock cycles. 
During these five clock cycles,the Program Counter (three bytes) is 
popped back from the Stack, the Stack Pointer is incremented

Das sind schon mal mindestens 13 Takte. Also bleiben noch 21 für die 
eignetlich Interruptroutine.

Sieh dir im Assemblerlisting an, was dort gemacht wird.

MfG Spess

von Guy N. (Firma: Student) (lechristiano)


Angehängte Dateien:

Lesenswert?

Danke für die Antwort. Anhang schicke ich Ihnen das lss file (assembler) 
von dem Code. Im Interrupt gibt's nicht so viele Anweisungen... Ich 
verstehe immer noch nicht warum ich nur auf 117kHz komme statt 4MHz. 
Hier ein Teil vom asm Code (Anhang das ganze file).
Danke vielmal.
Christian
1
...
2
ISR(TIMER1_COMPA_vect) 
3
{
4
  88:  1f 92         push  r1
5
  8a:  0f 92         push  r0
6
  8c:  0f b6         in  r0, 0x3f  ; 63
7
  8e:  0f 92         push  r0
8
  90:  11 24         eor  r1, r1
9
  92:  8f 93         push  r24
10
  TEST_PORT = ~TEST_PIN;
11
  94:  80 b1         in  r24, 0x00  ; 0
12
  96:  80 95         com  r24
13
  98:  82 b9         out  0x02, r24  ; 2
14
}
15
  9a:  8f 91         pop  r24
16
  9c:  0f 90         pop  r0
17
  9e:  0f be         out  0x3f, r0  ; 63
18
  a0:  0f 90         pop  r0
19
  a2:  1f 90         pop  r1
20
  a4:  18 95         reti
21
22
000000a6 <main>:
23
24
int main(void)
25
{
26
...
27
}
28
...

von Karl H. (kbuchegg)


Lesenswert?

Guy Ngamy schrieb:
> Danke für die Antwort. Anhang schicke ich Ihnen das lss file (assembler)
> von dem Code. Im Interrupt gibt's nicht so viele Anweisungen... Ich
> verstehe immer noch nicht warum ich nur auf 117kHz komme statt 4MHz.
> Hier ein Teil vom asm Code (Anhang das ganze file).

Über den Daumen.
In der ISR sind 15 Befehle. Grob gerechnet sind das bischen mehr als 15 
Takte. Ich nehm mal 20, weil einige Befehle mehr als 1 Takt brauchen 
werden, ich aber jetzt zu faul bin um rauszusuchen welche.

Dazu kommen noch ein paar Takte nach dem Auslösen der ISR sowie nach dem 
Rücksprung aus der ISR. Spess hat oben schon zusammengerechnet und ist 
auf 13 Takte für dies Aktion gekommen.

20 + 13 macht 33

4000000 durch 33 dividiert ergibt rund 121-tausend.

Da sind also deine 117kHz. Schneller geht nicht, weil der µC nicht 
schneller arbeiten kann. Langsamer ist ok, je weniger Hz du von ihm 
verlangst, desto mehr Zeit bleibt ausserhalb der ISR für andere Dinge 
übrig. Wenn du aber schneller willst, dann ist irgendwann diese 'andere 
Zeit' auf 0 geschrumpft und der µC bearbeitet nur noch die ISR. Und die 
beschränkt nun mal durch ihre Laufzeit und das ganze drumherum das 
Maximum dessen, was abgearbeitet werden kann. Noch schneller geht dann 
nicht mehr, wenn der µC eh schon mit Volldampf nur noch Schwingungen 
erzeugt. Mehr als 100% voll ausgelastet ist nun mal nicht drinnen.

von spess53 (Gast)


Lesenswert?

Hi

Da lag ich doch ganz gut:

                  Takte
push  r1             2
push  r0             2
in  r0, 0x3f         1
push  r0             2
eor  r1, r1          1
push  r24            2
in  r24, 0x00        1
com  r24             1
out  0x02, r24       1
pop  r24             2
pop  r0              2
out  0x3f, r0        1
pop  r0              2
pop  r1              2
---------------------------
                    22 Takte

MfG Spess

von Guy N. (Firma: Student) (lechristiano)


Angehängte Dateien:

Lesenswert?

Vielen Dank für Ihre Erläuterungen. Ich habe 3 verschiedene Atmega zur 
Verfügung (Atmega2560, Atmega644 und Atmega8515). die 3 brechen bei ca. 
117kHz ab beim Aufruf von Interrupt (8MHz Takt Frequenz) egal wie hoch 
ich gehe mit dem clk (siehe Bild Anhang). Das heißt es würde auch 
dasselbe sein mit einem Takt höher als 8MHz. Ich kann es mir aber nicht 
vorstellen.
Ich will eigentlich ein Sinus erzeugen und mit dem 117kHz lande ich max. 
auf 7kHz (mit 16 Stützpunkten Sinus).
mit einem Atmega16 hat aber einer 1MHz sinus erreicht. Hätten Sie 
irgendwelche Erklärung davon.
vielen Dank für Ihre Antworte.
MfG
Christian

von spess53 (Gast)


Lesenswert?

Hi

>Das heißt es würde auch
>dasselbe sein mit einem Takt höher als 8MHz. Ich kann es mir aber nicht
>vorstellen.

Bei einer höheren Taktfrequenz wird auch deine Interruptroutine 
schneller abgearbeitet. Dadurch steigt auch deine maximale Frequenz (bei 
gleicher Interruptroutine).

>mit einem Atmega16 hat aber einer 1MHz sinus erreicht. Hätten Sie
>irgendwelche Erklärung davon.

Mit einem optimierten Assemblerprogramm ist das schon möglich. Dann ist 
aber dein Controller zu 100% damit beschäftigt.

So etwa wie hier:

Beitrag "DDS normal ?"

MfG Spess

von Guy N. (Firma: Student) (lechristiano)


Lesenswert?

Hallo,
danke für Ihre Antwort.
ich werde mich in AVR Assembler Programmierung einarbeiten. Sicher wird 
das besser sein. aber wie gesagt, mich wundert, dass einer in C 
programmiert hat und 10kHz Sinus geschafft hat (mit 256 Stützpunkten). 
ich komme aber nur auf ca.200Hz. liegt das bei mir nicht an Fuse 
Einstellung? wie soll die eingestellt sein bei Atmega644 mit 8MHz quarz?
(Entschuldigung für die Störung, ich will nur verstehen!)

Mit freundlichen Grüßen
Ngamy

von Karl H. (kbuchegg)


Lesenswert?

> aber wie gesagt, mich wundert, dass einer in C programmiert hat
> und 10kHz Sinus geschafft hat (mit 256 Stützpunkten).

Wenn das stimmt, dann muss man sich ansehen, WIE er es gemacht hat und 
ob sein µC mit 8Mhz getaktet war.

Mit der Methode hier und 8Mhz ist Ende der Fahnenstange.
Was ja nicht heißt, dass der jenige das genau so gemacht haben muss. 
Also: Sein Prinzip studieren, die Nebenbedingungen studieren und daraus 
lernen! Man kann eine Menge lernen, wenn man fremden Code studiert.

von Guy N. (Firma: Student) (lechristiano)


Angehängte Dateien:

Lesenswert?

Hallo, ich habe jetzt ein Code in Assembler geschrieben und es siehst 
besser aus. mit dem Code anhang erreiche ich fast die 10kHz sinus. es 
liegt daran, dass die Auflösung zu hoch ist (ca. 24,6 mHz für eine 
Schrittweite 1). Ich will aber 1Hz für eine Schrittweite 1 und ich 
schaffe es nicht. so bin ich vorgegangen:
Gewünschte Freq: 10kHz
Frequenzauflösung: 1Hz für eine Schrittweite 1
Feste Taktfrequenz: 2hoch13 = 8192Hz
mit 8bit DAC
=> 8+13 = 21bit Phasenakkumulator

ich brauche dann 3 Register von 8bit => 24bit (Akku3,Akku2,Akku1)
ich habe dann die Register um 3 nach links verschoben, um die 8bit, die 
mich interessieren in Akku3 zu haben. Anschließend habe ich Akku3 mit ZL 
addiert und den Funktionswert mit dem Befehl lpm gelesen.
1
  add AkkuReg1, SW1 ; Phasenakkumulator
2
  adc AkkuReg2, SW2 ; SW = Schrittweite
3
  adc AkkuReg3, SW3
4
5
  lsl  AkkuReg2 ; Verschiebung um 3 nach links
6
  rol  AkkuReg3
7
  lsl  AkkuReg2
8
  rol  AkkuReg3
9
  lsl  AkkuReg2
10
  rol  AkkuReg3
11
12
  ldi ZL, LOW(SINTABLE*2) ; Zeiger am Anfang der Tabelle
13
  ldi ZH, HIGH(SINTABLE*2)
14
15
  add ZL,AkkuReg3
16
  adc ZH,null ; null ist ein leeres Register
17
18
  lpm;  R0 <- (Z). Funktionswert aus dem Speicher lesen
19
  out AD_WERTE_PORT, R0 ; Wert an den Analog-Digital-Wandler ausgeben (an PORTA angeschlossen)

=> Funktionniert nicht.
Ich würde mich sehr auf Vorschläge freuen.
Gott segnet euch!

MfG
Christian

von Stefan (Gast)


Lesenswert?

Für solche Anwendungen sind AVR Mikrocontroller nicht gedacht. 
Vielleicht kann mna da noch ein klein wenig optimieren, aber Dein Ziel 
wirst Du mit 8Mhz Systemtakt sicher nicht erreichen.

von Guy N. (Firma: Student) (lechristiano)


Lesenswert?

Doch es funktionniert in C Programmierung sogar sehr gut. der 
Ausgangsfrequenzbereich ist aber viel kleiner. deswegen will ich 
dasselbe in Assembler schreiben.

von spess53 (Gast)


Lesenswert?

Hi

>  ldi tempReg1, (1<<WGM12)|(1<<CS10) ; Timer 1 - CTC mode - No prescaling,
>  sts  TCCR1B, tempReg1
>  ldi tempReg1, 3
>  sts OCR1AL, tempReg1
>  ldi tempReg1, (1<<OCIE1A)
>  sts TIMSK1, tempReg1

Damit wird der OC-Interrupt alle 4 Controllertakte ausgelöst. Der 
Interrupt braucht aber ca. 20 Takte.

>...
>  rol  AkkuReg3
>  ldi ZL, LOW(SINTABLE*2) ; Zeiger am Anfang der Tabelle
>  ldi ZH, HIGH(SINTABLE*2)
>  add ZL,AkkuReg3
>  ....

>=> Funktionniert nicht.

>.def AkkuReg3 = R30

r30 ist ZL. Abgesehen davon ist die Routine ziemlich unsinnig. Wenn du 
den 'Phasenakkumulator' nicht wieder zurück 'shiftest' ist die nächste 
Addition falsch. Den gleichen Effekt wie mit dem Shiften erreichst du 
mit dem doppelten Wert in SW3-1.

Deine Berechnung kann ich auch nicht nachvollziehen.

Bei 256 Stützstellen für den Sinus muss für 10kHz alle 390ns ein 
Stützstellenwert ausgeben werden. Die Realisierbarkeit kannst du dir 
selbst ausrechnen.

MfG Spess

von Guy N. (Firma: Student) (lechristiano)


Lesenswert?

Hallo,
wie kann ich ein C Programm in AVR Assembler umwandeln und umgekehrt, 
wie kann ich ein AVR Assembler Programm nach C Programm so umwandeln, 
dass man es direkt verwenden kann?

danke!
Christian

von Cyblord -. (cyblord)


Lesenswert?

Guy Ngamy schrieb:
> Hallo,
> wie kann ich ein C Programm in AVR Assembler umwandeln und umgekehrt,

Das kann der GCC Compiler. Standardmäßig spuckt der beim Kompilieren 
gleich noch das Assemblerlisting mit aus.

> wie kann ich ein AVR Assembler Programm nach C Programm so umwandeln,
> dass man es direkt verwenden kann?

Brain 1.0

automatisch wird doch nur Quatsch draus. Außerdem warum sollte man das 
wollen? Was bringt es eine Maschinensprache wieder zurück in eine 
Hochsprache zu überführen?

gruß cyblord

von Guy N. (Firma: Student) (lechristiano)


Lesenswert?

> Das kann der GCC Compiler. Standardmäßig spuckt der beim Kompilieren
> gleich noch das Assemblerlisting mit aus.

Beim Kompilieren bekomme ich ein .lss Datei. Da sind C und asm zusammen. 
Ich will nur den asm Datei. Die finde ich nicht.

> Was bringt es eine Maschinensprache wieder zurück in eine
> Hochsprache zu überführen?

ich habe einen großen Teil von meinem Code in C geschrieben und musste 
nur einen kleinen Teil in asm schreiben. Ich will jetzt die beiden 
verbinden sozusagen. ich habe keine Ahnung wie es geht.

von Cyblord -. (cyblord)


Lesenswert?

Guy Ngamy schrieb:
>> Das kann der GCC Compiler. Standardmäßig spuckt der beim Kompilieren
>> gleich noch das Assemblerlisting mit aus.
>
> Beim Kompilieren bekomme ich ein .lss Datei. Da sind C und asm zusammen.
> Ich will nur den asm Datei. Die finde ich nicht.

Das ist nur Assembler, lediglich mit dem entsprechenden C-Code als 
Kommentar.

> ich habe einen großen Teil von meinem Code in C geschrieben und musste
> nur einen kleinen Teil in asm schreiben. Ich will jetzt die beiden
> verbinden sozusagen.

1.) Wieso kann der ASM Teil nicht ASM bleiben? Du kannst in ein 
C-Projekt auch asm Dateien einbinden. Kommt allein auf deine IDE an, 
bzw. deinen Makefile wenn du den noch selber schreibst. Aber nimm eine 
vernüftige IDE dann klappt das.

2.) Wenn du C und ASM Programmieren kannst, wo ist dann das Problem ein 
wenig ASM-Code in C-Code umzuschreiben? Hast du eine Ahnung wie eine 
automatische Konvertierung aussehen würde? Was würdest du dann damit 
anfangen? Lesbar wäre es nicht. Wenn man in C Programmiert sollte das 
Programm eine logische Struktur haben, sinvolle Variablen- und 
Funktionsnamen. Das bekommst du alles nicht wenn du von ASM Konvertieren 
würdest.

> ich habe keine Ahnung wie es geht.
Ich glaube das ist dein Hauptproblem. Dir scheint etwas Routine und der 
Überblick zu fehlen. Ich glaube auch nicht dass du fit in C- oder ASM 
Programmierung bist. Ich glaube du machst da irgendein schmutziges 
Copy&Paste.

gruß cyblord

von Guy N. (Firma: Student) (lechristiano)


Lesenswert?

> Das ist nur Assembler, lediglich mit dem entsprechenden C-Code als
> Kommentar.

Zwar, aber eins zu eins kopieren geht nicht. Was soll ich dann 
vernachlässigen und was soll ich auf jedenfall nehmen? AVR Assembler ist 
neu für mich, ich habe versucht mich einzuarbeiten, ich habe aber noch 
schwierigkeiten.

ich programmiere einen DDS Generator. ich habe in C angefangen (LCD und 
Tastenfeld Code) und dann musste ich den Hauptteil (sinus Erzeugung...) 
in asm schreiben, um höhere Frequenzen erreichen zu können. ich möchte 
jetzt die beiden zu laufen bringen, bzw. die eingegebenen Werte vom 
Tastenfeld in asm Code lesen und somit meine Frequenz einstellbar 
machen.

> Brain 1.0
Das ist doch zum Schütz vor Viren oder?

Danke!
Christian

von Cyblord -. (cyblord)


Lesenswert?

Guy Ngamy schrieb:
>> Das ist nur Assembler, lediglich mit dem entsprechenden C-Code als
>> Kommentar.
>
> Zwar, aber eins zu eins kopieren geht nicht. Was soll ich dann
> vernachlässigen und was soll ich auf jedenfall nehmen? AVR Assembler ist
> neu für mich, ich habe versucht mich einzuarbeiten, ich habe aber noch
> schwierigkeiten.

Also erstmal Assembler lernen, bzw. programmieren an sich lernen. Vorher 
kannst du so ein Projekt halt nicht durchziehen. Die .lss gibt dir den 
Assemblercode mit den entsprechenden Adressen vorne und den Kommentaren 
hinten. Eventuell gibt es im gcc einen Schalter um wirklich nur ASM zu 
bekommen. Trotzdem wird das dein Problem nicht lösen. Du schreibst doch, 
du hast bereits den ASM Teil. Also hängt den einfach in dein C-Projekt 
mit rein. Da musst du gar nichts hin oder her konvertieren.

gruß cyblord

von Guy N. (Firma: Student) (lechristiano)


Angehängte Dateien:

Lesenswert?

danke für deine Antwort! ich will jetzt so machen, dass ich ein ASM Code 
im C Programm integriere. es sollte folgendermaßen aussehen. Den Code 
habe ich aus Internet. Ich versuche den gerade zu verstehen.
1
void static inline Signal_OUT(const uint8_t *signal, uint8_t ad2, uint8_t ad1, uint8_t ad0)
2
{
3
asm volatile(  "eor r18, r18   ;r18<-0"  "\n\t"
4
        "eor r19, r19   ;r19<-0"  "\n\t"
5
        "1:"            "\n\t"
6
        "add r18, %0  ;1 cycle"      "\n\t"
7
        "adc r19, %1  ;1 cycle"      "\n\t"  
8
        "adc %A3, %2  ;1 cycle"      "\n\t"
9
        "lpm       ;3 cycles"   "\n\t"
10
        "out %4, __tmp_reg__  ;1 cycle"  "\n\t"
11
        "sbis %5, 2    ;1 cycle if no skip" "\n\t"
12
        "rjmp 1b    ;2 cycles. Total 10 cycles"  "\n\t"
13
        :
14
        :"r" (ad0),"r" (ad1),"r" (ad2),"e" (signal),"I" (_SFR_IO_ADDR(PORTA)), "I" (_SFR_IO_ADDR(SPCR))
15
        :"r18", "r19" 
16
  );
17
}


1) Was bedeutet "1:" in der 5. Zeile?
2) Was bedeutet die 3 letzte Zeilen
:
:"r" (ad0)....
:"r18",... ???

3) ich versuche den ganzen Code zu kompilieren, und ich bekomme einen 
Fehler wegen jenen Codeabschnitt:
ERROR: register number above 15 required

Kann Jemand mir helfen?

danke.
Christian

von asdf (Gast)


Lesenswert?

Guy Ngamy schrieb:
> 1) Was bedeutet "1:" in der 5. Zeile?

ein jump label

> 2) Was bedeutet die 3 letzte Zeilen
sagen dem kompiler was du mit welchem register vorhast.

> 3) ich versuche den ganzen Code zu kompilieren, und ich bekomme einen
> Fehler wegen jenen Codeabschnitt:
> ERROR: register number above 15 required

gewisse(die meisten) AVR opcodes koennen nicht mit jedem register..

>
> Kann Jemand mir helfen?

Nein. Musst du wohl oder uebel AVR instruction datenblaetter und gcc 
dokumentation durchlesen.

von Thomas K. (thomas_k39)


Lesenswert?

Die Zeile

> adc %A3, %2

ist sehr verdächtig.

Auf der linken Seite muss ein Register stehen. Vermutlich ist Dir beim 
Kopieren ein Fehler passiert.

Ansonsten einen Link auf Deine Quelle (wo Du das Codefragment her hast) 
posten.

von Uwe (Gast)


Lesenswert?

Man kann auch einfach *.s Assembler Files schreiben und die Assembler 
funktionen als .global markieren ( um die aufrufkonvention musst du dich 
kümmern, kann man aber nachlesen). Dann muss man im C file diese nur 
noch als extern kennzeichnen und den header einbinden mit den richtigen 
Rückgabewerten und Parametern.

von spontan (Gast)


Lesenswert?

Wenn der Prozessor nur damit beschäftigt ist diesen Sinus zu erzeugen 
und nix anderes macht, so seh ich dsa als recht sinnlos an. Da tuts ne 
alte Wien-Brücke schöner.


Also Prozessor mit Zeit für andere Dinge -> nimm einfach einen flotteren 
µC und alle Probleme sind nichtig.

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.