Forum: Mikrocontroller und Digitale Elektronik Timer ATMEGA 2560


von Gary (Gast)


Lesenswert?

Hallo

Ich versuche den Timer5 des ATMEGA 2560 zu nutzen, doch klappt das 
leider nicht. Ich möchte, dass die ISR jede Sekunde einmal aufgerufen 
wird. Bisher habe ich folgendes gemacht:
1
#define wait_ms 1000
2
3
void setup() {
4
  //Init Serial
5
  Serial.begin(9600);
6
7
  //init Timer
8
  TCCR5B |=(1<<CS51);                         //8 prescaler -> 0.5us cycles
9
  TIMSK5 |=(1<<ICIE5)+(1<<OCIE5A);            //Interupt enable and compare A enable
10
  OCR5AH = (wait_ms*1000*1000/500)>>8;
11
  OCR5AL =(wait_ms*1000*1000/500);
12
  TCNT5=0;
13
  sei();                                      //global Interrupt
14
}
15
16
void loop() {
17
18
}
19
20
ISR(TIMER5_COMPA) {
21
    Serial.write('x');
22
    TCNT5=0;
23
}

Leider gibt es mir keinen Interrupt. Habe ich den ISR Interrupt Vektor 
falsch benannt?

Gruss Gary

von S. Landolt (Gast)


Lesenswert?

Verstehe ich das richtig: 10^9/500 für OCR5AL?

von Karl M. (Gast)


Lesenswert?

Hallo,

da hast Du nicht in das Datenblatt des AVR gesehen, und dir fehlen 
grundlegende C Kenntnisse.

Bit Manipulation. Bit-Masken werden über ODER (OR) verknüpft.

Wenn man diesen Interrupt ICIE5 freigibt, dann sollte man auch einen 
Interrupthandler dazu linken.

Im Datenblatt steht auch, wie man den CTC Modus aktiviert.

Dazu muss man die richtigen Bits in den Registern TCCR5A und TCCR5B 
setzen.
Mode 4: CTC WGM5[3:0] = 0100

Dann muss man auch OCR5A Register für den als TOP-Wert wählen.

Auch passen bei 8MHz = 8*10⁶Hz mit einem Vorteiler von 8, also Timer5 
Clock = 8*10⁶Hz /8 = 1*10⁶Hz diese nicht in einen 16Bit Zähler (OCR5A).

Maximal also: 2¹⁶-1 = 65535

Somit muss man den Zähler 5 noch um einen Softwarezähler um weitere Bits 
erweitern, oder einen anderen Vorteiler (Prescaler) verwenden.
Mit T5 Prescaler = 1024 ergibt sich:
T5 PRELOAD = uint16_t(1.0 * 8*10⁶ /1024 +.5) -1 = 7812 ; mit Aufrunden
Der Fehler ist dann minimal.

Deine Interrupt Service Routine ist fehlerhaft, man nutzt dort kein 
Serial.write() und setzt nicht das Zählerregister 5 auf 0.

von Gary (Gast)


Lesenswert?

S. Landolt schrieb:
> Verstehe ich das richtig: 10^9/500 für OCR5AL?

Ich denke schon, 1sekunde / 500ns, da 0.5us cycles.

von Karl M. (Gast)


Lesenswert?

S. Landolt schrieb:
> Verstehe ich das richtig: 10^9/500 für OCR5AL?

Ja der Wert ist zwar flasch (-1) fehlt, abe der Compiler verwendet nur 
die untersten 8Bit.
Man könnte das auch als uint8_t(10^9/500) schreiben und die -1 nicht 
vergessen.

von Sascha (Gast)


Lesenswert?

ICIE ist imho Input Capture Interrupt Enable, was du suchst ist 
vielleicht der Timer Overflow bzw der Timer Output Compare A/B 
Interrupt.

Input Capture findet am ICP Pin statt.

von S. Landolt (Gast)


Lesenswert?

Karl M. schrieb:
> abe der Compiler verwendet nur die untersten 8Bit.
Und der meldet bei dieser Konstantenzuweisung keinen Overflow, wie es 
z.B. mein Assembler macht?

