hy
Ich möchte mit dem 16Bit Timer (MEga8 8MHz) ein 4kHz Signal genieren,
das an OC1 ausgegeben werden soll. Leider beginnnt mein Programm immer
wieder von vornen hinter Sei()...
wo liegt der Fehler?
TCCR1A = _BV(COM1A0);
TCCR1B = _BV(WGM12) | _BV(CS11);
TIMSK = _BV(OCIE1A);
OCR1A = 0x7E;
sei();
Wenn Du keinen kompletten Code schickst, kann man nur Vermutungen
anstellen. Meine Vermutung: Du hast keine Interrupt-Routine definiert
oder hast sie falsch definiert, so dass bei Auftreten des Interrupts der
"Spurious Interrupt Handler" aufgerufen wird, der zu einem RESET führt.
ja das könnte gut sein.
ich dachte der Timer macht alles selber im Hintergrund, bzw setzt den
Port selber um durch das toggeln, ohne das ich es extra aufrufen muss...
Sonst müsste ich ja mit Signal oder so wieder extra eine Routine
aufrufen...
Wenn Du den Interrupt aktivierst, brauchst Du auch einen
Interrupt-Handler. Wenn Du nur einen Pin toggeln willst, dann
deaktiviere den Interrupt. Den brauchst Du dafür nicht. Also lass die
Zeile
> ich dachte der Timer macht alles selber im Hintergrund, bzw setzt den> Port selber um durch das toggeln, ohne das ich es extra aufrufen muss...
Das kann er auch.
Nur: Wenn du den zugehörigen Interrupt
aktivierst
TIMSK = _BV(OCIE1A);
wird der Interrupt Handler auch aufgerufen.
Wenn es keinen gibt -> Reset
irgendwie unterbricht ADMUX bzw ADCRSA meinen Timer A und setzt ihn auf
NUll bevor 0x7C erreicht ist...!!
nutzen die beide den selben? wie kann ich es umgehen?
1
ADMUX=0;// AD Kanal A.0
2
ADCSRA|=_BV(ADSC);// AD Messung starten
3
while(ADCSRA&_BV(ADSC))// bis ein Wert eingelesen ist warten
> nutzen die beide den selben?
Den selben was? Der ADC hat mit dem Timer nichts zu tun. Was gibt Dir
die Gewissheit, dass der Timer tatsächlich zurückgesetzt wird? Bei dem
Codeschnipsel gilt selbiges wie oben: Ohne kompletten Code kann da
niemand was zu sagen, außer vielleicht, dass das Starten des ADC
anscheinend korrekt ist.
Übrigens: Wer ist "Timer A"? Beim AVR gibts Timer 0, Timer 1... aber
keinen Timer A. Meinst Du vielleicht "Compare A"?
Also im debugger funktioniert das ganze wunderbar. Er Setzt den OC1
Ausgang immer schon hin her. aber in Realität bleibt es konstant auf 5
V!!
Wieso? Ich kann keine Fehler entdecken...
oh man vielen Dank!!! Hab nicht gesehen das ich PORTB anstatt DDRB
geschrieben hatte
jetzt klappt es !!
Ja mit den Kontanten muss ich noch alles ändern.
Die Umwandlung in char dauert leider einfach viel zu lange.
dtostrf(LF,6,4,LFC);
1. Wie kann ich sie als INT übertragen? wollte die zahl *100 nehmen und
dann übertragen ohne Komma...
Oder kann ich eine int Zahl 0-3000 in Hex umwandeln und dann direkt als
Binärcode per UART senden...?
oder geht das einfacher?
> 1. Wie kann ich sie als INT übertragen? wollte die zahl *100 nehmen und> dann übertragen ohne Komma...
Hatten wir das nicht vor Kurzem schon mal.
Der Weg den ich gehen würde:
Von vorne herein gar keine double nehmen, sondern alles
als Fixed Point Arithmetik aufbauen.
Fixed Point Arithmetik: Das kennst du schon nur war es dir
bisher nicht bewusst :-)
Angenomen du willst mit Kilometer rechnen.
Du rechnest zb 3.456 Kilometer plus 2.729 Kilometer
3.456
2.729
-------
6.185 Kilometer
Dazu brauchst du natürlich Gleitkomma, also double.
Aber warum eigentlich. Du kannst das Ganze auch in Meter
rechnen:
3456 Meter
plus 2729 Meter
-----
6185 Meter
Wenn deine Ausgabe unbedingt Kilometer sein müssen, dann
reicht es doch die 4185 Meter von oben zu nehmen und
während der Ausgabe nach der Tausenderstelle ein Komma
einzuschmuggeln.
Du musst aber nicht Meter nehmen. Du könntest auch Millimeter
nehmen. Oder, weil du weist dass du nie über 10 Kilometer
hinauskommen wirst, alles in 1/3000 Kilometer ausdrücken.
10 Kilometer sind dann ein Zahlenwert von 30000
1 Kilometer wäre dann 3000
3.456 Kilometer wären dann 10368 (3.456 * 3000)
2.729 Kilometer wären dann 8187 (2.729 * 3000)
Die Summe ergibt 1855, was nach Rückrechnung (/3000) wieder
die bewussten 6.185 Kilometer ergibt.
Natürlich wird man nicht mit 3000 arbeiten. Wenn schon dann hat
man meist glatte 10er Potenzen oder 2er Potenzen für sowas.
Aber das Prinzip ist einfach: Untersuche deine Formeln, ob die
Genauigkeit reicht, wenn du alles mal 1000 nimmst und dafür
in int oder long rechnen kannst (long müsste auf jeden Fall
ausreichen).
Anstatt
T= (T*Faktor)*28.869-27.713;
rechnest du zb
long Faktor = 5; // 0.0048828125 * 1000, gerundet
T = ( T Faktor 28869L ) / 1000 - 27713L;
Falls die Genauigkeit mit einem 1000er Vielfachen nicht
reicht (vorher untersuchen, ob das so ist), dann nimmst
du halt noch eine Kommastelle dazu und machst ein 10000er
Vielfaches.
Bei der Ausgabe dann noch an der richtigen Stelle ein
Komma einschmuggeln und du bist intern die double los,
fährst maximalen Speed und am anderen Ende der UART
kann niemand den Unterschied feststellen.
> Oder kann ich eine int Zahl 0-3000 in Hex umwandeln und dann direkt> als Binärcode per UART senden...?
Du brauchst nichts in HEX umwandeln. Du kannst auch die
Bytes direkt senden. Kommt halt immer darauf an, wer
am anderen Ende der UART lauscht. Wenn das ein Programm
ist, dann ist das kein Problem (double würde ich so nicht
verschicken, da es verschiedene Gleitkommaformate gibt).
Wenn da aber ein Mensch sitzt, und sei es nur um während
der Entwicklung die Übertragung zu kontrollieren, dann
würde ich ihm das nicht antun.
also als Hex senden klar ist nix sehr menschenfreundlich.
aber wie kann ich INT Zahlen versenden? das würde schon reichen.
0-65536 würde ja reichen und so hät ich einen 16bit Wert.
Senden kann ich ja jeweils 8Bit.
also müsste ich das ganze aufteilen und zwei teile senden...