mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Uhr mit PIC18


Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo wollte Fragen was mein Fehler ist, da meine "Uhr" etwas zu langsam 
zählt und ich einfach nicht darauf komme.

Das Projekt soll eine Uhr sein welche auf einem Display ausgegeben wird. 
Es muss mit dem PIC18F25K22 programmiert werden und ich benötige dies 
für eine Arbeit in der Schule.

Danke schon im Vorhinein für eure Vorschläge und Anregungen

MFG

PROGRAMMCODE:
#include "main.h"
#include "lcd.h"

int sec1, sec2, min1, min2, hour1, hour2;


void main(void)
{  
  //Initialisierungen
  ANSELA = 0;
  ANSELC = 0;
  TRISA = 0;
  TRISC = 0;        
  
//Startwert bestimmen
  sec1 = 0;
  sec2 = 0;
  min1 = 0;
  min2 = 0;
   hour1 = 0;
  hour2 = 0;

  LCD_init();

  //Timer initialisieren für das Zählen von 1 sekunde
  TMR0H = 00001011;
  TMR0L = 11011100;


  //Interrupt für Timer0  
  RCONbits.IPEN =0;

  INTCONbits.GIE = 1;
  INTCONbits.TMR0IE = 1;
  
  //Timer starten
  T0CON = 10000001;

  while(1){
    LCD_WC(3);
    LCD_WD(hour1 + '0');
    LCD_WD(hour2 + '0');
    LCD_WD(':');
    LCD_WD(min1 + '0');
    LCD_WD(min2 + '0');
    LCD_WD(':');    
    LCD_WD(sec1+ '0');
    LCD_WD(sec2+ '0');
      
  }    
}
//INterrupt
#pragma code isr=0x08
#pragma interrupt isr

 void isr()
  {
    if(INTCONbits.TMR0IF){


      sec2++;

    if (sec2==10){
      sec1++;
      sec2=0;
    }
    if(sec1 == 6){
      min2++;
      sec1 =0;
    }

    if(min2 ==10){
      min1++;
      min2 = 0;
    }

    if (min1 == 6){
      hour2++;
      min1 = 0;
    }

    if(hour2 == 10){
      hour1++;
      hour2 =0;
    }

    if (hour1==2 && hour2==4){
      hour1=0;
      hour2=0;
    }

  
    
    }
      TMR0H = 00001011;
      TMR0L = 11011100;

      
      INTCONbits.T0IF =0;
  }
#pragma code
      

Autor: Löser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist "etwas" und woher kommt der Takt für den Pic?

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Für genaue Zeiten haben die Timer Betriebsarten, die unabhängig von 
Programmlaufzeiten sind, wie auto-reload oder clear-on-compare.

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interne Clock wird verwendet.
es sind ca 250 ms welcher er zu langsam zählt,weiß nicht ob Fehler im 
Programm liegt, oder ob es rein die "Verarbeitungszeiten" sind.
MFG

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> Hallo wollte Fragen was mein Fehler ist, da meine "Uhr" etwas zu langsam
> zählt und ich einfach nicht darauf komme.

Du solltest einen anderen Timer (1/3/5) mit einem dem CCP- Modul 
verwenden.
Dann hast du die von Peter angesprochene Möglichkeit.

Wenn es eine Bedingungen der Aufgabe ist, den Timer0 zu verwenden, dann 
musst du den Timer vorstellen, indem du was zum aktuellen Timerwert dazu 
addierst und nicht den Timer neu lädst.

Schau mal da: 
http://www.hs-ulm.de/nocache/wir/Personal/PersonalSaSchr/vschilli/Mikrocontroller/uCQ/
Der oberste Download auf der rechten Seite.
5.1 Timer_0 Interrupt
5.2 Interrupt mit Special-Event-Trigger (CCP + Timer)
Uhr gibt es auch...

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort, ich werde mich gleich versuschen sie umzusetzen 
und melde mich dann

MFG

Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> es sind ca 250 ms

Pro Sekunde? Pro Tag?

Häufigste Fehler:

A: interne clock hat Abweichungen: kalibrieren oder Quarz verwenden.

Timer-Teiler zu ungenau: entsprechende Schalttakte einfügen.

Off by one Fehler beim Teiler: nachrechnen, Beispiele verstehen, Pin 
togglen lassen und messen, mit Oszi oder Frequenzzähler

