Verständnisfrage zum Timerregister tx

Postby mr. teflon » Thu Feb 10, 2011 12:00 am

Hallo,

ich beschäftige mich gerade mit dem Timer X, Seite 67 im Buch "Basiskurs R8C/13".
Bei dem Bsp. wird der gesamte Inhalt an P1 kopiert. Ich messe auch an P1.0 1562,5Hz und an P1.7 12,7Hz.

Meine Frage ist, wenn ich nur ein bestimmtes Bit vom tx Register herausfischen möchte, muß ich dann einen konkreten Bitvergleich machen oder muß man immer den Inhalt von tx vorher verschieben?

Ich möchte zum Bsp. das vorletzte Bit von tx als Takt (wäre Bit 6) an einen bestimmten Port 1.7 haben. Kann ich dann einfach schreiben
p1_7 = tx >> 6;
Was passiert mit Bit 7 von tx? Wäre nach der Verschiebung das zweit niedrigste. Wohin wird das ausgegeben?
Nicht das es mir den P1 unkontrolliert mit Nullen "überschreibt"?

Bei
p1 = tx >> 6;
leuchtet mir das ein, dass der komplette Inhalt von tx an P1 ausgegeben wird und damit auch alle aufgefüllten Nullen an den höherwertigen Bits von P1 erscheinen und überschrieben werden. Nur sonst weis ich nicht wie der R8C13 arbeitet.

Könnte das bitte jemand erklären?
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm

Postby herch » Fri Feb 11, 2011 12:00 am

Hallo Mr. Teflon,

es kommt bei der Port-Zuweisung immer auf das niederwertigste Bit an

Beispiel: // p1_7 ist danach:
p1_7 = 0b11000000; // low
p1_7 = 0b11000000 >> 6; // high
p1_7 = 0b01000000 >> 6; // high
p1_7 = 0b10000000 >> 6; // low
p1_7 = (0b11000000 & 0b01000000) >> 6; // high


So etwas kann man mit dem Debugger herausfinden:
http://www.elektor.de/projekte/r8c-die-elektor-r8c-mikrocontroller-startseite.83229.lynkx


Du kannst allerdings auch
if ((tx % 4711) == 0)
pd1_7 ^= 1; // XOR
damit würde der Port p1_7 seinen Zustand ändern, wenn der Wert von tx geteilt durch 4711 den Rest "0" ergibt.


tx >> 6 // verschiebt den Inhalt von tx um 6 Stellen nach rechts. Von Links kommen "0" nach. Was rechts "rausfällt" wird nirgendwo gespeichert. Übrig beiben die beiden höherwertigen Bits von tx.

p1_7 = tx >> 6 // siehe oben, und es wird das niederwertigste Bit an p1_7 zugewiesen


weitere gute Quellen zum Timer/Interrupt sind auf der Elektor CD
das Projekt "timer_interrupt"
Ordner: Application Notes R8C \ Timer (einige Beispiele zum Timer)
Hardware Manual - r8c13hm_rev110.pdf (Kapitel 10, 12)
herch
 
Posts: 52
Joined: Fri Jan 03, 2014 1:48 pm

Postby mr. teflon » Sun Feb 13, 2011 12:00 am

Hallo herch,

mit der kürzeren aber komplizierteren Schreibweise
if ((tx % 4711) == 0)
pd1_7 ^= 1; // XOR
komme ich noch nicht ganz mit. Meine Frage hast Du aber wunderbar beantwortet. Danke dafür.

Eine Frage noch zum verwendeten Takt der Timer.
Ich habe viel rumprobiert und komme zu dem Schluss, dass die Timer, habe mit Timer X gespielt, immer nur mit dem Haupttakt arbeiten den die CPU bekommt. Also nicht mit dem eigentlichen CPU Takt. Kann das sein?

Wenn ich den R8C13 mit dem 20MHz Quarz aber mit verschiedenen Frequenzen laufen lasse, ändert sich am Takt von P1 mit Timer X absolut nichts. Egal ob ich 5, 10 oder 20MHz verwende. Der Takt von P1 durch Timer X ändert sich erst, wenn ich den R8C13 mit seinen Standardtakt von 15,625kHz arbeiten lasse. Der Timer arbeitet dann anscheinend mit den anliegenden 125kHz vom Low-Speed Oszilator. Dann messe ich mit dem Oszi andere Frequenzen bzw. sehe es an den LEDs an P1.0 und P1.7

