Hallo, ich programmiere im moment eine Binär Uhr und habe jetzt das Uhren Script fertig :) Ich weiß das es nicht genau ist, aber ich werde das ganze bei gelegenheit mit einem Quarz anpassen. Nun weiß ich allerdings nicht ob der Quellcode so stimmt (ich kann ihn leider auch nicht testen). Würde mich freuen wenn ihn mal jemand schnell durchlesen könnte und mir sagen könnte ob das so funktioniert. Grüße Sebastian
> _delay_ms(1000);
das wird je nach verwendetem quarz nicht klappen, du solltest lieber
einen timer verwenden (max einstellbare zeit: 262.1 ms / F_CPU in MHz)
die abfragen benötigen ja auch zeit, du hast also deine 1000ms+zeit für
abfragen, also definitiv mehr als 1s
Einige Anfängerfehler sind enthalten: if (s2 = 6) muss geändert werden auf if (s2 == 6) sonst wird der Wert 6 zu s2 zugewiesen und das ergibt immer "Wahr" gleiches bei h2 und m2 [edit] noch etwas: if (h1 > 9) && (h2 < 2) sollte so aussehen if ((h1 > 9) && (h2 < 2)) oder if (h1 > 9 && h2 < 2) [edit] Und Strichpunkte nicht vergessen h2 = h2 + 1 h1 = 0
Und folgende Zeile ist auch von der Logik her falsch: if (h2 = 2) && (h1 < 5)
wow gleich so viele Fehler ^^ Ich werde sie mal berichtigen und dann nochmal den Code schicken. Achja @Stefan Ernst: Ich find den Fehler in der Logic nicht. Meinst du das ich es so schreiben soll oder etwas anderes? -> if ((h1 == 5) &&(h2 == 2)) Achja und @ Gast: Wie soll ich das mit dem delay_ms(1000) dann anders schreiben? Danke schonmal für eure Hilfe.
Ja ich programmier noch net lange Microprozessoren. Bin also noch net so routiniert :)
> Achja @Stefan Ernst: > Ich find den Fehler in der Logic nicht. Meinst du das ich es > so schreiben soll oder etwas anderes? > -> if ((h1 == 5) &&(h2 == 2)) Bei "if ((h2 == 2) && (h1 < 5))" hat der Tag nur 20 Stunden, und bei obiger Zeile hat er 25 Stunden. ;-)
OH danke.... Also richtig ist es dann so: if ((h1 == 4) && (h2 == 2)) { h2 = 0; h1 = 0; } Danke :) Hätte mich dann gewundert wenn der Tag 25 Stunden hat ^^ Wie soll ich das mit dem Delay_ms(1000) anders schreiben damit die Uhr genauer wird?
> Wie soll ich das mit dem Delay_ms(1000) anders schreiben damit die Uhr > genauer wird? Du konfigurierst einen der Timer so, dass er ein mal pro Sekunde einen Interrupt auslöst, und in der Interruptroutine machst du dann deine Berechnungen. Dann ist deine Uhr so genau, wie der Takt des AVR. Falls der Timer sich nicht auf 1s konfigurieren lässt, kannst du ihn z.B. auch auf 10ms programmieren, und dann erst mal eine Variable bis 100 zählen lassen, quasi als Vorstufe zu den Sekunden.
Am besten einen externen 32.768kHz Uhrenquarz und per Interrupt im Sekundentakt die Uhrzeit erhöhen siehe hier Beitrag "Warum Uhrenquarz 32,768 kHz?"
Wie kann man dass den Umrechnen... Also zum Beispiel woher weiß man das wieveile interupts in der Sekunde ein 16 MHz Quarz auslöst?
Sebastian H. wrote: > Also zum Beispiel woher weiß man das wieveile interupts in der Sekunde > ein 16 MHz Quarz auslöst? Das stellt man sich selber entsprechend passend ein. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Die_Timer.2FCounter_des_AVR
Danke ich werde mir das tutorial mal durchlesen und dann weitere fragen stellen (sofern noch welche vorhanden sind) Grüße Sebastian
Den Timer auf Asynchronen Modus schalten und den Teiler auf / 128 einstellen und einen OVF Interrupt schreiben (32768 / 128 = 256) der Timer läuft von 0 auf 255 und beim Überlauf wird der Interrupt ausgeführt. Beispiele gibt es hier http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 AVR134: Real-Time Clock using the Asynchronous Timer
ok... könnt mit vielleicht jemand einen einfachen interupt timer für den Anfang schicken, damit ich damit ein wenig rumbasteln kann und lernen kann wie das ganze funktionert?
Hallo, da es mir im moment noch nicht auf die genauigkeit ankommt, habe ich mal das Programm weiter geschrieben. Allerdings zeigt das ganze im moment nur blödsinn an (ausgegeben sollen nur die sekunden) Wo liegt denn der Fehler?? Grüße Sebastian
Kenne nur die Interrupts vom IAR Compiler, bei gcc müsstest du die Interrupt Routine anpassen // Initialisieren des Timers und freichalten des Interrupts void InitUhr(void) { TIMSK2 = 0; //TC2 Interrupt Ausschalten ASSR = (1<<AS2); //Timer/counter2 auf asynchronous mode (32,768kHz) TCNT2 = 0x00; TCCR2A = ((1<<CS22)|(1<<CS20)); //prescaler setzen / 128 //Einen Uhrenquarz-takt abwarten while(ASSR & ((1<<TCN2UB)|(1<<OCR2UB)|(1<<TCR2UB))); TIMSK2 = (1<<TOIE2); //8-bit Timer/Counter2 Overflow Interrupt aktivieren } //Hauptprogramm void main(void) { ... InitUhr(); while(1) { ... } } // Interrupt #pragma vector=TIMER2_OVF_vect void Time_Interrupt(void) { // erhöhen der Urzeit ... }
Probier mal _delay_ms(10); auf _delay_ms(1000); Dann bei den &= die | in Klammer einschließen PORTA &= ~ (1 << PA0)|(1 << PA1)|(1 << PA2)|(1 << PA3); wie folgt PORTA &= ~ ((1 << PA0)|(1 << PA1)|(1 << PA2)|(1 << PA3)); ~ hat die selbe priorität wie | wenn ich mich nicht täusche
das mit dem delay_ms hab ich schneller gemacht, damit irgendwas passiert :) Bei _delay_ms(1000) hat das ewig gedauert. Werde dann mal alle so PORTA &= ~ ((1 << PA0)|(1 << PA1)|(1 << PA2)|(1 << PA3)); umschreiben. Hoffe das funktioniert dann. Fals ihr noch mehr fehler findet unbedingt posten :) Danke für eure Hilfe ich melde mich dann wieder, wenn ich das geändert hab.
So auf den ersten Blick würde ich sagen, du willst auf PA0 bis PA3 das Binärmuster von s1 ausgeben, oder? PORTA &= 0xf0; PORTA |= s1;
Und wenn du zusätzlich auf PA4 - PA7 s2 ausgeben willst, wird es noch einfacher: PORTA = (s2 << 4) | s1;
Die s1 sind aber nicht binär sondern 1 - 9 ^^ Jetzt brauch ich nur noch eine Interruptbefehl mit einem externen Quarz (oder am besten den Internen Quarz eines ATMega 16)
Sebastian H. wrote:
> Die s1 sind aber nicht binär sondern 1 - 9 ^^
Hä? Wie meinst du das?
naja s1 ist ja eine Variable in der immer + 1 Addiert wird ? Vielleicht hab ich auch grad nen Denkfehler drin aber ich denke das wenn man das eingibt PORTA = (s2 << 4) | s1; dann wird als zweiter ausgang s1 ausgegeben (also zum beispiel 3) und das ist ja nicht binär :? Fals ich mich jetzt irre bitte sagen : Könnte mir vielleicht noch jemand einen Interruptbefehl mit einem externen Quarz (oder am besten den Internen Quarz eines ATMega 16) schreiben/schicken damit ich mir das mal anschauen kann (ich lerne sowas am besten wenn ich einen funktionierenden code vor mir habe) :)
Hi, geh doch einfach mal in die Codesammlung und such mal nach Peter Danneggers "genaue Sekunde". Kann ich nur Empfehlen. Cecky
#define fosc 80000000 //8 MHz Quarz zwischen XTAL 1 und XTAL 2 #define SEI __enable_interrupt() #define CLI __disable_interrupt() void init_Timer1(void) { OCR1A = 0xBB7F; // TOP = 47999 TIMSK |= (1<<OCIE1A); // CTC-Interrupt zulassen TCCR1B = (1<<CS12) | (1<<WGM12); // Mode 4 (CTC; OCR), Timer starten PSC = 256 } #pragma vector = TIMER1_COMPA_vect __interrupt void TIMER1_COMPA_Interrupt(void) { //Hier dann das mit der Uhr rein schreiben } int main( void ) { // Variablen vereinbaren / initialisieren init_Timer1(); // Interrupts freigeben SEI; while(1) { } return 0; } Würde das funktionieren ?? @Daniel: den code kapier ich nicht ^^
Sebastian H. wrote: > dann wird als zweiter ausgang s1 ausgegeben (also zum beispiel 3) und > das ist ja nicht binär :? Und was glaubst du, wie diese 3 im Speicher steht, wie sie vom Prozessor verarbeitet wird und wie sie auf dem Port ausgegeben wird, wenn nicht binär?
k cool :) das wusste ich nicht :) Da kann ich ja dann ganz schön viel code einsparen. Was haltet ihr davon? #define fosc 80000000 //8 MHz Quarz zwischen XTAL 1 und XTAL 2 #define SEI __enable_interrupt() #define CLI __disable_interrupt() void init_Timer1(void) { OCR1A = 0xBB7F; // TOP = 47999 TIMSK |= (1<<OCIE1A); // CTC-Interrupt zulassen TCCR1B = (1<<CS12) | (1<<WGM12); // Mode 4 (CTC; OCR), Timer starten PSC = 256 } #pragma vector = TIMER1_COMPA_vect __interrupt void TIMER1_COMPA_Interrupt(void) { //Hier dann das mit der Uhr rein schreiben } int main( void ) { // Variablen vereinbaren / initialisieren init_Timer1(); // Interrupts freigeben SEI; while(1) { } return 0; }
Sollte funktionieren, nur noch #define fosc von 80 MHz auf 8 MHz setzen. Laut meinen Berechnungen ist 8000000 / 256 = 31250 auf den du den Compare Match setzen solltest
Nein, mit dem GCC wird das ganz sicher nicht gehen. Das ist Code für einen anderen Compiler (ICC ?).
hm k hab ich mir aus dem forum zusammengestückelt. Könnte mir jemand das ganze nach C für AVR-GCC umschreiben?
1 | #include <avr/interrupt.h> |
2 | |
3 | |
4 | void init_Timer1(void) { |
5 | |
6 | // Hier Timer initialisieren
|
7 | }
|
8 | |
9 | |
10 | ISR(TIMER1_COMPA_vect) { |
11 | |
12 | // Hier dein Uhr-Code
|
13 | }
|
14 | |
15 | |
16 | int main( void ) { |
17 | |
18 | init_Timer1(); |
19 | |
20 | sei(); |
21 | |
22 | while(1) {} |
23 | |
24 | return 0; |
25 | }
|
Also so? #include <avr/interrupt.h> #define fosc 80000000 //8 MHz Quarz zwischen XTAL 1 und XTAL 2 void init_Timer1(void) { OCR1A = 0xBB7F; // TOP = 47999 TIMSK |= (1<<OCIE1A); // CTC-Interrupt zulassen TCCR1B = (1<<CS12) | (1<<WGM12); // Mode 4 (CTC; OCR), Timer starten PSC = 256 } ISR(TIMER1_COMPA_vect) { // Hier dein Uhr-Code } int main( void ) { init_Timer1(); sei(); while(1) {} return 0; }
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.