mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 8051:Timer - Reload und Teilerfaktoren


Autor: R. B. (rabis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeig mal den dazugehörigen Code. Ansonsten können wir auch nur raten, 
wodran das Problem liegt. ;)

Autor: R. B. (rabis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, gerne

main.h:
//--------------------------------------------------------------------
// Defines

#ifndef __MAIN
  #define __MAIN
#endif

#define x2                     1           // 0 or 1 , x2 mode
#define XtalFreq               22118400
#define Baudrate               38400       // 19200
//#define TH0_RELOAD             0x0
//#define TL0_RELOAD             0x0
#define ON        0
#define OFF       1
#define LED_GN   P0_0
#define LED_YE   P0_1
#define LED_RD   P0_2
#define Beeper   P0_3

//--------------------------------------------------------------------

__sbit __at (0x2F) BIT2F;

//--------------------------------------------------------------------

main.c
//--------------------------------------------------------------------
#include "./main.h"
#ifdef __MAIN
 #include <at89s8253.h>
 #include <stdio.h>            
 #include <serial_IO.h>
#endif 
//--------------------------------------------------------------------
unsigned char tick1,tick2,msec,seconds,minutes,hours,RELOAD_T0;
//--------------------------------------------------------------------
// Function: Timer 0 Initialisierung

void Timer0_Init (void) {
  TMOD  |= 0x02;            // Timer 0 Mode 2, 8 Bit Autoreload
  RELOAD_T0 = 192;
  TL0    = RELOAD_T0;
  TH0    = RELOAD_T0;        // TL0 reload value;
  IP     = 0x00;            // Interruptprioritaet  
  ET0    = 1;               // Timer 0 Interrupt EIN 
}

//--------------------------------------------------------------------
// Function: Timer 0 Interrupt

void Timer0_ISR (void) interrupt TF0_VECTOR using 1 {
  tick1++;
  if (tick1 == 64){
     tick1 = 0;
     tick2++;     
     if (tick2 == 12) {
        tick2 = 0;
        msec++;      
        if (msec == 100) {
           msec = 0;
           seconds++;
           LED_YE = !LED_YE; 
           BIT2F = 1;    
           if (seconds == 60) {
              seconds = 0;
              minutes++; 
              if (minutes == 60) {
                 minutes = 0;
                 hours++; 
                 if (hours == 24) {
                    hours = 0;
                 }  
              } 
           } 
        } 
     } 
  }          
}

//--------------------------------------------------------------------
// Function: Main

void main (void) { 
  unsigned char z;
#if (x2 == 1)
  CLKREG = 0x01;          // x2 mode
#else
  CLKREG = 0x00;
#endif 
  Beeper = ON;
  Timer0_Init();
  EA     = 1;             // Alle Interrupts EIN   
  TR0    = 1;             // Start Timer 0  
          
  inituart((unsigned int)(256-((XtalFreq/Baudrate)*(x2+1)/192)));  // Timer1
  printf_fast(__DATE__);putchar(',');
  printf_fast(__TIME__);
  printf_fast("\r\n>");
  
  BIT2F  = 0;
  LED_GN = ON;
  while(1) {
   if (BIT2F) {  
      LED_GN = !LED_GN; 
      printf_fast("%2d:%2d:%2d\r\n",hours,minutes,seconds);
      BIT2F = 0;
   }
   if (SIO_RI) {
    switch (SIO_SBUF) {
      case 's'  :  SIO_RI = 0;
                   printf_fast("\r\nUhr stellen (00:00:00):\r\n>"); 
                   TR0 = 0;   // STOP Timer 0
                   z = getchar(); putchar(z); hours = (z - 48)*10;
                   z = getchar(); putchar(z); hours = hours + (z -48);
                   putchar(':');
                   z = getchar(); putchar(z); minutes = (z - 48)*10;
                   z = getchar(); putchar(z); minutes = minutes + (z -48);
                   putchar(':');
                   z = getchar(); putchar(z); seconds = (z - 48)*10;
                   z = getchar(); putchar(z); seconds = seconds + (z -48);
                   printf_fast(" -> [ENTER]\r\n");
                   tick1  = tick2 = msec = 0;
                   TL0    = RELOAD_T0;        // TL0 reload value;
                   z = getchar();                   
                   TR0 = 1;
                   break; 
      default   :  break; 
    }
    // SIO_RI = 0;              
   }               
  } 
}
  
//--------------------------------------------------------------------
//--------------------------------------------------------------------

So siehts mit SDCC aus ...

Rabis

Autor: Wilhelm S. (willi67)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: R. B. (rabis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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:
                            615 ;  -----------------------------------------
                            616 ;   function Timer0_ISR
                            617 ;  -----------------------------------------
   00D8                     618 _Timer0_ISR:
                    000A    619   ar2 = 0x0a
                    000B    620   ar3 = 0x0b
                    000C    621   ar4 = 0x0c
                    000D    622   ar5 = 0x0d
                    000E    623   ar6 = 0x0e
                    000F    624   ar7 = 0x0f
                    0008    625   ar0 = 0x08
                    0009    626   ar1 = 0x09
   00D8 C0 E0               627   push  acc
   00DA C0 D0               628   push  psw
   00DC 75 D0 08            629   mov  psw,#0x08
                            630 ;  ./main.c:27: tick1++;
   00DF 05 10               631   inc  _tick1
                            632 ;  ./main.c:28: if (tick1 == 64){
   00E1 74 40               633   mov  a,#0x40
   00E3 B5 10 39            634   cjne  a,_tick1,00113$
                            635 ;  ./main.c:29: tick1 = 0;
   00E6 75 10 00            636   mov  _tick1,#0x00
                            637 ;  ./main.c:30: tick2++;     
   00E9 05 11               638   inc  _tick2
                            639 ;  ./main.c:31: if (tick2 == 12) {
   00EB 74 0C               640   mov  a,#0x0C
   00ED B5 11 2F            641   cjne  a,_tick2,00113$
                            642 ;  ./main.c:32: tick2 = 0;
   00F0 75 11 00            643   mov  _tick2,#0x00
                            644 ;  ./main.c:33: msec++;      
   00F3 05 12               645   inc  _msec
                            646 ;  ./main.c:34: if (msec == 100) {
   00F5 74 64               647   mov  a,#0x64
   00F7 B5 12 25            648   cjne  a,_msec,00113$
                            649 ;  ./main.c:35: msec = 0;
   00FA 75 12 00            650   mov  _msec,#0x00
                            651 ;  ./main.c:36: seconds++;
   00FD 05 13               652   inc  _seconds
                            653 ;  ./main.c:37: LED_YE = !LED_YE; 
   00FF B2 81               654   cpl  _P0_1
                            655 ;  ./main.c:38: BIT2F = 1;    
   0101 D2 2F               656   setb  _BIT2F
                            657 ;  ./main.c:39: if (seconds == 60) {
   0103 74 3C               658   mov  a,#0x3C
   0105 B5 13 17            659   cjne  a,_seconds,00113$
                            660 ;  ./main.c:40: seconds = 0;
   0108 75 13 00            661   mov  _seconds,#0x00
                            662 ;  ./main.c:41: minutes++; 
   010B 05 14               663   inc  _minutes
                            664 ;  ./main.c:42: if (minutes == 60) {
   010D 74 3C               665   mov  a,#0x3C
   010F B5 14 0D            666   cjne  a,_minutes,00113$
                            667 ;  ./main.c:43: minutes = 0;
   0112 75 14 00            668   mov  _minutes,#0x00
                            669 ;  ./main.c:44: hours++; 
   0115 05 15               670   inc  _hours
                            671 ;  ./main.c:45: if (hours == 24) {
   0117 74 18               672   mov  a,#0x18
   0119 B5 15 03            673   cjne  a,_hours,00113$
                            674 ;  ./main.c:46: hours = 0;
   011C 75 15 00            675   mov  _hours,#0x00
   011F                     676 00113$:
   011F D0 D0               677   pop  psw
   0121 D0 E0               678   pop  acc
   0123 32                  679   reti
Wenn ich das in ASM programmiere bin ich nicht besser

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
R. B. schrieb:
> RELOAD_T0 = 192;

Das ergibt dann aber 256 - 192 = 64 Zyklen Interruptrate.

RELOAD_T0 = -192;


Peter

Autor: R. B. (rabis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter
Danke!
RELOAD_T0 = 256-192;
So mags SDCC und die Interruptroutine läßt sich noch verkürzen:
//--------------------------------------------------------------------
// Function: Timer 0 Interrupt

void Timer0_ISR (void) interrupt TF0_VECTOR using 1 {
  tick1++;
  if (tick1 == 192){
     tick1 = 0;
     msec++;         
        if (msec == 100) {
           msec = 0;
           seconds++;
           LED_YE = !LED_YE; 
           BIT2F = 1;    
           if (seconds == 60) {
              seconds = 0;
              minutes++; 
              if (minutes == 60) {
                 minutes = 0;
                 hours++; 
                 if (hours == 24) {
                    hours = 0;
                 }  
              } 
           } 
        } 
  }          
}

Problem gelöst, herrlicher Wochenendausgang!
Dank an alle!
Rabis

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.