von N.Sekan (Gast)


Lesenswert?

OCR5AH = (wait_ms*1000*1000/500)>>8;
  OCR5AL =(wait_ms*1000*1000/500);

???

bist du dir sicher das, dass richtig ist ?
Nutz man nicht den Wert des Quarzes als Basis der Berechnung ?
Muss der Wert nicht bei jeder ISR wieder hinterlegen werden ?
ich denke mal eher so:

OCR5AH = (wait_ms*1000*1000/500)<<8;
OCR5AL =(wait_ms*1000*1000/500)&0xFF;

oder eher so:
bei 16MHz F_CPU
OCR5AH = (65535-(F_CPU/8/100))<<8;
OCR5AL =(65535-(F_CPU/8/100))&0xFF;
macht aber dann alle 10ms die ISR
Also, größeren Teiler !!

ähm... :
1000*1000*1000/500=2000000 ???
sind doch mehr wie 16bit !?

P.S.
Vorher mal auf nem Blatt Papier mal Rechnen ,
Was macht der ATmeag da eigentlich ?
Wie viele Impulse bekomme ich bei einem Teiler von zum Beispiel 8 in den 
Timer , pro Sekunde ???

MFG

von Gary (Gast)


Lesenswert?

N.Sekan schrieb:
> Nutz man nicht den Wert des Quarzes als Basis der Berechnung ?

Dieser Wert ist in den 500 eingeflossen: die 500 stellen die 500ns cycle 
dar, aufgrund des prescalers 8.

N.Sekan schrieb:
> 1000*1000*1000/500=2000000 ???
> sind doch mehr wie 16bit !?

Das stimmt, habe das nun geändert, geht aber immer noch nicht.
1
#define wait_us 1000000
2
3
void setup() {
4
  //Init Serial
5
  Serial.begin(9600);
6
7
  //init Timer
8
  TCCR5B |=(1<<CS52);                         //256 prescaler -> 16us cycles
9
  TIMSK5 |=(1<<ICIE5)+(1<<OCIE5A);            //Interupt enable and compare A enable
10
  int val = wait_us/16-1;
11
  OCR5AH = (val)>>8;
12
  OCR5AL = val;
13
  TCNT5=0;
14
  sei();                                      //global Interrupt
15
}
16
17
void loop() {
18
19
}
20
21
ISR(TIMER5_COMPA_vect) {
22
    Serial.write('x');
23
    TCNT5=0;
24
}

von Karl M. (Gast)


Lesenswert?

Gary,

ich habe Dir alle Fehler aufgezeigt und auch zwei Beispielrechnungen 
gegeben, wenn Du es nicht für nötig ansiehst im Datenblatt das zu 
verifizieren und auch zu verwenden, na dann..

Dann brauchst Du hier auch nicht mehr schreiben.

Selbst Die Formel für die verschiedenen Zählereinstellungen stehen im 
Datenblatt.

20.4.2 Clear Timer on Compare Match (CTC) Mode
Die Formel ist als "waveform frequency" angegeben !
Eine Formel umstellen wird bestimmt noch klappen.

von Joachim B. (jar)


Lesenswert?

>#define wait_us 1000000

wenn ich mich recht erinner dann doch nur so:

#define wait_us 1000000UL

sonst kommt das eh nicht an

und:

>int val = wait_us/16-1;

dann so

int val = (wait_us/16UL)-1UL;

oder

int val = (int)((unsigned long)(wait_us/16UL)-(unsigned long)1UL);

wenns richtig ankommen soll, evtl. habe ich irgendwo doppelt gemoppelt, 
aber vergessene cast sind schlimmer

von N.Sekan (Gast)


Lesenswert?

wie gesagt :
Mit wie viel MHZ läuft der Chip ?

bei 16MHz
durch 256 = 62500 Takte pro Sekunde
also muss 62500 als Vergleichswert im OCRA stehen !
Denk ich mal

Datenblatt mal lesen !!!
steht meist alles drin !!

von Karl M. (Gast)


Lesenswert?

C-Grundlagen !

was kommt hier wohl bei 16 Bit Arithmetik heraus ?
1
#define wait_us 1000000
2
int val = wait_us/16-1;