Programm siehe Anhang
Attachments
Timer-Spielereien.c
(6.15 KiB) Downloaded 33 times
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm

Postby herch » Mon Feb 14, 2011 12:00 am

Hallo Mr. Teflon,

CPU und Timer werden jeweils vom Haupttakt (20MHz) runtergeteilt (siehe Seite 30 des Hardware Manuals "Figure 6.1 Clock Generation Circuit").


Mit "f ((tx % 4711) == 0) pd1_7 ^= 1; // XOR " dachte ich, Du wolltest eine LED regelmäßig blinken lassen (siehe Forumsbeitrag "Tipps für optimale Programmierung") und habe das falsche Register erwischt.
Eine Möglichkeit wäre, eine timer-Interrupt-Prozedur zum Auslösen der Messungen zu nehmen und diese auch für die blinkende LED zu nehmen.
z.B. Wird nachfolgende Interrupt-Prozedur alle 5ms aufgerufen, dann blinkt bei Alarm die LED an p1_7 mit 2 Hz.



unsigned char zaehler = 0;unsigned char alarm = 0;#pragma interrupt timer_xvoid timer_x(void){  ...  // hier die Temperaturmessung, dann ...     if (alarm == 1) {    zaehler++;    if ((zaehler % 52) == 0)     // zaehler modulo 52 ist 0 bei:     // 0, 52, 104, 156, 208      p1_7 ^= 1;                    // XOR   }  ...}
herch
 
Posts: 52
Joined: Fri Jan 03, 2014 1:48 pm

Postby mr. teflon » Mon Feb 14, 2011 12:00 am

Hallo,

erstmal Danke für die wirklich hilfreiche Unterstützung.

Du hast mein Hauptziel schon richtig verstanden. Ich sehe da keinen Fehler Deinerseits. Ganz am Ende soll noch das DCF77 Programm eingebunden und die Messwerte auf eine SD-Karte geschrieben werden. Das ist aber noch Zukunftmusik. Ich muß erstmal mit dem Timer und Interrupt richtig warm werden. Denn in das DCF77 Programm mein Programm wild reinzukopieren funktioniert nicht. Dann kommt die Bit Berechnung vom DCF77 außer Tritt. Leuchtet mir ja auch ein, weil das äußerst Zeit kritisch ist.

Ich wäre nie aus dem Manual schlau gewurden womit die Timer getaktet werden. Jetzt sehe ich erst das quasi die Seite 71 mit ihrem Eingängen f2, f2, f8, f32 an die Seite 30 rechts "andockt". Damit kann der Timer wirklich nur entweder vom Quarz oder vom Low-Speed Oszilator getaktet werden. Also nur richtig schnell oder richtig langsam. Okay soweit.

Was Modulo wirklich bedeutet mußte ich erstmal nachlesen.
Division mit Rest.
Du prüfst also ob der Rest der Division gleich 0 ist, was aller 52 Durchläufe der Fall ist und schaltest dann immer den P1.7 jeweils um. Wirklich clever. Damit erspart man sich eine Verzögerungsschleife die das restliche Programm warten lässt, wenn ich das richtig verstehe. Das wäre ja richtig SPS Profi mäßig.
Muß der "zähler" nicht irgendwann mal genullt werden oder ist es ausreichend wenn er sich durch einen Überlauf selbst nullt? Dann müßte es ausreichend sein die Zählervariable mit unsigned char oder unsigned int zu deklarieren.

Mit Interrupts habe ich mich noch nicht beschäftigt. Das halte ich noch für zu kompliziert. Zudem ich hier im Forum lesen mußte das man eine Datei von seinem "Projekt" modifizieren muß das der Timer Interrupt auch wirklich funktioniert. Ich verstehe das jedenfalls so, dass Renesas da einen kleinen Bug drin hat.

Tschau
Mr. Teflon
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm


Return to Das R8C-Projekt

Who is online

Users browsing this forum: No registered users and 1 guest

cron