Hi, meine Uhr läuft viel zu schnell, doch warum? Ich benutze Timer0 im Modus2 (8Bit,Autoreload) Prozessor: AT89S8253 mit 22,1184 Mhz und x2 Mode Nun zur Berechnung: 22118400 / 6 = 3686400 ( 6 wegen x1 Mode, sonst 12) 3686400 / 192 = 19200 ( Reload für Timer0 (256-64) = 0xC0 ) 19200 / 64 = 300 ( tick1-Zähler in Interrupt-Routine) 300 / 3 = 100 ( tick2-Zähler in Interrupt-Routine) 100 / 100 = 1 s ( ms-Zähler in Interrupt-Routine) Da müsste dann doch 1 s rauskommen, dacht ich mir ABER es funktioniert so nicht. Selbst wenn ich den tick2 Teiler auf 6 verdopple ist noch zu schnell. Bei 12 ists zu langsam... Die Baudrate (Timer1, reload 0xFA, 38400 Baud) funktioniert doch auch, wo ist der Knoten bei Timer0 bzw. in der Berechnung??? Danke für Eure Tipps! Rabis
Zeig mal den dazugehörigen Code. Ansonsten können wir auch nur raten, wodran das Problem liegt. ;)
Ja, gerne main.h:
1 | //--------------------------------------------------------------------
|
2 | // Defines
|
3 | |
4 | #ifndef __MAIN
|
5 | #define __MAIN
|
6 | #endif
|
7 | |
8 | #define x2 1 // 0 or 1 , x2 mode
|
9 | #define XtalFreq 22118400
|
10 | #define Baudrate 38400 // 19200
|
11 | //#define TH0_RELOAD 0x0
|
12 | //#define TL0_RELOAD 0x0
|
13 | #define ON 0
|
14 | #define OFF 1
|
15 | #define LED_GN P0_0
|
16 | #define LED_YE P0_1
|
17 | #define LED_RD P0_2
|
18 | #define Beeper P0_3
|
19 | |
20 | //--------------------------------------------------------------------
|
21 | |
22 | __sbit __at (0x2F) BIT2F; |
23 | |
24 | //--------------------------------------------------------------------
|
main.c
1 | //--------------------------------------------------------------------
|
2 | #include "./main.h" |
3 | #ifdef __MAIN
|
4 | #include <at89s8253.h> |
5 | #include <stdio.h> |
6 | #include <serial_IO.h> |
7 | #endif
|
8 | //--------------------------------------------------------------------
|
9 | unsigned char tick1,tick2,msec,seconds,minutes,hours,RELOAD_T0; |
10 | //--------------------------------------------------------------------
|
11 | // Function: Timer 0 Initialisierung
|
12 | |
13 | void Timer0_Init (void) { |
14 | TMOD |= 0x02; // Timer 0 Mode 2, 8 Bit Autoreload |
15 | RELOAD_T0 = 192; |
16 | TL0 = RELOAD_T0; |
17 | TH0 = RELOAD_T0; // TL0 reload value; |
18 | IP = 0x00; // Interruptprioritaet |
19 | ET0 = 1; // Timer 0 Interrupt EIN |
20 | }
|
21 | |
22 | //--------------------------------------------------------------------
|
23 | // Function: Timer 0 Interrupt
|
24 | |
25 | void Timer0_ISR (void) interrupt TF0_VECTOR using 1 { |
26 | tick1++; |
27 | if (tick1 == 64){ |
28 | tick1 = 0; |
29 | tick2++; |
30 | if (tick2 == 12) { |
31 | tick2 = 0; |
32 | msec++; |
33 | if (msec == 100) { |
34 | msec = 0; |
35 | seconds++; |
36 | LED_YE = !LED_YE; |
37 | BIT2F = 1; |
38 | if (seconds == 60) { |
39 | seconds = 0; |
40 | minutes++; |
41 | if (minutes == 60) { |
42 | minutes = 0; |
43 | hours++; |
44 | if (hours == 24) { |
45 | hours = 0; |
46 | }
|
47 | }
|
48 | }
|
49 | }
|
50 | }
|
51 | }
|
52 | }
|
53 | |
54 | //--------------------------------------------------------------------
|
55 | // Function: Main
|
56 | |
57 | void main (void) { |
58 | unsigned char z; |
59 | #if (x2 == 1)
|
60 | CLKREG = 0x01; // x2 mode |
61 | #else
|
62 | CLKREG = 0x00; |
63 | #endif
|
64 | Beeper = ON; |
65 | Timer0_Init(); |
66 | EA = 1; // Alle Interrupts EIN |
67 | TR0 = 1; // Start Timer 0 |
68 | |
69 | inituart((unsigned int)(256-((XtalFreq/Baudrate)*(x2+1)/192))); // Timer1 |
70 | printf_fast(__DATE__);putchar(','); |
71 | printf_fast(__TIME__); |
72 | printf_fast("\r\n>"); |
73 | |
74 | BIT2F = 0; |
75 | LED_GN = ON; |
76 | while(1) { |
77 | if (BIT2F) { |
78 | LED_GN = !LED_GN; |
79 | printf_fast("%2d:%2d:%2d\r\n",hours,minutes,seconds); |
80 | BIT2F = 0; |
81 | }
|
82 | if (SIO_RI) { |
83 | switch (SIO_SBUF) { |
84 | case 's' : SIO_RI = 0; |
85 | printf_fast("\r\nUhr stellen (00:00:00):\r\n>"); |
86 | TR0 = 0; // STOP Timer 0 |
87 | z = getchar(); putchar(z); hours = (z - 48)*10; |
88 | z = getchar(); putchar(z); hours = hours + (z -48); |
89 | putchar(':'); |
90 | z = getchar(); putchar(z); minutes = (z - 48)*10; |
91 | z = getchar(); putchar(z); minutes = minutes + (z -48); |
92 | putchar(':'); |
93 | z = getchar(); putchar(z); seconds = (z - 48)*10; |
94 | z = getchar(); putchar(z); seconds = seconds + (z -48); |
95 | printf_fast(" -> [ENTER]\r\n"); |
96 | tick1 = tick2 = msec = 0; |
97 | TL0 = RELOAD_T0; // TL0 reload value; |
98 | z = getchar(); |
99 | TR0 = 1; |
100 | break; |
101 | default : break; |
102 | }
|
103 | // SIO_RI = 0;
|
104 | }
|
105 | }
|
106 | }
|
107 | |
108 | //--------------------------------------------------------------------
|
109 | //--------------------------------------------------------------------
|
So siehts mit SDCC aus ... Rabis
Moin Wie es aussieht hast du die Behfelslaufzeiten nicht berücksichtig was bei Timer- und Interrupptfunktionen zu verschiebungen von 1 bis 4 taketen je durchlauf führen kann. Ich emfehle dir die timer0 Zeitsequenz bis in den millisekunden bereich in Assembler zu programieren dann hast du einen genauen wert von dem du aus alle weiteren abläufe steuern kannst mfg
@willi67 Hmm, mit Timer0 im Modus2 und Autoreload(!) sollte es m.E. keine Verschiebung geben, es sei denn die Interruptroutine wäre zu lang - in assmbler sieht das bei SDCC so aus:
1 | 615 ; ----------------------------------------- |
2 | 616 ; function Timer0_ISR |
3 | 617 ; ----------------------------------------- |
4 | 00D8 618 _Timer0_ISR: |
5 | 000A 619 ar2 = 0x0a |
6 | 000B 620 ar3 = 0x0b |
7 | 000C 621 ar4 = 0x0c |
8 | 000D 622 ar5 = 0x0d |
9 | 000E 623 ar6 = 0x0e |
10 | 000F 624 ar7 = 0x0f |
11 | 0008 625 ar0 = 0x08 |
12 | 0009 626 ar1 = 0x09 |
13 | 00D8 C0 E0 627 push acc |
14 | 00DA C0 D0 628 push psw |
15 | 00DC 75 D0 08 629 mov psw,#0x08 |
16 | 630 ; ./main.c:27: tick1++; |
17 | 00DF 05 10 631 inc _tick1 |
18 | 632 ; ./main.c:28: if (tick1 == 64){ |
19 | 00E1 74 40 633 mov a,#0x40 |
20 | 00E3 B5 10 39 634 cjne a,_tick1,00113$ |
21 | 635 ; ./main.c:29: tick1 = 0; |
22 | 00E6 75 10 00 636 mov _tick1,#0x00 |
23 | 637 ; ./main.c:30: tick2++; |
24 | 00E9 05 11 638 inc _tick2 |
25 | 639 ; ./main.c:31: if (tick2 == 12) { |
26 | 00EB 74 0C 640 mov a,#0x0C |
27 | 00ED B5 11 2F 641 cjne a,_tick2,00113$ |
28 | 642 ; ./main.c:32: tick2 = 0; |
29 | 00F0 75 11 00 643 mov _tick2,#0x00 |
30 | 644 ; ./main.c:33: msec++; |
31 | 00F3 05 12 645 inc _msec |
32 | 646 ; ./main.c:34: if (msec == 100) { |
33 | 00F5 74 64 647 mov a,#0x64 |
34 | 00F7 B5 12 25 648 cjne a,_msec,00113$ |
35 | 649 ; ./main.c:35: msec = 0; |
36 | 00FA 75 12 00 650 mov _msec,#0x00 |
37 | 651 ; ./main.c:36: seconds++; |
38 | 00FD 05 13 652 inc _seconds |
39 | 653 ; ./main.c:37: LED_YE = !LED_YE; |
40 | 00FF B2 81 654 cpl _P0_1 |
41 | 655 ; ./main.c:38: BIT2F = 1; |
42 | 0101 D2 2F 656 setb _BIT2F |
43 | 657 ; ./main.c:39: if (seconds == 60) { |
44 | 0103 74 3C 658 mov a,#0x3C |
45 | 0105 B5 13 17 659 cjne a,_seconds,00113$ |
46 | 660 ; ./main.c:40: seconds = 0; |
47 | 0108 75 13 00 661 mov _seconds,#0x00 |
48 | 662 ; ./main.c:41: minutes++; |
49 | 010B 05 14 663 inc _minutes |
50 | 664 ; ./main.c:42: if (minutes == 60) { |
51 | 010D 74 3C 665 mov a,#0x3C |
52 | 010F B5 14 0D 666 cjne a,_minutes,00113$ |
53 | 667 ; ./main.c:43: minutes = 0; |
54 | 0112 75 14 00 668 mov _minutes,#0x00 |
55 | 669 ; ./main.c:44: hours++; |
56 | 0115 05 15 670 inc _hours |
57 | 671 ; ./main.c:45: if (hours == 24) { |
58 | 0117 74 18 672 mov a,#0x18 |
59 | 0119 B5 15 03 673 cjne a,_hours,00113$ |
60 | 674 ; ./main.c:46: hours = 0; |
61 | 011C 75 15 00 675 mov _hours,#0x00 |
62 | 011F 676 00113$: |
63 | 011F D0 D0 677 pop psw |
64 | 0121 D0 E0 678 pop acc |
65 | 0123 32 679 reti |
Wenn ich das in ASM programmiere bin ich nicht besser
R. B. schrieb: > RELOAD_T0 = 192; Das ergibt dann aber 256 - 192 = 64 Zyklen Interruptrate. RELOAD_T0 = -192; Peter
@Peter Danke! RELOAD_T0 = 256-192; So mags SDCC und die Interruptroutine läßt sich noch verkürzen:
1 | //--------------------------------------------------------------------
|
2 | // Function: Timer 0 Interrupt
|
3 | |
4 | void Timer0_ISR (void) interrupt TF0_VECTOR using 1 { |
5 | tick1++; |
6 | if (tick1 == 192){ |
7 | tick1 = 0; |
8 | msec++; |
9 | if (msec == 100) { |
10 | msec = 0; |
11 | seconds++; |
12 | LED_YE = !LED_YE; |
13 | BIT2F = 1; |
14 | if (seconds == 60) { |
15 | seconds = 0; |
16 | minutes++; |
17 | if (minutes == 60) { |
18 | minutes = 0; |
19 | hours++; |
20 | if (hours == 24) { |
21 | hours = 0; |
22 | }
|
23 | }
|
24 | }
|
25 | }
|
26 | }
|
27 | }
|
Problem gelöst, herrlicher Wochenendausgang! Dank an alle! Rabis
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.