von Sascha (Gast)


Lesenswert?

Du kannst übrigens in C direkt OCR5A = uint16_t value schreiben, also 
z.B. OCR5A = 65000;.

Weiterhin wie bereits erwähnt: Du hast den Input Capture Interrupt an! 
Aber du hast nur den COMPA Interruptvektor definiert.
ISR gehört btw. über die main() wegen C forward Deklaration aber kann 
sein dass das in C++ umwichtig ist.

von Sascha (Gast)


Lesenswert?

Karl M. schrieb:
> C-Grundlagen !
>
> was kommt hier wohl bei 16 Bit Arithmetik heraus ?#define wait_us
> 1000000
> int val = wait_us/16-1;

62499, was ein valider Wert für OCRxA ist. Aber wenn man es in einen int 
packt, führt der Überlauf zu...32767 oder so? In dem Fall wäre der 
Interrupt einfach doppelt so schnell wie gewollt. Das kanns nicht sein.

von Gary (Gast)


Lesenswert?

Ok, ich habe versucht mal alles zu berücksichtigen, doch es klappt immer 
noch nicht. Nur bei einem prescaler kleiner 64 gibt es mir 'x' aus.
1
#define wait_us 1000000UL
2
#define F_CPU 16000000UL
3
4
bool new_data=0;
5
6
void setup() {
7
  //Init Serial
8
  Serial.begin(9600);
9
10
  //init Timer
11
  TCCR5B |=(1<<CS52)+(1<<CS50)+(1<<WGM52);          //1024 prescaler -> 64us cycles, activate CTC
12
  TIMSK5 |=(1<<OCIE5A);                             //Interupt enable and compare A enable
13
  uint16_t val = (wait_us/64UL)-1;
14
  OCR5A = val;
15
  sei();                                            //global Interrupt
16
}
17
18
void loop() {
19
    if(new_data) {
20
        new_data=0;
21
        Serial.write('x');
22
    }
23
}
24
25
ISR(TIMER5_COMPA_vect) {
26
    new_data=1;   
27
}

von Sascha (Gast)


Lesenswert?

Nur mal so interessehalber...was hindert dich daran, deine Setup-Routine 
mal mit Serial.Write zuzupflastern und bei jeder Zeile zu gucken was 
hinten rauskommt? Das ist ein Debugging-Tool, das sollte man zum 
debuggen verwenden!

Fuse-Settings wären ganz gut, Vielleicht ist die Watchdog-Fuse gesetzt. 
Aber der Rest ist auch interessant.



  uint16_t val = (wait_us/64UL)-1;
  OCR5A = val;

Geht auch OCR5A = 15624;.
wait_us/64UL (unsigned long! Für 6 bit!) wird beim kompilieren eh genau 
dazu.

Bist du dir sicher, dass es nur mit Werten kleiner 64 geht?

  TCCR5B |=(1<<CS52)+(1<<CS50)+(1<<WGM52);

Das mit den Pluszeichen wäre mir neu. Guck dir mal das AVR-GCC Tutorial 
OBEN LINKS an.

von S. Landolt (Gast)


Lesenswert?

> Das mit den Pluszeichen wäre mir neu.
Au contraire, das ist steinalt, so habe ich es vor Ewigkeiten in der 
Schule in Schaltalgebra gelernt.

von Karl M. (Gast)


Lesenswert?

Mach doch bitte mal die,

OCRA Berechnung richtig ! Die Formel steht im Datenblatt !
1
bool new_data=0;
 ist bezgl. Interruptbetrieb nicht richtig.
Stichwort: volatile

von Karl M. (Gast)


Lesenswert?

Noch eine Anmerkung,

guter Stil ist es alle relevanten Register von Timer5 zu initialisieren.

TCCR5A = ...
dort finden wir die Bits WGM51 WGM50.

von Gary (Gast)


Lesenswert?

Karl M. schrieb:
> Ja der Wert ist zwar flasch (-1) fehlt, abe der Compiler verwendet nur
> die untersten 8Bit.

