Ich mal wieder ;-)
Ich bastle nun schon seit geraumer Zeit mit meinem 18F4520 rum... Und
wieder hab ich Probleme mit den Interrupts.
Kurze Beschreibung zum Ablauf.
Ein externes Signal (DCF77) lege ich an INT1 und INT2 an ... INT1 ist
dabei Interrupt mäßig auf High-Edge gestellt, INT2 auf Low-Edge
Sinn und Zweck der geschichte ist, die Impulslänge zu messen.
Mysterium eins: wenn ich die Interrupts wechsle (es kam eine High Flanke
-> Int1 aus -> INT2 an um auf Low-Flanke reagieren zu können) wurde
jedesmal GIEL auf Low gesetzt... beide Interrupts sind Low-Prio...
Nach ewigen rumgesuche schalte ich nun bei jedem Flankenwechsel den GIEL
manuel wieder ein ...
Mysterium zwei: Damit das sinn macht, werd nach erhalt der High-Flanke
Timer0 gestartet. nach erhalt der Low-Flanke dieser gestoppt und gelesen
... so ermittle ich Impulslänge ...
ABER: das Mistding ^^ springt einfach nicht in die ISR (Timer0 ist als
High Prio definiert)
Damit ich meine Definitionen der Prio's, Flanken ect auch wärend des
"BEtriebs" nachvollziehen/kontrollieren kann, lass ich mir mitlerweile
sämtliche Interrupts / Prio's an diversen Ports ausgeben (zur Kontrolle)
alles Stimmt, aber T0 Interrupt springt einfach nicht zur entspr. Pos.
bissel Quelltext:
Frage ist, wieso springt er nicht in die High Interrupt Routine (Anhand
meines angeschlossenen LCD sehe ich auch, das er Zählt (TMR0L ändert
sich ständig)
in der Initialisierung ist nat. T0 configuriert
@ Gero Nimo (geronimo76)
>Ein externes Signal (DCF77) lege ich an INT1 und INT2 an ... INT1 ist>dabei Interrupt mäßig auf High-Edge gestellt, INT2 auf Low-Edge>Sinn und Zweck der geschichte ist, die Impulslänge zu messen.
Das ist ersten Pinverschwendung und zweitens ungünstig. Denn diese
Schaltung reagiert auf kleinste Pulse, sprich Störungen.
Praktisch tastet man das Signal mittels Timer-Interrupt mit ca. 100Hz ab
und misst damit die Pulsbreite.
MFG
Falk
Gero Nimo schrieb:> Ein externes Signal (DCF77) lege ich an INT1 und INT2 an ... INT1 ist> dabei Interrupt mäßig auf High-Edge gestellt, INT2 auf Low-Edge> Sinn und Zweck der geschichte ist, die Impulslänge zu messen.
Ja, man kann es auch höllisch kompliziert machen.
Oder man überlegt erstmal, was braucht man.
Eine supergenaue Messung ist nämlich völlig überflüssig.
Man muß ja nur 100ms von 200ms unterscheiden und für die Synchronisation
die 1000ms von 2000ms.
Und dann geht alles popelinfach nur mit nem Timerinterrupt 10ms und 2
Zählbytes (Puls, Periode) darin:
7 - 13: 0-Bit
17 - 23: 1-Bit
70 - 130: Sekundendauer
170 - 230: Sync-Sekunde
Und fertüsch.
Peter
Interessante Aufgabenstellung. Ich hätte diesen Ansatz um Zeiten zu
messen auch schon brauchen können.
>/*Timer 0 Settup */> T0CON = 0b00000111; // OFF | 8bit | 256PreScale> INTCON2bits.TMR0IP = 1; // High Interrupt
Okay soweit.
Aber:
GIEH für das Abarbeiten der ISR von T0 in der entsprechenden
Flankenroutine gesetzt? Ich habe es in deinem Code nicht finden können.
Mir ist so ziemlich das gleiche auch mal passiert...
Interrupts sind an. lasse ich mir sogar per LED anzeigen um diese
fehlerquelle ausschließen zu können
Es ist mir Klar, das ich mit den TimerInterrupt arbeiten muss.. nur wenn
er bei Overflow nicht in die ISRT springt, bringt mir das nix ...
ich arbeite mit 20Mhz Quarz ... ergo ist bei einem 1:256 Verhältnis
jeder TimerTakt 0,05 ms => 12,8 ms für jeden überlauf (0-255)
bei nem 8bit timer muss ich also den overflow interrupt nehmen um die
anzahl der interrupts zu zählen (t0_teiler) ... also sind 8 überläufe
rund eine sekunde ,,,, da aber der Interrupt nicht funktioniert (er
apringt nicht in die ISR) kann ich auch nicht die durchläufe und somit
nicht die ms ermitteln...
eine möglichkeit wäre, denTimer0 auf 16bit umzustellen .. muss ich mal
probieren
Nachtrag .... T0 stand auf 16bit ,,, da kann es natürlich nicht zu
Keinem überlauf kommen^^
Kennt jemand ein Tool, mit dem ich mir den To einstellungen berechnen
lassen kann .. so wie hier:
http://www.best-microcontroller-projects.com/pic-timer-0.html
ich brauchs aber für 16bit variante / 256prescale
Klar ist ein 16bit timer die elegantere lösung (ICH DEPP) ... bei Timer0
schaltet mein Hirn automatisch synchron in den 8bit modus :))
und wenn ich mir das recht überlege, brauch ich dann nicht mal mehr den
Overflow Interrupt... zählt er dann ja bis 65536 .. was rund 3,2 seks
sind :)
gleich heut abend mal testen .. jetzt heißt es erstaml 8h arbeiten :(
>zählt er dann ja bis 65536 .. was rund 3,2 seks
sind :)
Glaub ich nicht. Wenn dein PIC mit 20MHz/4 läuft, sind 256 * volle 16bit
ca 0,3 sek. Zeit messen ist nix gescheites mit dem Takt, man sollte
irgendwas Vielfaches von 16bit haben wenns genau werden soll... deswegen
bin ich auf den Uhrenquartz ausgewichen... und selbst der geht 2sek/h
weg...
Hab ich da jetzt nen Denkfehler?
20Mhz / Fosc(4) sind 5Mhz ... PreScaler von 256 macht doch knapp
19.531,25 KHz => (1/s) => 0,0000512s pro zählwert .. also aller 0,0512ms
erhöht der den 16bit counter um 1 ... => x65536 => 3355,66ms = 3,3...sek
Rechne ich da was falsch?
wenn ich mir anhand des Timer1 berechnungstools
(http://www.best-microcontroller-projects.com/pic-timer-1.html) mal die
werte für 1:8 prescale und 20Mhz ansehe, bin ich ja schon bei 104ms /
kompletten durchlauf ,,, der T0 teilt aber 1:256 .. also das 32fache ...
32x104ms sind auch wieder um die 3,3seks
Mea culpa. Sorry, stimmt. 3,3 sek. Irgendwie wohl 'n
Taschenrechner-Tippfehler.
Aber sag mal, gibt's DCF Empfängerroutinen nicht schon fix und fertig im
Netz? Oder steckt da mehr dahinter?
Hallo
Genau wegen diesen Rechnereien die mir als Anfänger das Leben schwer
machen, erstelle ich diese Javascript Hilfsmittel.
Ist zwar noch in Arbeit, möchte es noch erweitern mit der Anzeige der
Interrupts, aber mit Euren Daten spuckt er 3.3555/sek aus.
Die Zahlen sollten stimmen, nehme gerne Korrekturen an.
P.S. Ist Fosc(4) ein zusätzlicher Teiler beim PIC??
Würde den noch einbauen.
bjn
bjnas schrieb:> Genau wegen diesen Rechnereien die mir als Anfänger das Leben schwer> machen, erstelle ich diese Javascript Hilfsmittel.
Ooch nöö.
Der Compiler kann doch Konstanten prima selber ausrechnen.
Einfach nur die Formel hinschreiben als Define und benutzen.
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC
Peter
Das Tool ist auch nicht für so Profis gedacht wie Du einer bist.
Bin immer wieder begeistert wie Du den Code optimierst. Bis ich Laie den
dann begreife, helfen mir diese Tools (manchmal!!).
bjn
>P.S. Ist Fosc(4) ein zusätzlicher Teiler beim PIC??
Grau ist alle Theorie?
Jeder externe Osc.takt (Quartztakt) wird für das Rechenwerk in einer
Vierer-Kombination genutzt:
Q1 -> Q2 -> Q3 -> Q4 -> Q1 -> Q2 usf.
Nur bei jedem 4. Takt (bei Q1) wird der Programmzähler auf die
entsprechende Addresse neu eingestellt und damit der nächste Befehl
abgearbeitet. Die dazwischen liegenden Takte braucht das Rechenwerk um
beispielsweise ein Datum einzulesen, es zu verändern und
zurückzuschreiben.
Siehe auch: PIC18 Instruction Cycle/CLOCKING SCHEME
Es gab mal Zeiten, da hat ein Vorgang beim 8051 nicht nur vier Osc.takte
benötigt sondern zwölf...
Joachim schrieb:> PIC, Peterchen, PIC!
Das ist ja das schöne an C.
Ob 8051, ARM, AVR oder PIC ist egal, C bleibt C.
Die Konstanten muß also auch Dein PIC-Compiler schon zur Compilezeit
ausrechnen und die Ergebnisse in die Register laden.
Die IO-Register heißen beim AVR halt anders und ihre Funktion ist
ähnlich.
Peter
Mal zurück zum Thema interrupts .... nun hab ich es endlich hinbekommen,
mein DCF signal sauber zu lesen und Datum/Uhrzeit daraus ermitteln zu
können ..
Aber nun stehe ich wieder vor dem selben Problem, das ein PORTB Change
Interrupt den PIC völlig aus dem konzept brinbt..
MainSchleife sieht so aus
while(1)
{
if(DCF77_Status == 0) //hier hin, wenn Zeit abgeglichen werden muss
{
INTERRUPT_PortB_Off();
INTERRUPT_Int2_Off();
INTERRUPT_Int1_On();
INTERRUPT_Timer0_On();
INTERRUPT_Timer1_Off();
INTERRUPT_Low_On();
INTERRUPT_High_On();
//DCF Initialiseren
//Signal lesen und Flanken messen
//Bit ermitteln -> zeit berechnen
while(dcf_time == 0); //innerhalb der interrupts setzte ich dann
dcf_time auf 1, wenn zeit OK ist
}
else //hier hin, wenn Zeit OK => standard ausgabe
{
INTERRUPT_PortB_On();
INTERRUPT_Int2_Off();
INTERRUPT_Int1_Off();
INTERRUPT_Timer0_Off();
INTERRUPT_Timer1_On();
INTERRUPT_Low_On();
INTERRUPT_High_On();
while(dcf_status == 1)
{
//Ausgabe LCD wie zeit, temp ect.
//
}
}
} //ENDE MainWhile
alles funktioniert ... er gleich die Zeit ab, wechselt die Interrupts
und bleibt dann in der "Standard ausgabe" .. aber sobald ich eine taste
drücke, die am PortB<7:4> hängt, spinnt er rum .. als würde er nen RESET
ausführen. allerdings werden willkürlich interrupts gesetzt (xxxIE)
hat das event. was mit den eingeschalteten PULLUPS zu tun? ...
1)
http://img826.imageshack.us/i/portb452.png/
Na ich würd' schon sagen daß man die Pull-ups wegnehmen muß, immerhin
gegen die direkt auf den Porteingang.
2)
The interrupt flag bits must be cleared in software before re-enabling
interrupts to avoid recursive interrupts.
Dein
INTERRUPT_Int1_Off();
macht das vermutlich, sprich: tut das entsprechende Int Enable Bit
löschen, oder? Das eigentliche I-Bit (Flag) kann man nicht sperren.
3)
Najaah... ich würde hat einfach mal nach und nach Software-Teile
abhängen um zu kucken wo's herkommt.
im ISR gehe ich natürlich nach den Anweisungen
1. Interrupt aus
2. Flag löschen
3. Code, was der interrupt eig. bewirken soll ....
4. Inerrupt wieder an
ich hab mir nur die kleinen funktionen dazu gebastelt, da es dann für
mich übersichtlicher bleibt ,,, ansonsten muss ich ständig nachschauen,
in welchen der 5 register die Enable-bits und welchen die Flag-bits
stehen
... werd das ganze später mal ohne zugeschaltete Pullups testen .. hoffe
es liegt daran