Interrupt verschluckt:
Interrupts nicht sperren, Zählerstand am Anfang und Ende auf 
Plausibilität prüfen, Fehlerzähler einbauen und auch anzeigen

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> 5.1 Timer_0 Interrupt

Siehe auch:
4.4.2 Die exakte Methode (nur für Freaks)

Beitrag #5259951 wurde vom Autor gelöscht.
Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> Pro Sekunde? Pro Tag?

Pro sekunde

Autor: Volker S. (vloki)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
D. R. schrieb:
> TMR0H = 00001011;

Ist das dein originaler Code?
Dann hast du vielleicht auch noch ein ganz anderes Problem.

1011 != 0b1011

<EDIT>
1011 = 0b100_00000011

<edit2>
D. R. schrieb:
> //Timer starten
>   T0CON = 10000001;
Hier kommt zufällig das gewollte raus ;-)
(0b1001100010010110_10000001)

: Bearbeitet durch User
Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry verstehe jetzt nicht was du damit meinst :( ^^

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zumindest macht es keinen unterschied ob ich es jetzt so schreibe

  LCD_init();

  //Timer initialisieren für das Zählen von 1 sekunde
  TMR0H = 0b00001011;
  TMR0L = 0b11011100;


  //Interrupt für Timer0  
  RCONbits.IPEN =0;

  INTCONbits.GIE = 1;
  INTCONbits.TMR0IE = 1;
  
  //Timer starten
  T0CON = 0b10000001;

  while(1){


Autor: A. S. (achs)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
0b010 ist zwei und eine Erweiterung um binäre zahlen

10 ist zehn

010 ist acht. Zumindest in C, da oktal

Es wäre aber möglich, dass dein Compiler jede separate Folge von 8 
Nullen und Einsen als binär nimmt

: Bearbeitet durch User
Autor: Toxic (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> Es muss mit dem PIC18F25K22 programmiert werden

Dein PIC hat einen "Dedicated Secondary 32 kHz oscillator circuit"

Warum nicht einen Uhrenquarz verwenden?

Anbei eine pdf-Zusammenstellung wie man eine Real Time Clock 
programmiert und was zu beachten ist,wenn man Timer1 updated.

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> Es wäre aber möglich, dass dein Compiler jede separate Folge von 8
> Nullen und Einsen als binär nimmt

ich glaube so ist es ja ^^


dankeschön Leute ich hab heute keine Zeit mehr ich schau morgen weiter 
und berichte von meinen "Ergebnisen" (falls euch interessiert) xD

MFG

Autor: Volker S. (vloki)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> 010 ist acht. Zumindest in C, da oktal

Ja richtig, hatte oktal ganz vergessen...
(also ist das einer meiner Beispiele oben eigentlich falsch)
01011 -> 0b 001 000 001 001

D. R. schrieb:
> Zumindest macht es keinen unterschied ob ich es jetzt so schreibe...

Schau dir doch mal im Debugger/Simulator an, was da wirklich in den 
Registern steht.


Ich nehme an, du verwendest den C18 Compiler
User Guide ->
------------------------------------------------------------------------
2.7.2    Numeric Constants
MPLAB C18 supports the standard prefixes for specifying hexadecimal (0x) 
and octal (0) values and adds support for specifying binary values using 
the 0b prefix. For example, the value two hundred thirty seven may be 
denoted as the binary constant 0b11101101
------------------------------------------------------------------------

: Bearbeitet durch User
Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> Achim S. schrieb:
>> Es wäre aber möglich, dass dein Compiler jede separate Folge von 8
>> Nullen und Einsen als binär nimmt
>
> ich glaube so ist es ja ^^

Ich bin mir sehr sicher, dass dem nicht so ist ;-)
Trotzdem sollte der Fehler weit geringer als deine 250ms sein.
Wie hast du den ermittelt? Waren es vielleicht 250us?

Vermutlich gibt es mehrere Baustellen ;-)

Lösungsvorschläge:
1. Mach dir den Unterschied zwischen binär, oktal, hexadezimal und 
dezimal klar.
2. Poste doch mal die Aufgabenstellung, damit wir keine dazu unpassenden 
Ratschläge geben.
3. Sag doch bitte mal welche IDE und Compiler du verwendest
4. Falls MPLABX, dann Poste doch einfach das gepackte Projekt 
(http://microchipdeveloper.com/mplabx:projects-package)

: Bearbeitet durch User
Autor: Michael B. (laberkopp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> //Timer initialisieren für das Zählen von 1 sekunde
>   TMR0H = 00001011;
>   TMR0L = 11011100;

Irgendwoherkopiert oder für deinen uC richtig berechnet, das sind keine 
binären Zahlen.

  while(1){
    LCD_WC(3);

besser

  while(1)
  {
    int sec=sec1;
    while(sec==sec1) ; // sec1 sollte volatile sein
    LCD(WC(3);

damit nicht ständig das LCD geupdated wird, flimmert meist.

Eigentlich sollten die Doppelpunkte aber blinken, damit man sieht, daß 
die Uhr noch läuft.

Autor: D. R. (reisii)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Michael B. schrieb:
> Irgendwoherkopiert oder für deinen uC richtig berechnet, das sind keine
> binären Zahlen.

Berechnet:
fosc = 1 MHz
fosc/4 = 250 000 Hz
1s...250 000

Presacler benötigt:
250000/4 = 62500

Startwert= 65 536 - 62 500 = 3036

  H      L
0 0 0 0 1 0 1 1      1 1 0 1 1 1 0 0

Michael B. schrieb:
> damit nicht ständig das LCD geupdated wird, flimmert meist.

Flimmert nicht habs schon aufgebaut.


IM anhang jetzt die ZIP-File
(Timer ist jetzt für 0,79 berechnet da die Abweichung so geringer ist)

Autor: A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur eine Idee:

Ich bin früher immer drauf reingefallen, dass ich immer "-1" rechnen 
muss, um den genauen Zählerwert eines Timers zu bekommen.

Als Beispiel: Ich habe 4Mhz Timer-Takt und möchte, dass dieser jede 
Millisekunde einen Überlauf macht. Dann ist die Formel:

iZ = 4.000.000 / 1000 - 1;

Warum die -1? Weil die 0 nach einem Überlauf mitzählt. Es soll von 0 bis 
3999 gezählt werden und nicht von 0 bis 4000, das wären 4001 Schritte.

Das hat mir damals eine genaue Frequenzausgabe einer DDS total merklich 
zerstört.

Autor: A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also in deinem Fall wohl:

fosc = 1 MHz
fosc/4 = 250 000 Hz

Presacler benötigt:
250000/4 = 62500

Startwert= 65 536 - 62 500 = 3036
FALSCH!

Richtig:
0xffff - 62500 + 1

Autor: A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bzw. sehe grade, du hast mit 0x1000 gerechnet, also stimmts ;).
Vergiss, was ich sagte.

Autor: Volker S. (vloki)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
D. R. schrieb:
> IM anhang jetzt die ZIP-File

OK, dann verwendest du also noch die "alte" IDE.

Keine Ahnung, warum deine Abweichung so groß ist. Der interne Oszillator 
muss sehr ungenau sein. Das habe ich so noch nie gesehen.

Hier noch einige Tips zu deinem Code:

Von der Berechnung des Startwertes mal abgesehen, sind die Sekunden 
unterschiedlich lang, wenn mehr oder weniger der IFs abgearbeitet 
werden, weil der Reload erst danach erfolgt.
-> Das muss als aller erstes passieren, oder eben nicht nachgeladen, 
sondern aufaddiert werden. (Das Addieren ist in aber diesem Fall 
komplizierter als man auf den ersten Blick annehmen würde ;-)

Die LCD Funktionen sollten zum Schreiben LAT Register verwenden und 
nicht PORT. (RMW Effekt)

Der Datentyp int ist zum Speichern einer Variable von 0..9 ganz schön 
übertrieben. Da würde man vier davon rein bekommen. -> unsigned char.

Eigentlich könntest du gleich überall mit Ziffern rechnen und dir das 
Aufaddieren der '0' bei der Ausgabe sparen.
        if (sec2 > '9') {
            sec1++;
            sec2 = '0';
        }

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Tipps ich schau mal was sich für mich alles umsetzten 
lässt

Volker S. schrieb:
> Eigentlich könntest du gleich überall mit Ziffern rechnen und dir das
> Aufaddieren der '0' bei der Ausgabe sparen.        if (sec2 > '9') {
>             sec1++;
>             sec2 = '0';
>         }

Wenn ich so schreibe, werden dann Buchstaben etc. ausgegeben

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Punkt eins, das OSCAL wird nicht initialisiert. Damit ist warscheinlich 
der
Takt falsch.
Punkt zwei, Timer hat einen 2clk hw sync, deshalb muss man 2 cpu cyclen
abziehen.
Punkt drei, wieso .... wird hier eine Binärzahl verwendet und wieso kein
16bit Adresse ????
Punkt vier, der Interrupt ist falsch, da wird Zeit verbraucht , und dann
wird der Timer auf den Wert gesetzt. Diese Interruptzeit muss abgezählt 
werden.
Am einfachsten geht es so:
tmr1 -= 62500 ; // oder der Wert den du errechnet hast, inclk den 2 sync 
cyclen.
Damit braucht man dann keine Asm cyclen Zählen, bzw im Simulator diese
raussuchen.

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> ich benötige dies
> für eine Arbeit in der Schule.

Was für eine Schule ist das eigentlich?




D. R. schrieb:
> Wenn ich so schreibe, werden dann Buchstaben etc. ausgegeben

Dir scheinen da einige Grundlagen zu fehlen. Die kann man vermutlich 
nicht an jeder / keiner Schule vermitteln, ohne dass alle Schüler das 
Interesse schon verloren haben, bevor es an's Programmieren geht ;-)

Es werden immer Zeichen ausgegeben. In den Registern für die Variablen 
stehen aber nur Bitmuster (keine Zahlen). Stehen in den Variablen schon 
die Bitmuster, welche den gewünschten Zeichen entsprechn, dann muss man 
diese nicht mehr durch addieren der Bitmuster für '0' umwandeln...

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> Was für eine Schule ist das eigentlich?

HTL

Volker S. schrieb:
> Dir scheinen da einige Grundlagen zu fehlen

Stimmt xD

chris schrieb:
> Punkt eins, das OSCAL wird nicht initialisiert. Damit ist warscheinlich
> der
> Takt falsch.

Takt sollte passen (normal 1 MHz), habs jetzt nochmal extra deklariert 
und es bleibt alles beim alten..

chris schrieb:
> Punkt zwei, Timer hat einen 2clk hw sync, deshalb muss man 2 cpu cyclen
> abziehen.
> Punkt drei, wieso .... wird hier eine Binärzahl verwendet und wieso kein
> 16bit Adresse ????

Punkt 2: ???????

Punkt 3: wo meinst du ?

chris schrieb:
> Punkt vier, der Interrupt ist falsch, da wird Zeit verbraucht , und dann
> wird der Timer auf den Wert gesetzt. Diese Interruptzeit muss abgezählt
> werden.
> Am einfachsten geht es so:
> tmr1 -= 62500 ; // oder der Wert den du errechnet hast, inclk den 2 sync
> cyclen.
> Damit braucht man dann keine Asm cyclen Zählen, bzw im Simulator diese
> raussuchen.

Kann dir leider dort auch nicht folgen :O

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> chris schrieb:
>> Punkt eins, das OSCAL wird nicht initialisiert. Damit ist warscheinlich
>> der
>> Takt falsch.
>
> Takt sollte passen (normal 1 MHz), habs jetzt nochmal extra deklariert
> und es bleibt alles beim alten..
>
Dieser interne RingOscillator muss calibriert werden, dies wird er ab 
Werk
grob sowie Fein und als Osccal Value im Flash 2-3 mal abgelegt.
Den kann man auch selbst kalibrieren, aber man muss den Wert dann ins
osccal Register schreiben, damit die 1Mhz oder was es auch ist stimmen.
Das Datenblatt gibt weitere Auskünfte.

> chris schrieb:
>> Punkt zwei, Timer hat einen 2clk hw sync, deshalb muss man 2 cpu cyclen
>> abziehen.
Siehe Datenblatt, beim Schreiben wird der Timer für 2 cpu clk 
angehalten.

>> Punkt drei, wieso .... wird hier eine Binärzahl verwendet und wieso kein
>> 16bit Adresse ????
TMR1 = -62500 ; // startwert

Dies ist viel leserlicher, und erleichter das abziehen des Wertes im 
ISR.
>
> Punkt 2: ???????
>
> Punkt 3: wo meinst du ?
>
> chris schrieb:
>> Punkt vier, der Interrupt ist falsch, da wird Zeit verbraucht , und dann
>> wird der Timer auf den Wert gesetzt. Diese Interruptzeit muss abgezählt
>> werden.
>> Am einfachsten geht es so:
Wie geschrieben,
>> tmr1 -= 62500 ;
anstelle von
TMR1L = 0b10011;
TMR1H = 0b10011;
denn dann muss man die Zeit vom Interrupt sowie den Clockzycle jitter
compensieren, dies wird eine ASM zählerei und einen free running timer,
wenn es auf synchronen clock ankommt, wenn es wie hier nicht so genau 
ist
genügt die Zählerei, aber mit der Subtraction braucht man dies nicht.

Autor: Volker S. (vloki)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
chris schrieb:
> Punkt eins, das OSCAL wird nicht initialisiert.
Es gibt nur ein OSCTUNE


chris schrieb:
> Punkt zwei, Timer hat einen 2clk hw sync, deshalb muss man 2 cpu cyclen
> abziehen.
Bin mir jetz nicht hunder Prozent sicher, aber warum sollte der interne 
Clock mit dem internen Clock synchronisiert werden müssen?
Müsste man dann nicht zwei nicht gezählte dazu addieren?


chris schrieb:
> Punkt drei, wieso .... wird hier eine Binärzahl verwendet und wieso kein
> 16bit Adresse ????
Was für eine Adresse?


chris schrieb:
> Am einfachsten geht es so:
> tmr1 -= 62500 ;
Ich fürchte der verwendete Compiler wird TMR0 (oder irgend ein anderen 
Namen für beide Register eines Timers) nicht akzeptieren.


chris schrieb:
> Punkt vier, der Interrupt ist falsch, da wird Zeit verbraucht , und dann
> wird der Timer auf den Wert gesetzt.
Was ganz neues ;-)

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Volker S. schrieb:
@Ein Mitschüler,
> chris schrieb:
>> Punkt zwei, Timer hat einen 2clk hw sync, deshalb muss man 2 cpu cyclen
>> abziehen.
> Bin mir jetz nicht hunder Prozent sicher, aber warum sollte der interne
> Clock mit dem internen Clock synchronisiert werden müssen?
Man kann ihn auch als Asyncron configurieren, aber diesen Unterschied 
ist minimal

> Müsste man dann nicht zwei nicht gezählte dazu addieren?
je nach Logic wie man dies macht, wenn man 100 Zählereinheiten 
configurieren will schriebe ich
TMR1 = -100; // in diesem Falle muss ich es wegzählen.
wenn man aber folgendes Verwendet
TMR1 = 65436; // muss man es dazuzählen.
>
> chris schrieb:
>> Punkt drei, wieso .... wird hier eine Binärzahl verwendet und wieso kein
>> 16bit Adresse ????
> Was für eine Adresse?
Normalerweise TMR1 , bei C18 ist dies aber nicht.
verwende die Include timers.h
und benutze
WriteTimer1(ReadTimer1()-6200); // 6200 ist hier eine Hausnummer der 
Sekunde.

> Was ganz neues ;-)

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
chris schrieb:
>> chris schrieb:
>>> Punkt drei, wieso .... wird hier eine Binärzahl verwendet und wieso kein
>>> 16bit Adresse ????
>> Was für eine Adresse?
> Normalerweise TMR1 , bei C18 ist dies aber nicht.
> verwende die Include timers.h
> und benutze
> WriteTimer1(ReadTimer1()-6200); // 6200 ist hier eine Hausnummer der
> Sekunde.

Ach so meinst du das mit der Adresse. Würde mich wundern, wenn das 
irgendein Compiler in diesem speziellen Fall einfach so könnte.
Mit Gewalt, *(unsigned short *)(&TMR0L) = ... , geht's ja auch nicht, 
weil dann die Reihenfolge falsch ist.

Auf die Idee mit dem Abziehen bin ich noch gar nicht gekommen. Denke 
wohl immer vorstellen -> dazu zählen. Muss ich mir mal anschauen, was da 
für ein Maschinencode bei raus kommt.

<edit>
Vergiss es, ich würde überhaupt nie den Timer manuell umstellen,
sondern das CCP verwenden.

@reisii
Lass dich nicht verwirren und ignoriere bitte meine Fachsimpeleien...

: Bearbeitet durch User
Autor: time.h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal ganz was anderes:
Für PICs bietet microchip die C Standardlibrary an. Statt also das ganze 
Konstrukt selber zu pflegen, und die Zeit hochzuziehen, kann man das 
auch so lösen:
#include <time.h>

time_t Zeit;

//jede Sekunde einmal aufrufen
Zeit++;


//und so liest man die Zeit aus:
struct tm *Time = gmtime(&Zeit);

in tm findest du dan all die Sekunden, Wochentage und Jahre, aufgelistet 
in einer Struktur.

Großer Vorteil der Sache: Da es eine C Standardlibrary ist, ist es 
portabel.

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> Lass dich nicht verwirren und ignoriere bitte meine Fachsimpeleien

Werde mich bemühen ^^
Naja ich bin noch immer nicht wirklich weiter gekommen :(

Volker S. schrieb:
> Punkt vier, der Interrupt ist falsch, da wird Zeit verbraucht , und
> dann
>> wird der Timer auf den Wert gesetzt.
> Was ganz neues ;-)

Ist mein Interrupt jetzt falsch ? :O

time.h schrieb:
> Für PICs bietet microchip die C Standardlibrary an. Statt also das ganze

hört sich interessant an, werde ich mich erkundigen danke

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vergiss time.h. Das gibt es bei deinem Compiler nicht.
(und geht vermutlich an deiner AUFGABENSTELLUNG weit vorbei)

Dein Interrupt ist insofern falsch, dass du wie schon mehrmals gesagt, 
erst Code von nicht immer gleicher Länge ausführst und dann trotzdem 
immer den gleichen Wert in die Timer Register lädst. So bekommst du 
(leicht) unterschiedliche Laufzeiten für die Sekunde.

Was heißt, du bist noch nicht weiter gekommen?
Was ist den dein Ziel? (Aufgabenstellung)

: Bearbeitet durch User
Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
time.h schrieb:
> Für PICs bietet microchip die C Standardlibrary an.

Finde keine passende information oder download für die Library

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> Dein Interrupt ist insofern falsch,

hab jetzt eifnach das Timerstellen davor geschrieben ^^

Ja gut ich schätze mal es ist einfach bei Timer0 mit solchen 
Verzögerungen zu rechnen ? :/

Autor: time.h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> time.h schrieb:
>> Für PICs bietet microchip die C Standardlibrary an.
>
> Finde keine passende information oder download für die Library

Die Information steht in der Hilfe zum Compiler, also in MPLABX. Die 
C-Standardlib ist beim XC8-Compiler schon mit dabei, behauptete 
zumindest die Hilfe.

Theoretisch sollte ein #include <time.h> ausreichen.

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
time.h schrieb:
> Theoretisch sollte ein #include <time.h> ausreichen.

funktioniert nicht, glaube
> Volker SK hat recht

Autor: time.h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> time.h schrieb:
>> Theoretisch sollte ein #include <time.h> ausreichen.
>
> funktioniert nicht, glaube
>> Volker SK hat recht

Sicher?
time.h ist Bestandteil der Sprache C.
ich hab jetzt keinen XC8 installiert, aber beim XC16 und XC32 - Compiler 
ist time.h mit dabei.

Die Hilfe erwähnt für time.h und beteiligte Funktionen ist in der Hilfe 
von MPLABX in der Sektion für den XC8 enthalten.

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
time.h schrieb:
> Sicher?

Ja! Kein MPLABX kein XC Compiler...

Jetzt komm bloß nicht damit, dass man das ja installieren könnte.
Könnte man, aber die Aufgabe soll vermutlich mit den vorhandenen Mitteln 
gelöst werden. Es geht (bei der Übungsaufgabe?) vermutlich auch gar 
nicht darum, eine möglichst perfekte Uhr mit den tollsten 
Bibliotheksfunktionen zu programmieren, sondern um das Verständnis, wie 
so ein Timer funktioniert.

Die Uhr ist wahrscheinlich nur ein Beispiel, damit sich die Schüler 
leichter etwas darunter vorstellen können. Wer eine vernünftige Uhr 
haben möchte, der geht am besten in den nächsten Laden und kauft sich 
eine.

In der nächsten Übung wird dann vielleicht ein anderer Timer mit einem 
CCP Modul als Trigger für den AD-Wandler verwendet...

@reisii
vermutlich, wahrscheinlich, vielleicht... ?
Volker S. schrieb:
> 2. Poste doch mal die Aufgabenstellung, damit wir keine dazu unpassenden
> Ratschläge geben.

: Bearbeitet durch User
Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
>> 2. Poste doch mal die Aufgabenstellung, damit wir keine dazu unpassenden
>> Ratschläge geben

Ich soll eine Übung selbst entwickeln um das das Verständniss mit dem 
Timer und Interrupt zu erarbeiten, von dem her passt das einfache mit 
TMR0 eigentlich.

Die Genauigkeit war/ist nur so ein persönliches Ding für mich.

Vermutlich wird das mit Timer0 und CCP etc. noch dazukommen irgendwann.

Autor: Dietrich L. (dietrichl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> Ich soll eine Übung selbst entwickeln um das das Verständniss mit dem
> Timer und Interrupt zu erarbeiten, von dem her passt das einfache mit
> TMR0 eigentlich.
>
> Die Genauigkeit war/ist nur so ein persönliches Ding für mich.
>
> Vermutlich wird das mit Timer0 und CCP etc. noch dazukommen irgendwann.

Ich würde als Ausgangspunkt (d.h. nicht irgendwann) dann eher einen 
Timer-Modus nehmen, wo der Timer selbständig einen regelmäßigen, durch 
die Hardware bestimmten Interrupt auslöst. D.h. in der ISR wird 
nicht an den Timer-Registern "rumgemacht", dort steht quasi nur das 
"Anwenderprogramm", das den Zeittakt verwendet.

Das wäre eine Basis, mit der man einen stabilen, vom Programm 
(weitgehend) unabhängigen Zeittakt hat, den man eigentlich immer 
braucht. Und das Programm ist sogar noch einfacher und übersichtlicher.
Also warum nicht gleich die "genaue" Version, wenn die "ungenaue" weder 
bei der Programmierung noch bei der Anwendung Vorteile hat...

Autor: georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dietrich L. schrieb:
> Ich würde als Ausgangspunkt (d.h. nicht irgendwann) dann eher einen
> Timer-Modus nehmen, wo der Timer selbständig einen regelmäßigen, durch
> die Hardware bestimmten Interrupt auslöst.

Das ist die einzige Möglichkeit, eine stabile Frequenz zu erhalten, zur 
Einstellung die Zyklenzahl von Befehlen abzuziehen war, ist und wird 
immer Murks sein.

Georg

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> Ich soll eine Übung selbst entwickeln um das das Verständniss mit dem
> Timer und Interrupt zu erarbeiten, von dem her passt das einfache mit
> TMR0 eigentlich.

Dann solltest du das mit dem TimerO jetzt abhaken und wie von vielen 
hier vorgeschlagen, dazu über gehen einen Timer zu verwenden, bei dem 
das ganze Gefrickel gar nicht nötig ist.

Wie das funktioniert, solltest du aus dem ganz oben verlinkten Skript 
entnehmen können. Falls das dort nicht ausreichend gut beschrieben ist, 
wäre ich auch für Feedback dankbar ;-)

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> Ich soll eine Übung selbst entwickeln....

Sorry, muss noch mal nachfragen ;-)

Du bearbeitest also keine fertig gestellte Übungsaufgabe, sondern du 
sollst  selbst eine entwickeln, die dann von anderen bearbeitet werden 
wird?

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> Du bearbeitest also keine fertig gestellte Übungsaufgabe, sondern du
> sollst  selbst eine entwickeln, die dann von anderen bearbeitet werden
> wird?

also ich soll eine Aufgabe stellen, dazu theorie teil, dann durchführung 
etc beschreiben

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, dann passt schon mit Timer0.

Wenn Uhr, dann ist das Resultat der Übung eben,
dass dieser dafür nicht so gut geeignet ist.

Oder einfach 'ne LED blinken lassen...

Hast du eigentlich mal einen anderen 18F24K22 getestet,
ob da die Zeit auch so eklatant abweicht?

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> k, dann passt schon mit Timer0.

ich muss sowieso mehr Übungen "entwickeln"
ich glaube es folgt dann mit Timer1 und CCP eine erweiterung (aber bin 
gerade noch am tüfteln und kenn mich damit gar nicht aus)

Volker S. schrieb:
> Hast du eigentlich mal einen anderen 18F24K22 getestet,
> ob da die Zeit auch so eklatant abweicht?

Nein hab ich noch nicht

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> Wenn es eine Bedingungen der Aufgabe ist, den Timer0 zu verwenden, dann
> musst du den Timer vorstellen, indem du was zum aktuellen Timerwert dazu
> addierst und nicht den Timer neu lädst.

also nicht TMR0H = 0bXXXXXXXX sondern TMR0H = TMR0H + 0bXXXXXXXX ??

Inwiefern ändert das die Situation ? bzw erreiche ich so mehr fehler 
oder denke ich mal wieder falsch :(
MFG

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> Volker S. schrieb:
>> Hast du eigentlich mal einen anderen 18F24K22 getestet,
>> ob da die Zeit auch so eklatant abweicht?
>
> Nein hab ich noch nicht

Wir verwenden den ja auch meist mit internem Oszillator in den Laboren 
für unsere Studies. Bei den Bedingungen in den Laborräumen ( ~20°C ;-) 
sind da selbst bei serieller Datenübertragung via USART nie Probleme 
aufgetreten.
-> die internen Oszillatoren sind eigentlich relativ gut.

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> also nicht TMR0H = 0bXXXXXXXX sondern TMR0H = TMR0H + 0bXXXXXXXX ??
>
> Inwiefern ändert das die Situation ? bzw erreiche ich so mehr fehler
> oder denke ich mal wieder falsch :(

Wenn der Timer durch Addition/Subtraktion verändert wird, ist der 
Zeitpunkt, bzw. wie viele Zyklen inzwischen vergangen sind nicht so 
wichtig. (So lang keine Überlaufe durch die Addition entstehen)

Die Verarbeitung ist aber tricky-

TMR0H = TMR0H + T0H_KORREKTUR;
TMR0L = TMR0L + T0L_KORREKTUR;

scheitert z.B. daran, dass das neue TMR0H nicht übernommen wird, sondern 
durch das erneute Auslesen von TMR0L wieder mit dem internen Wert 
überschrieben wird. Der ist kurz nach dem Überlauf sehr wahrscheinlich 
Null - und das steht nach der Operation dann auch drin ;-)



D. R. schrieb:
> ich muss sowieso mehr Übungen "entwickeln"

Wenn das sozusagen eine größere Überarbeitung bedeutet, dann solltet ihr 
mal überlegen, ob in dem Zug nicht auch die veraltete IDE und Compiler 
gegen aktuelle Tools ausgetauscht werden sollten.

Beide werden seit Jahren nicht mehr gepflegt und sind für die Schüler 
auch nicht mehr ganz so einfach erhältlich.

Zudem besteht keine Einschränkung mehr in Bezug auf das OS.
Die "neuen" laufen unter Windows, Linux und MAC OS.

Autor: D. R. (reisii)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volker S. schrieb:
> aktuelle Tools ausgetauscht werden sollten.

ich werde mal mit dem Lehrer darüber reden wir haben halt nur diese 
MPLAB und den PIC22... bekommen

Volker S. schrieb:
> Die Verarbeitung ist aber tricky-

ich glaub ich bleib einfach beim Timer beschreiben ^^

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. R. schrieb:
> ich glaub ich bleib einfach beim Timer beschreiben ^^

Mach das. Der ganze zusätzliche Aufwand lohnt gar nicht, weil das am 
Ende keiner mehr so machen würde. Es geht ja viel einfacher und 
automatisch mit dem Compare Modul.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt auch noch die Möglichkeit, einen Prescaler zu verwenden.
Wenn man z.B. 64 als Prescaler nimmt und nicht durch andere Interrupts 
mehr als 64 CPU-Takte verzögert wird, dann ist das Laden des Timers in 
SW auch genau.
Natürlich darf man nicht auch noch den Prescaler neu starten, sondern 
der muß durchlaufen.

Autor: Volker S. (vloki)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Natürlich darf man nicht auch noch den Prescaler neu starten, sondern
> der muß durchlaufen.

Das kann man sich hier leider nicht aussuchen.

#####################################################
When assigned to the Timer0 module, all instructions
writing to the TMR0 register (e.g., CLRF TMR0, MOVWF
TMR0,BSF TMR0, etc.) clear the prescaler count.
#####################################################

Autor: Ingo S. (schicki)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo,

ich habe das beim PIC 18F auch schon öfter gemacht. Allerdings hat mein 
PIC einen RTV via I2C angebunden.

http://www.schwabenplan.com/allgemeines.htm

PIC18F46K80 oder PIC18F97J60

Viele Grüße
Ingo

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.