Das scheint zu stimmen, TCNT5 geht nur bis 255. Der Timer5 ist aber ein 
16bit Timer?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Au contraire, das ist steinalt, so habe ich es vor Ewigkeiten in der
> Schule in Schaltalgebra gelernt.

Die hat aber nichts mit der Programmiersprache C zu tun. ;-)

Allerdings ist das in diesem Falle egal, wenn man zwei Zahlen addiert,
in denen je ein Bit gesetzt ist, welches in beiden Zahlen verschieden
ist (das ist hier gegeben), dann hat eine Addition das gleiche Ergebnis
wie eine VerODERung.

Ja, volatile für die Auswertevariable ist auf jeden Fall Pflicht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gary schrieb:
> uint16_t val = (wait_us/64UL)-1;

Pure Logik sollte dich stutzig werden lassen: da taucht nirgends ein
F_CPU auf, aber ganz offensichtlich sollte der Wert von der Frequenz
abhängen.

von Karl M. (Gast)


Lesenswert?

Dann ist es unsinnig den Timer5 schon zu starten
1
TCCR5B |=(1<<CS52)+(1<<CS50)+(1<<WGM52);
bevor er vollständig initialisiert und konfiguriert ist.

Und so schreibe ich den TOP-Zählerwert von Timer5 richtig hin:
1
#include <stdint.h>
2
const uint32_t T5_FREQUENCY = 1ul; // Hz
3
const uint32_t T5_PRESCALER = 1024ul;
4
const uint32_t T5_PRELOAD = uint32_t(1.0 * F_CPU /T5_PRESCALER /T5_FREQUENCY+.5)-1;
5
if (T5_PRELOAD >= 65536) 
6
{
7
 // error("T5 Prescaler !");
8
}
9
OCR5A = T5_PRELOAD;
10
; wichtig T5_PRELOAD < 65536 !

von S. Landolt (Gast)


Lesenswert?

> Die hat aber nichts mit der Programmiersprache C zu tun. ;-)
> Allerdings ist das in diesem Falle egal

Wir wollen Assembler nicht vergessen.
Und einen kleinen Unterschied gibt es: ein Zehnfingerschreiber tut sich 
mit dem '+' leichter als mit dem '|'.

von S. Landolt (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Die hat aber nichts mit der Programmiersprache C zu tun. ;-)

Übrigens ist diese Bitsetzerei in den SFRs sehr wohl reinste 
Schaltalgebra, was sonst?

von Sascha (Gast)


Lesenswert?

S. Landolt schrieb:
>> Die hat aber nichts mit der Programmiersprache C zu tun. ;-)
>> Allerdings ist das in diesem Falle egal
>
> Wir wollen Assembler nicht vergessen.
> Und einen kleinen Unterschied gibt es: ein Zehnfingerschreiber tut sich
> mit dem '+' leichter als mit dem '|'.

Eigentlich nicht, aber ich habe ein QWERTY Keyboard auf meinem Thinkpad 
drauf und da gibts die Taste nicht. Daher trotzdem danke.

Und ja: Es ist boolsche Algebra und ja, das Pluszeichen ergibt Sinn. Ich 
habe ja auch nur gesagt, dass es mir NEU ist.

von Gary (Gast)


Lesenswert?

Habe das nochmal überarbeitet, doch am Wert im OCR5A liegt es nicht, der 
ist richtig. Sobald der prescaler zu hoch ist, ändert sich der Wert in 
TCNT5 nicht mehr.
1
#define wait_us 1000000UL
2
#define F_CPU 16000000UL
3
#define prescaler 1024UL
4
5
volatile bool new_data=0;
6
int val;
7
8
void setup() {
9
  //Init Serial
10
  Serial.begin(9600);
11
12
  //init Timer
13
  val = int(wait_us*(F_CPU/1000000)/prescaler+0.5)-1;
14
  if(val > 65536) {
15
      Serial.write("error");
16
  } else {
17
    TCCR5B |=(1<<CS52)+(1<<CS50)+(1<<WGM52);          //8 prescaler -> 0.5us cycles, activate CTC
18
    TIMSK5 |=(1<<OCIE5A);                             //Interupt enable and compare A enable
19
    OCR5A = val;
20
    sei();                                            //global Interrupt
21
  }
22
}
23
24
void loop() {
25
    if(new_data) {
26
        new_data=0;
27
        Serial.write('x');
28
    }
29
}
30
31
ISR(TIMER5_COMPA_vect) {
32
    new_data=1;   
33
}

