Stoppuhr
Dienstag, 22. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  PIC Mikrocontroller Allgemein  |  Timer (Allgemein)  |  Stoppuhr « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Umfrage
Frage: muss ich mit 2 Interrupts arbeiten?
---   -0 (0%)
----   -0 (0%)
Stimmen insgesamt: 0

Autor Thema: Stoppuhr  (Gelesen 3835 mal)
 
medo
Newbie
*
Offline Offline

Beiträge: 2


Profil anzeigen
« am: Juli 04, 2007, 23:47:18 »

Hi Leute!
ich muss 6 stellige 7-Segment-Stoppuhr programmieren mit einer Auflösung von 10ms.Die Zeitmultiplexing der LEDs muss mit einem Timer realisiert werden (50 Hz) und die Zeit muss auch intern mit einem Timer realisiert werden.
Kann ich die LED-Multiplexing und die Zeit mit dem Timer0 machen oder benötige ich zwei Timer.
Falls ich zwei Timer benutze, wie kann ich die beide Interrupt verwenden. Der Timer für die Zeit muss ständig laufen
kann mir jemand helfen.
Gespeichert
Flo
Full Member
***
Offline Offline

Beiträge: 229



Profil anzeigen
« Antworten #1 am: Juli 05, 2007, 01:18:56 »

Hey!

Ich hab gerade vor kurzem ein ähnliches Projekt bearbeitet und habe nur den Timer1 und das CCP-Modul verwendet. Über das CCP-Modul im Compare-Modus kann man komfortabel eine sehr genau Zeitbasis schaffen, in meinem Fall waren das 100us. Und an dieser Zeitbasis kann man dann einfach alles mitzählen lassen, z.B. müssten 100 mal 100us vergehen das Du Deine 10ms hast.

Schau Dir dazu am besten mal das Datenblatt an -> 15.3 Compare Mode

Also einfach eine gewünschte Zeitbasis einstellen und dann die Überläufe mitzählen bis Du die Zeiten hast die Du brauchst. Ist es von der Aufgabe her notwendig Interrupts zu verwenden? Ansonsten kannst Du einfach das Interupt-Flag in der Software abfragen, das ist für eine Stopuhr genau genug.

Welche Programmiersprache und noch wichtiger welchem PIC verwendest Du denn? Bist Du neu bei den PICs? Bei Bedarf kann ich Dirs noch ein wenig genauer erläutern. Wofür brauchst Du denn die Aufgabe? *neugier*

Gruß
flo
Gespeichert
medo
Newbie
*
Offline Offline

Beiträge: 2


Profil anzeigen
« Antworten #2 am: Juli 05, 2007, 09:09:35 »

Danke für die Antwort.
ich arbeite mit dem 16F876 (kann auch anderen PIC benutzen) und progammiere mit C. Ich habe schon die klassiche PIC-Projekte (Blinker, LCD,Lauflicht..) gemacht sonst nicht. Ich habe noch nie mit CCP-Modul gearbeitet.
ich habe so überlegt, dass ich für Zeitbasis Timer0 benutze TMR0=131 und 4Mhz und prescaler von 8, damit kann ich alle 1ms Interrupt auflösen.
(Die Zeit kann ich auch mit Timer1 machen aber habe muss noch überlegen, wie ich es realisiere,welche prescaler, welche preload.usw...)
mein Problem: wie kann ich die LED-Multiplexing und zeitbasis realisieren. Es muss nicht Interrupt sein. Aber falls ich zwei Interrupt benutze. in welcher Reihenfolge oder welche zusammenhang gibt zwischen den beiden geben.
wie hast du  die Zeit-Multiplexing realisiert?

Gespeichert
Flo
Full Member
***
Offline Offline

Beiträge: 229



Profil anzeigen
« Antworten #3 am: Juli 05, 2007, 18:19:22 »

Also um das LED-Multiplexing hab ich mir nicht großartig Gedanken gemacht, Bedingung war eigentlich nur, dass die Anzeige möglichst hell sein sollte, damit die Kamera auch gut belichtet wird Smiley

Ich habe zusätzlich einen 74HC4543 (Treiber/Decoder/Latch) vor jede Sieben-Segment-Ziffer gebaut. Dadurch muss man nur den 4 Bit breiten Dezimalwert ausgeben und der Decoder bereitet die Daten dann so auf, dass die Sieben-Segment-Anzeige alles richtig anzeigt.
Bei mir sieht das dann so aus, wenn 100us rum sind werden alle Ziffern ausgeschaltet, alle Latches nacheinander mit neuen Werten beschrieben und danach werden alle Ziffern wieder eingeschaltet und die neue Zeit steht dann da. Der ganze Vorgang dauert so um die 3,6us.
Wenn du solche Bauteile auch anwenden darfst würde ich das machen.

