Hallo
ich benutze AVR Studio mit WinAVR.
Ich habe einen 8 Prescaler mit einem OCR0A-Wert.
Das Problem ist dass es den Interrupt immer bei 256 auslöst.
Mich würde interessieren wie ich bei AVR Studio die Variablen
besichtigen kann um zu sehen welcher Wert zugewiesen wurde.
MfG
Wie meinst du das?
Das Programm wird in diesen Zeilen ausgeführt.
Meine Vermutung ist dass man Register nicht in Dez. ausgeben kann.
1
unsignedintvariable
2
3
zahl=TIME*1000/(8*125);
4
funktion(8,zahl);
5
6
7
funktion(....,unsignedintzahl)
8
{
9
OCR0A=zahl;
10
}
Ich vermute der Fehler liegt bei der zahl. Sie wird in INT berechnet und
dann weise ich die Zahl dem Register OCR0A zu.
Brauchen Register eine HEX-Zahl. Gibt es einen Befehl zur umformung von
DEZ in HEX
Zunächst mal Dez und Hex ( und auch binär) sind nur verschiedene
Darstellungen für das selbe Bitmuster. Ist also nur einen andere
schreibweise.
Die Variable Zahl wird in der Tat wegoptimiert, da der Compiler erkennt,
dass sie nicht benötigt wird, weil der Wert konstant ist. Also der
Compilier verwendet statt der Variable direkt den Wert, den du
zugewiesen hast. Das darf der Compiler machen, solange die Funktion des
Programms die selbe bleibt. Das einzige was du von der Optimierung
(neben einem kleineren Programm) mitbekommst, ist eben, dass du die
Variable nicht mehr im debugger anschauen kannst. Dafür gibt es nun 2
lösungen:
1) du schaltest in den Projekteinstellungen die Optimierung komplett aus
(-O0). Dadurch wird nichts mehr wegoptimiert, aber das Programm wird
auch größer.
2) du deklarierst die Variable zum Debuggen als volatile. Das verhindert
unter anderem, dass die Variable wegoptimiert wird.
Hex, Dezimal und Binär ist alles nur eine jeweils andere Darstellung
einer Zahl. Ich kann jede ganze Zahl in allen Schreibweisen
darstellen.
Als char betrachtet gibt es dafür nur 8 Bit. Schön ist, dass diese 8 Bit
in 2 Nibble passen, von denen wieder jedes einzelne die Hälfte einer
Hex-Zahl ist.
0xff = 0b11111111 = 255 = -1
0x07 = 0b00000111 = 7 = +7
0xf0 = 0b11110000 = 248 = -16
usw. usf.
Ein short (=int bei AVR) sind dann nur 2 Bytes hintereinander und
demnach 4 Hex-Zeichen.
0xffff = 0b1111111111111111 = 65535 = -1
0x0007 = 0b0000000000000111 = 7 = +7
0xfff0 = 0b1111111111110000 = 65520 = -16
TIME ist ein irgendein Wert in us.
Irgendwas stimmt mit der Berechnung nicht.
Habe zb. 90 genommen. Beim Prescaler 8 sollte der OCR0A Wert auch 90
sein.
Bei 8MHz
OCR0A= 90*1000/ (8*125)= 90
Zugewiesen wird aber 0x18
90*1000 ist ein bischen zu groß, als das diese Berechnung im Zahlenraum
int durchgeführt werden könnte.
int endet bei 32767. Sobald du drüberkommst und sei aus auch nur bei
einem Zwischenergebnis, hast du verloren :-)
Berechnung ein wenig umstellen und schon geht sich alles aus.
> OCR0A= 90*1000/ (8*125)= 90
Frei nach Karl heinz Buchegger könntest du es so machen:
OCR0A = (90*(1000/8))/125;
> OCR0A= 90*1000/ (8*125)= 90
Frei nach Stefan Ernst: warum schreibst du nicht einfach
OCR0A = 90;
Stefan Ernst schrieb:
> Karl heinz Buchegger schrieb:>>> Berechnung ein wenig umstellen und schon geht sich alles aus.>> "Umstellen"? Wie wäre es mit "weglassen"? ;-)
Er wird schon seinen Grund haben :-)
Und sei es nur, daß er den Vorteiler einfach wechseln kann, was ja
grundsätzlich nicht schlecht ist.
Danke für die Hilfe. Das int war der Fehler.
Für unterschiedliche Werte brauche ich unterschiedliche Prescaler.
Das einzige was ich noch machen könnte ist alle zb. 10us einen Interrupt
auslösen.
Bei 1000 us würde ich da aber viele Interrupts auslösen aber beinahe
nichts machen.
Selbes Problem
else if( (ZEIT > 8000) && (ZEIT <= 30000) )
{
TCCR0B= 0x05; //CS=5 => 1024
nummer = ZEIT*8/1024;
Wenn ZEIT minmial den Wert 8000 hat, dann ergibt 8000 * 8 ein
Zwischenergebnis von 64000. Damit bist du über den magischen 32767
drüber :-)
(Was sagt eigentlich dein C-Buch zum Thema 'long')
Und bitte: Übertrage deinen Code per Copy&Paste hier ins Forum. Es ist
ziemlich mühselig, deine wirklichen Probleme von den Tippfehlern zu
unterscheiden.
AVR schrieb:
>> Vielleicht ist es ein Fehler hier>>variable = TIME*8/1024;> weil TIME ein Integer ist.
Morgen früh, gleich als allererstes, gehst du in die nächste
Buchhandlung und besorgst dir ein C-Buch.
Das sind alles Grundlagen. Und zwar von der Sorte, die in jedem noch so
grindigen C-Buch in den ersten 4 Kapiteln (von 25) erklärt werden.
> TCCR0B= 0x05;> variable = TIME*8/1024;
Zu dem Zeitpunkt, zu dem an 'variable' zugewiesen wird, ist das Kind
längst in den Brunnen gefallen.
TIME * 8
interessiert nicht die Bohne, dass du das Endergebnis an einen unsigned
long zuweist. TIME ist ein unsigned int, 8 ist ein int. Also wird in
unsigned int gerechnet und das Ergebnis ist wieder ein unsigned int.
Was anderes ist allerdings
TIME * 8L
TIME ist ein unsigned int, 8 ist jetzt ein long. Also wird in long
gerechnet.
TIME * 8UL
Jetzt ist 8 ein unsigned long und es wird im Zahlenraum unsigned long
gerechnet.
Wieso hältst du dich eigentlich nicht an die übliche Konvention, dass
Namen, welche komplett in Grossbuchstaben geschrieben sind,
ausschliesslich für Makros reserviert sind.
Was sagt eigentlich dein Compiler dazu?
> Morgen früh, gleich als allererstes, gehst du in die nächste> Buchhandlung und besorgst dir ein C-Buch.
Ja, das wäre wohl das Beste...
BTW:
Es ist oft einfacher, das C-Programmieren am PC zu lernen. Und wenns
dort klappt, dann erst in die Einschränkungen der uC-Welt einzusteigen.
Hallo
Könnte einen Denkanstoß gebrauchen. Es heißt man soll möglichst viel in
den Hauptcode verlagern und nicht im ISR lassen. Habe es so versucht
aber der Timer wird nicht richtig ausgeführt.
delay_t1_s geht das Programm nur einmal durch und bleibt dann in der
ISR-Funktion.
Ich wollte dass alle 100ms die innere for-Schleife um 1 hochzählt. Wenn
Da scheint ein grundsätzliches Misverständnis vorzuliegen.
Der Timer arbeitet völlig unabhängig von allem anderen.
Wenn du also etwas alle 100ms ausführen lassen willst, dann setzt du den
Timer so auf, dass er dir alle x Millisekunden einen Interrupt auslöst
(zb. weil der Timer einen Overflow generiert). In der ISR zählst du mit,
wie oft die ISR aufgerufen wurde und leitest davon die 100 Millisekunden
ab.
Wird dein Timer zb alle 0.5 Millisekunden aufgerufen, dann muss
innerhalb der ISR eine Variable bis 200 zählen, damit 100 Millisekunden
vergangen sind.
Hallo Karl Heinz
hast du gemeint dass der Code ca. so zu programmieren wäre. Mein Problem
ist dass ich nicht schauen kann wieviel Zeit vergeht weil AVR Studio in
der Zeile if(zaehler == 2) hängen bleibt und im us-Takt weiter zählt. Es
springt komischer Weise nicht ins ISR und berechnet die Zeit.
Gibt es hier irgendwo Infos zur Programmierung eines Callbacks.
LOL
Das die Funktionen nicht die Selbstzerstörung aktivierer war mir schon
klar. Nur, was machen die? Code!
Wir betreiben hier Fehlersuche. Da kann alles relevant sein!
>Und was zum T.... verbirgt sich hinter all den timer Funktionen?
Dachte du wolltest wissen was die Funktionen machen.
Habe jetzt länger getestet. Der Simulator hat sehr lange gebraucht beim
hochzählen deshalb blieb er bei der Zeile "if (zaehler == 2)" die ganze
Zeit hängen.
Danke für die Hilfe.