von Karl M. (Gast)


Lesenswert?

Diese Ignoranz !

Ich habe Dir die Formel noch hingeschrieben und was machst Du daraus ?
Code der falsch ist !

Was steht wohl in val ?

Welchen Prescaler verwendest Du ?

//8 prescaler -> 0.5us cycles, activate CTC

von Gary (Gast)


Lesenswert?

Karl M. schrieb:
> Code der falsch ist !

Der Kommentar dazu ist falsch, der Wert in val richtig!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> Übrigens ist diese Bitsetzerei in den SFRs sehr wohl reinste
> Schaltalgebra, was sonst?

Trotzdem musst du dich bei der Notation an die Regeln der verwendeten
Programmiersprache halten.

0x20 + 0x20 ist eben etwas anderes als 0x20 | 0x20.

von Sascha (Gast)


Lesenswert?

if(val > 65536) {
      Serial.write("error");

Also wenn val ein int ist, ist der auf AVR wenn ich mich nicht irre ein 
signed int 16 bit. Wie kann der bitte größer als 65536 werden? Nichtmal 
ein uint16_t könnte das!

  val = int(wait_us*(F_CPU/1000000)/prescaler+0.5)-1;

Hier wüsste ich selbst nicht so wirklich was dabei rauskommt. Versuch:
wait_us*(F_CPU/1000000)= 16 Mio. Furchtbar schlau, erst eine Million 
wegzudividieren, um sie danach wieder draufzumultiplizieren.

16 Mio / prescaler = 15625

+0.5 = vermutlich 15625.

Das ganze in einen int casten (wobei ein cast eher 
(uint16_t)ZuCastenderWert) ist): 15625

1 abziehen: 15624. Wie gut dass ich das vor einer Stunde schon so 
geschrieben hatte. Systematisch Fehlerquellen zu eliminieren (wie deine 
komplizierten Berechnungen) ist nicht so dein Ding, was.



Und was hindert dich an Serial.write(val)? Oder falls das nicht klappt, 
die bekannte itoa-Angelegenheit.

von Gary (Gast)


Lesenswert?

Ich glaube ich habe den Fehler gefunden, OCR5AH bleibt immer 0, egal wie 
ich die Zuweisung mache:
1
OCR5AH=val>>8;
2
OCR5AL=val;
1
OCR5A=val;
1
OCR5A=15624;

OCR5AH bleibt 0.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gary schrieb:
> OCR5AH bleibt immer 0, egal wie ich die Zuweisung mache:

Glaub' ich nicht.

Lad' doch mal das erzeugte ELF-File mit hoch.

Wenn es so wäre, müsste übrigens alles trotzdem noch funktionieren,
nur halt sehr viel schneller als erwartet.

: Bearbeitet durch Moderator
von Karl M. (Gast)


Lesenswert?

Garry,

schreibe doch bitte die Timer 5 OCR5A Init genau so und berichte bitte:
1
; im kopfbereich
2
#include <stdint.h>
3
4
; im code direkt nacheinander.
5
const uint32_t T5_FREQUENCY = 1ul; // Hz
6
const uint32_t T5_PRESCALER = 1024ul;
7
const uint32_t T5_PRELOAD = uint32_t(1.0 * F_CPU /T5_PRESCALER /T5_FREQUENCY+.5)-1;
8
OCR5A = T5_PRELOAD;

Dann poste bitte das Assemblerlisting hier.

von Gary (Gast)


Angehängte Dateien:

Lesenswert?

Karl M. schrieb:
> schreibe doch bitte die Timer 5 OCR5A Init genau so und berichte bitte:

Habe das nun so gemacht und hier dazu noch das .ELF

OCR5AH bleibt immer noch 0.

von S. Landolt (Gast)


Lesenswert?