Ich hab mir eben mal das Datenblatt angeschaut zu dem 18F876, der besitzt auch ein CCP-Modul. Schau mal unter 8.2 Compare Mode im Datenblatt. In dem anderen Beitrag von mir mit 15.3.. unter diesem Kapitel steht es in den 18F Datenblätter.
Das ist eigentlich ganz easy. Zuerst mal brauchst Du den TMR1 um mit dem CCP-Modul arbeiten zu können. Dann stellst Du das CCP-Modul so ein, dass es im Compare-Modus arbeitet und schreibst vorher noch den Zählerstand, wie weit der TMR1 zählen soll, in das CCPR1 Registerpaar. Nun wird ständig der TMR1 mit dem CCPR1 verglichen und wenn der TMR1 bis zu dem Wert im CCPR1 hochgezählt hat, wird das CCPIF-Interruptflag gesetzt und der TMR1 wird automatisch auf 0 gesetzt und läuft ganz normal weiter. Damit sparst Du Dir schonmal das vorladen des Timers. Einfach den Prescaler und das CCPR1 Register einmal richtig einstellen und Du bekommst ständig einen Interrupt in einem festen Interval.

Und das Programm könnte dann so irgendwie aussehen:
Code:
void main(void) {
unsigned char zehn_ms=0;
unsigned char led_mux=0;

init(); // Hier stellst Du alles ein was Du brauchst, CCP-Modul, CCPR1-Register, Pins usw...

while(1) {
if(CCPIF) { // Das CCPIF wird alle z.B. alle 1ms gesetzt)
CCPIF=0;
zehn_ms++;
led_mux++;

if(zehn_ms==10) {
zehn_mus=0;
// jetzt sind wieder 10ms vergangen und dann wird hier eine
// Funktion aufgerufen in der die Variablen der Zeit geändert werden
}

if(led_mux==XX) {
led_mux=0;
// hier gehts dann irgendwie weiter :)
}
}
}

Nur mit dem LED-Mux musst Du Dir mal etwas genauere Gedanken machen. Ich habs wie gesagt mit Latches gemacht und da ist die Anzeige ständig da, da muss nur beim beschreiben der Latches einmal gemuxt werden. Ansonsten hast Du bei 50Hz 20ms Periodendauer und in dieser Zeit müssten alle Anzeigen neu beschrieben werden. Also bei 6 Ziffer hättest du dann 3,33ms Leuchtdauer pro Ziffer. Das könnte vielleicht nen bissel dunkel werden Smiley aber ich würde es einfach mal versuchen.

Vielleicht so, ich nehme hier mal an, dass die Daten über PortA laufen und die Steuerleitungen über den PortB:
Code:
void main(void) {
unsigned char anzeige[5]={0,0,0,0,0,0}; // hier sollen die fertigen Daten zur Ausgabe stehen, für jede Ziffer ein Element
unsigned char i=0;

if(led_mux==3) { // wenn man das genauer brauch, muss man eine kleinere Zeitbasis wählen
led_mux=0;
ausgabe(anzeige[i], i);
i++;

if(i==6) { // wenn die letzte Ziffer beschrieben wurde, fängt es wieder von vorne an
i=0;
}
}
}

void ausgabe(unsigned char wert, unsigned char ziffer) {
LATB = 0; // die vorherige Stelle wieder ausschalten
LATA = wert; // Datenport mit neuem Wert beschreiben
LATB = 1<<ziffer; // an PortB hängen die Steuerleitungen common_anode oder common_kathode musst du dann selbst schaun
// die nächste Stelle einschalten
// und die bleibt für die nächsten 3 ms auch an
}

Also ob das so funktioniert weis ich nicht, sieht aber schonmal gut aus Smiley Probier einfach mal nen bissel rum...

Um noch mal auf Deine Frage wegen der Interrupts zurück zu kommen, bei den 16F war es glaub ich so, dass es keine priorisierten Interrupts gibt. Sobald ein Interrupt auftritt wird dieser abgearbeitet und falls währenddessen ein weiterer auftritt wird dieser danach abgearbeitet. Aber für diese Aufgabe brauchst die Interrupts nicht zu aktivieren, wenn Du das eine Flag einfach so in der Software abfragst ist das genau genug für eine Stopuhr. Die jeweiligen Interruptflags werden immer gesetzt, auch wenn die Interrupts nicht aktiviert sind (GIE bleibt 0). Es erfolgt dann einfach keine Programmunterbrechung.

Gruß
Flo
« Letzte Änderung: Juli 05, 2007, 18:23:19 von Flo » Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.1 Sekunden mit 21 Zugriffen.
 
Top! Top!