Gast
#323040
Hi, ich bastele gerade an einem Digitaluhrprojekt. Dabei wird die Uhrzeit in einem Uhrenbaustein aus dem Hause Dallas (DS1302) gespeichert. Dieser wird mit Hilfe eines GoldCap-Kondensators (1F) bei Laune gehalten, falls die Energieversorgung mal unterbrochen wird. Datum und Uhrzeit aus dem DS1302 werden auf einem grafischen LCD 128x64 Pixel dargestellt. Und das alles wird von einem Atmel 8052 mit 24kbyte Speicher kontrolliert. Soweit so gut. Nun soll das ganze um einen Drehimpulsgeber erweitert werden, damit die Uhrzeit auch ohne Hilfe eines PCs (serielle Schnittstelle) gestellt werden kann. Der Drehimpulsgeber lässt sich nach links und rechts drehen und zusätzlich drücken Ich möchte durch einen Druck auf den Drehimpulsgeber in das Uhr stellen Menü gelangen und dann die Einzelnen Positionen mit dem drehen nach links (minus) bzw. rechts (plus) einstellen. Im Moment ist der Druck auf den Drehimpulsgeber am externen Interrupt0 angeschlossen und die beiden Kontakte für links und rechts jeweils an Port0.0 bzw P0.1 Doch leider funktioniert das ganze nicht so wie geplant. Ich hatte mir überlegt bei jedem druck auf den Taster einen Interrupt auszulösen, der eine Variable hoch zählt so nach dem Motto einmal drücken Uhr stellen Modus 2. Mal drücken Tag stellen 3. Monat stellen 4. Jahr stellen und so weiter . Der Interrupt löst auch aus nur leider hat die Zählvariable dann nicht den Wert 1 oder 2 oder 3 sondern ehr in der Größenordnung 26000. Nach stöbern in diesem netten Forum habe ich herausgefunden, dass der externe Interrupt bei gedrückter Tast ein mal pro 1us auslöst . Ist es dann überhaupt sinnvoll das mit einem externen Interrupt zu lösen? Oder was würdet ihr vorschlagen? Die beiden Zustände mit denen mal herausbekommt ob der Drehimpulsgeber nach links oder nach rechts gedreht worden ist hole ich einmal pro 1ms über einen Timer0 Interrupt ab, aber das schein auch noch nicht so wirklich zu funzen Ich würde mich sehr über ein paar Anregungen von euch freuen ich bin relativ neu auf diesem Gebiet und programmiere mit C. MfG Nils etwas Quellcode zur Erklärung: #include <stdio.h> #include "mc.h" #include "Print.h" #include "DS1302.H" #include "display.h" #include "control.h" unsigned char M; int lcd_refresh, setclk, abx,set =0; long int i = 0; /** * Timer0 Interrupt-Routine. * * Regelt die Erneuerung der LCD-Anzeige ueber den * Wert von lcd_refresh. Timer0 löst alle 20ms einen * Interrupt aus. * */ void timer0() interrupt 1 { int ab,yy=0; lcd_refresh++; // regelt den LCD-Refesh //Drehimpulsgeber drehung abfragen cw bzw. ccw //--------------------------------------------------------- ab = (A_ & B_); if (ab != abx) { yy = ab ^ abx; // XOR if ((ab == 0) | (ab == 3)) // a = b { if (yy == 1);// set--; if (yy == 2) set++; } else // a != b { if (yy == 2);// set--; if (yy == 1) set++; } } abx = ab; //--------------------------------------------------------- TR0 = 0; //var Timer0 stoppen TL0 = Timer0L; // Startwerte Timer0 Low TH0 = Timer0H; // Startwerte Timer0 High TR0 = 1; // Timer0 starten } void EXT_IRS_0() interrupt 0 { IT0=0; setclk++; } /** Uhrzeit/Datum-Ausgabe auf LCD. * * Erstellt aus dem Struct Uhr die Chararrays zeit und datum * und gibt sie auf dem LCD aus. * */ void wr_clock(void) { date_s uhr; // Datumsstruckt Uhr definiert in DS1302.h unsigned char *days[] = {"Mo","Di","Mi","Do","Fr","Sa","So"}; unsigned char tag[3]; // temorärer Array zum aufnehmen des aktuellen Tages unsigned char zeit[9]; // aktuelle Zeit[std:mim:sec] unsigned char datum[9]; // aktuelles Datum [dd:mm:yy] read_ext_clk_regs(&uhr); // DS1302 Register auslesen. sprintf(zeit,"%02bx:%02bx:%02bx",uhr.hr,uhr.min,uhr.sec); // Aktuelle Uhrzeit in Zeitarry schreiben sprintf(datum,"%02bx.%02bx.%02bx", uhr.date, uhr.mn, uhr.yr); // Aktuelles Datum in Datumsarry schreiben sprintf(tag,"%s",days[uhr.dy-1]); // Aktuellen Tag ins Tagesarray schreiben if(setclk==0){ Print3(zeit,1,3,weiss); // Uhrzeit ans LCD senden Print2(tag,5,3,weiss); // Wochentag ans LCD senden Print2(datum,5,35,weiss); // Datum ans LCD senden //printf("%s\n",zeit); // Uhrzeit auf der Konsole ausgeben } } /** Uhrzeit/Datum stellen * * Liest die Angaben über Datum und Uhrzeit von der Tastatur ein * und veranlasst das schreiben in die Register des DS1302. * * */ void set_clock(){ date_s uhr; unsigned char tmp[3]; printf("\nUhr wird gestellt\n"); ClearLCD(); set=0; //zurücksetzen Print2("komplett stellen ?",0,0,weiss); Print2("Ja ->rechts",2,0,weiss); Print2("Nein ->links ",4,0,weiss); read_ext_clk_regs(&uhr);//aktuelle Uhrzeit/Datum holen while(set==0); // auf entscheidung warten ClearLCD(); printf("setclk: %d",setclk); if(set>0){ // Uhr komplett stellen while(setclk==1){// ----------------------------------Datum Print2(" ",5,41,weiss);//Jahr überschreiben while(lcd_refresh>=10); //blinken, pause 100ms if(set>=99)set=0; //Jahr zurücksetzten if(set<=-1)set=98; // uhr.yr=set; //Drehimpuls holen sprintf(tmp,"%02bx",uhr.yr); Print2(tmp,5,41,weiss); //geändertes Datum auf Display } while(setclk==2){ // ----------------------------------Datum //read_ext_clk_regs(&uhr); //aktuelle Uhrzeit/Datum holen Print2(" ",5,38,weiss); //Monat überschreiben while(lcd_refresh>=10); //blinken, pause 100ms if(set>=12)set=0; //Monat zurücksetzten if(set<=-1)set=11;// uhr.mn=set; //Drehimpuls holen sprintf(tmp,"%02bx",uhr.mn); Print2(tmp,5,38,weiss); //geändertes Datum auf Display } while(setclk==3){ // ----------------------------------Datum //read_ext_clk_regs(&uhr); //aktuelle Uhrzeit/Datum holen Print2(" ",5,35,weiss);//Tag überschreiben while(lcd_refresh>=10); //blinken, pause 100ms if(set>=31)set=0; //Tag zurücksetzten if(set<=-1)set=30; // uhr.dy=set; //Drehimpuls holen sprintf(tmp,"%02bx",uhr.dy); Print2(tmp,5,35,weiss); //geändertes Datum auf Display } while(setclk==4){ // ----------------------------------Uhrzeit //read_ext_clk_regs(&uhr); //aktuelle Uhrzeit/Datum holen Print2(" ",1,3,weiss); //Stunde überschreiben while(lcd_refresh>=10); //blinken, pause 100ms if(set>=24)set=0; //Stunde zurücksetzten if(set<=-1)set=23;// uhr.hr=set; //Drehimpuls holen sprintf(tmp,"%02bx",uhr.hr); Print2(tmp,1,3,weiss); //geändertes Datum auf Display } while(setclk==5){ // ----------------------------------Uhrzeit //read_ext_clk_regs(&uhr); //aktuelle Uhrzeit/Datum holen Print2(" ",1,6,weiss); //Minute überschreiben while(lcd_refresh>=10); //blinken, pause 100ms if(set>=60)set=0; //Minute zurücksetzten if(set<=-1)set=59;// uhr.mn=set; //Drehimpuls holen sprintf(tmp,"%02bx",uhr.mn); Print2(tmp,1,6,weiss); //geändertes Datum auf Display } while(setclk==6){ // ----------------------------------Uhrzeit //read_ext_clk_regs(&uhr); //aktuelle Uhrzeit/Datum holen Print2(" ",1,9,weiss); //Sekunden überschreiben while(lcd_refresh>=10); //blinken, pause 100ms if(set>=60)set=0; //Sekunden zurücksetzten if(set<=-1)set=59; // uhr.sec=set; //Drehimpuls holen sprintf(tmp,"%02bx",uhr.sec); Print2(tmp,5,35,weiss); //geändertes Datum auf Display } } else{ while(setclk<=1){ // ----------------------------------Uhrzeit //read_ext_clk_regs(&uhr); //aktuelle Uhrzeit/Datum holen Print2(" ",1,3,weiss); //Minute überschreiben while(lcd_refresh>=10); //blinken, pause 100ms if(set>=24)set=0; //Minute zurücksetzten if(set<=-1)set=23; // uhr.hr=set; //Drehimpuls holen sprintf(tmp,"%02bx",uhr.hr); Print2(tmp,1,3,weiss); //geändertes Datum auf Display } } setclk=0; write_ext_clk_regs(&uhr); } /** Kommunikation zwischen DS1302 und LC-Display * * Control.c initialisiert dem Atmel 8052 Kontroller und kontolliert die Kommunikation * zwischem dem Dalls DS1302 Uhrenbaustein und dem LC-Display KS1802. * @version $Revision: 1.0 $ $Name: Hoffmann / Anger $ */ void main (void) { //------------------------- Timer1 Initialisierung für Baudrate TMOD = 0x21; // Timer 1 = 8-Bit-Timer mit Auto-Reload-Modus. // Timer 0 = 16-Bit-Timer. TL1 = Timer1L; // 19200 Baud bei 22,118 MHz TH1 = Timer1H; // Nachladewert fuer TL1 TR1 = 1; // Timer 1 starten SCON = 0x52; // Freigabe von Sender und Empfaenger; Betriebsart: Modus 1 TL0 = Timer0L; // Startwert für Timer0 0x7000 TH0 = Timer0H; // dezimal 28672 => Interrupt alle 20ms ET0 = 1; // Timer0 Interrupt einschalten EA = 1; // Interrupt einschalten TR0 = 1; // Timer 0 starten EX0 = 1; // Externer Interrupt 0 einschalten IE0 = 1; // Interrupt0 reagiert auf negative Flanke ClearLCD(); // LCD löschen printf("Neustart"); Print3(" N.H&B.A",1,0,weiss); Print2(">>DigiWatch<<",6,0,weiss); while(lcd_refresh <200) ; // Warteschleife für Projekt Startseite (2 sec) ClearLCD(); while(1) { if (lcd_refresh >= 20) // Display aktuallisieren { // 10 entspricht ca. 20ms wr_clock(); lcd_refresh =0; printf("%d\n",set); } if(setclk>0) set_clock(); } }