> OCR5AH bleibt immer noch 0.
Wie lesen Sie das aus? Muss nicht, auch in c, die Reihenfolge 
eingehalten werden, erst L, dann H?

von Gary (Gast)


Lesenswert?

S. Landolt schrieb:
> Wie lesen Sie das aus? Muss nicht, auch in c, die Reihenfolge
> eingehalten werden, erst L, dann H?
1
char buff[8];
2
itoa(OCR1AH,buff,10);
3
Serial.println(buff);

von S. Landolt (Gast)


Lesenswert?

Dann schreiben Sie mal:
itoa(OCR1AL,buff,10);
itoa(OCR1AH,buff,10);

von Gary (Gast)


Lesenswert?

S. Landolt schrieb:
> itoa(OCR1AL,buff,10);
> itoa(OCR1AH,buff,10);

Das gibt mit 8 für OCR1AL und 0 für OCR1AH.
Wenn ich OCR1A=256 setzte, gibt mir das 0 für OCR1Al und 0 fürOCR1AH,
als wäre kein OCR1AH vorhanden.

Mir ist aufgefallen, dass bei meinem Arudino Mega 2560 made in china 
draufsteht, sollte doch made in italy sein, habe den auf ebay gekauft 
und der war nicht gerade billig. Wenn es sich um eine Fälschung handelt, 
ist es möglich, dass die irgendetwas verbaut haben, dass nur 8bit Timer 
hat?

von S. Landolt (Gast)


Lesenswert?

Jetzt bin ich etwas irritiert (und war auch reingefallen): nicht eins, 
sondern fünf: OCR5A!?

von Gary (Gast)


Lesenswert?

S. Landolt schrieb:
> Jetzt bin ich etwas irritiert (und war auch reingefallen): nicht eins,
> sondern fünf: OCR5A!?

Sorry, habe das nur zum testen geändert, auch wenn ich alles auf Timer 5 
einstelle ändert sich nichts.

von S. Landolt (Gast)


Lesenswert?

Bevor ich mich in die Fasnet (sic!) verabschiede, eine Bitte:

OCR5A= 0x1234;
itoa(OCR5AL,buff,10);
Serial.println(buff);
itoa(OCR5AH,buff,10);
Serial.println(buff);

Welche Ausgabe liefert dies?



(Hoorig isch die Katz)

von Felix Adam (Gast)


Lesenswert?

Zunächst solltest du deine Registerzugriffe wie folgt abändern, da 
dieses Verodern mit dem zuvor enthaltenen Inhalt zu Fehlern führen kann. 
Dabei bitte auch Jörgs Anmerkung mit einarbeiten:
1
TCCR5A = 0;
2
TCCR5B = (1<<CS52) | (1<<CS50) | (1<<WGM52);          //8 prescaler -> 0.5us cycles, activate CTC
3
TIMSK5 = (1<<OCIE5A);                             //Interupt enable and compare A enable

Das bitte einmal ausprobieren. Dieses Verodern bei Arduino war in einem 
anderen Beitrag schonmal der Fehler.

von Gary (Gast)


Lesenswert?

S. Landolt schrieb:
> OCR5A= 0x1234;
> itoa(OCR5AL,buff,10);
> Serial.println(buff);
> itoa(OCR5AH,buff,10);
> Serial.println(buff);

Das Liefert:
52
0

Felix Adam schrieb:
> TCCR5A = 0;

Das gibt es doch nicht! Das war tatsächlich der Fehler der OCR5AH immer 
0 sein lies.

von Felix Adam (Gast)


Lesenswert?

Arduino belegt den Inhalt wohl als Vorbereitung für irgendwas vor. Daher 
beim ersten schreibenden Zugriff auf Register besser nur ein "=" statt 
"|=" benutzen und besser alle Register initialisieren.

von Karl M. (Gast)


Lesenswert?

Hallo,

nicht dass jemand noch schreib, dass das nicht genannt wurde:

Karl M. schrieb:
> Dazu muss man die richtigen Bits in den Registern TCCR5A und TCCR5B
> setzen.
> Mode 4: CTC WGM5[3:0] = 0100

Karl M. schrieb:
> Noch eine Anmerkung,
>
> guter Stil ist es alle relevanten Register von Timer5 zu initialisieren.
>
> TCCR5A = ...
> dort finden wir die Bits WGM51 WGM50.


Es kommt leider nur bei Gary mit der Holzhammer Methode an.

von S. Landolt (Gast)


Lesenswert?

Trotzdem verstehe ich nicht, weshalb in dem Beispiel OCR5AH auf 0 
bleibt. Man helfe mir aufs Pferd.

von Karl M. (Gast)


Lesenswert?

Hallo,

vielleicht stand da vorher einer dieser Mode drin:

Timer 5
17.9 Modes of Operation

1: PWM, Phase Correct, 8-bit
5: Fast PWM, 8-bit

oder eine Mode mit TOP: ICR5
8 : PWM, Phase and Frequency Correct
10: PWM, Phase Correct
12: CTC Mode

von S. Landolt (Gast)


Lesenswert?

Danke, Karl M.

Und, Jörg Wunsch, ich komme zwar nie auf die Idee, ein und dasselbe Bit 
zweimal zu setzen, aber ich gebe Ihnen unumwunden zu, Ihr letztes 
Argument war sehr gut.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gary schrieb:
> Karl M. schrieb:
>> schreibe doch bitte die Timer 5 OCR5A Init genau so und berichte bitte:
>
> Habe das nun so gemacht und hier dazu noch das .ELF
>
> OCR5AH bleibt immer noch 0.

Hier das entsprechende Stück aus dem Disassembler:
1
00000144 <setup>:
2
 144:   26 e0           ldi     r18, 0x06       ; 6
3
 146:   40 e8           ldi     r20, 0x80       ; 128 ; 0x2580 => 9600
4
 148:   55 e2           ldi     r21, 0x25       ; 37
5
 14a:   60 e0           ldi     r22, 0x00       ; 0  ; 0x22D => Adresse von Serial (Objekt, this-Pointer)
6
 14c:   70 e0           ldi     r23, 0x00       ; 0
7
 14e:   8d e2           ldi     r24, 0x2D       ; 45
8
 150:   92 e0           ldi     r25, 0x02       ; 2
9
 152:   60 d1           rcall   .+704           ; 0x414 <HardwareSerial::begin(unsigned long, unsigned char)>
10
 154:   88 e0           ldi     r24, 0x08       ; 8  ; 0x3D08 => 15624
11
 156:   9d e3           ldi     r25, 0x3D       ; 61
12
 158:   90 93 2b 02     sts     0x022B, r25          ; 22A => Variable "val" (warum wird die nicht wegoptimiert?)
13
 15c:   80 93 2a 02     sts     0x022A, r24
14
 160:   e1 e2           ldi     r30, 0x21       ; 33 ; 0x121 => TCCR5B
15
 162:   f1 e0           ldi     r31, 0x01       ; 1
16
 164:   80 81           ld      r24, Z               ; nach R24 laden
17
 166:   8d 60           ori     r24, 0x0D       ; 13 ; WGM52, CS51 und CS50 setzen
18
 168:   80 83           st      Z, r24               ; nach TCCR5B zurückschreiben
19
 16a:   e3 e7           ldi     r30, 0x73       ; 115 ; 0x73 => TIMSK5
20
 16c:   f0 e0           ldi     r31, 0x00       ; 0
21
 16e:   80 81           ld      r24, Z
22
 170:   82 60           ori     r24, 0x02       ; 2   ; OCIE5A setzen
23
 172:   80 83           st      Z, r24                ; nach TCCR5B zurückschreiben
24
 174:   8f ef           ldi     r24, 0xFF       ; 255 ; 65536 laden
25
 176:   9f ef           ldi     r25, 0xFF       ; 255
26
 178:   90 93 29 01     sts     0x0129, r25           ; nach OCR5A schreiben
27
 17c:   80 93 28 01     sts     0x0128, r24
28

Danach folgt noch die Ausgabe von val und OCR5AH.

Da wird OCR5A auf 0xFFFF (oder 65535) gesetzt, und nicht auf den
Wert von val!

Irgendwie passt das Compilat nicht zum Sourcecode.

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.