- LiFePO4 Speicher Test         
Ergebnis 1 bis 6 von 6

Thema: Delay mittels Timer

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270

    Delay mittels Timer

    Anzeige

    Praxistest und DIY Projekte
    Hallo,
    ich versuche in folgendem Code eine Delay-funktion zu realisieren.
    Leider funktioniert es nicht wirklich, kann vllt. von euch jemand erkennen, warum nicht im Sekundentakt gesendet wird, sondern viel schneller?
    Code:
    #include <avr/io.h> 
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    volatile uint8_t count;
    
    void init_usart(void) 
    { 
     UBRRL |= 0b01100111; 
     UCSRB = (1<<TXEN) | (1<<RXEN); 
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 
    } 
    
    void send_char(unsigned char s)
    {
     while (!(UCSRA & (1<<UDRE)));
     UDR = s;
    }
    
    void send_string(char *s)
    {
     while(*s != '\0')
      {
       send_char(*s);
       s++;
      }
    }
    
    void waitms(uint16_t s)
    {
     
     uint16_t i;
     uint8_t j;
     TCCR0 |= (1<<CS01) | (1<<CS00);  //Vorteiler 64
     TIMSK |= (1<<TOIE0);
     
     for(i=0;i<s;i++)
      {
       TCNT0 = 6;                 // Timer auf 6 vorladen, da (16000000/64)^-1 = 0.000004s
      }                           // -> 1ms = 0.000004s*250
      
     TIMSK |= (0<<TOIE0);
    } 
     
    SIGNAL(SIG_OVERFLOW0)
    {
     count++;
     TCNT0 = 6;
    }
     
    int main(void) 
    { 
     sei();
     unsigned int i; 
     char a = "108:158#13#10";
     i = 0; 
     init_usart(); 
     do
      {
       send_string(a);
       waitms(1000); 
      }
      while (i == 0);  
    }
    Gruß
    Spurius

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802

    Re: Delay mittels Timer

    Versuch mal sowas:

    Code:
    #include <avr/io.h> 
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    volatile uint8_t count;
    
    void init_usart(void) 
    { 
     UBRRL |= 0b01100111; 
     UCSRB = (1<<TXEN) | (1<<RXEN); 
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 
    } 
    
    void send_char (unsigned char s)
    {
     while (!(UCSRA & (1<<UDRE)));
     UDR = s;
    }
    
    void send_string (char *s)
    {
     while (*s++)
       send_char(*s);
    }
    
    void init_timer0()
    {
     TCCR0 = (1<<CS01) | (1<<CS00);  //Vorteiler 64
     TIMSK |= (1<<TOIE0);
    }
    
    void waitms (uint16_t s)
    {
     while (s--)
     {
        uint16_t cnt;
    
        cli();
        count = 0;
        TCNT0 = 6;
    
        do 
        {
             cli();
             cnt = count;
             sei();
        }
        while (cnt < 1000);
      }
    } 
     
    SIGNAL (SIG_OVERFLOW0)
    {
     TCNT0 = 6;
     count++;
    }
     
    char a[] = "108:158#13#10";
    
    int main(void) 
    { 
     init_usart(); 
     init_timer0(); 
    
     sei();
    
     while (1)
      {
       send_string (a);
       waitms (1000); 
      }
    }
    Disclaimer: none. Sue me.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hi,
    bei deiner Version wird nur einmal gesendet
    Was ist bei mir denn konkret falsch? Hab ich nen Logikfehler oder eher was C-Spezifisches?

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Sorry, count muss uint16_t sein, nicht uint8_t (zählt bis 1000). Und in der Schleife muss es heissen while(*s) { foo (*s++); }

    Was bei dir konkret inkorrekt ist, ist schwer zu fprmulieren. Es geht eben nicht so. Interrupts hast du inaktiv und setzt in der Schleife nur s mal TCNT0 auf 6. Da müsste noch das Flag aus TIFR abgefrage/gelöscht werden, heisst glaub TOV0 oder so.
    Disclaimer: none. Sue me.

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    11.11.2005
    Beiträge
    321
    nimm diese hier, delay_us_(...) und delay_ms_(...):

    #define delay_us_(us) _delayFourCycles_( ( ( 1*(F_CPU/4000) )*us)/2005)

    static inline void _delayFourCycles_(uint16_t z)
    {
    uint16_t i;

    for (i=0; i<z; i++)
    asm volatile("nop");
    }

    static inline void delay_ms_(uint16_t z)
    {
    uint16_t i;

    for (i=0; i<z; i++)
    delay_us_(999);
    }

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    22.07.2004
    Beiträge
    270
    Hallo,
    danke für eure Hilfe, ich habs jetzt so gelöst:
    Code:
    #include <avr/io.h> 
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    
    volatile uint8_t count = 0; 
    
    void init_usart(void) 
    { 
     UBRRL |= 0b01100111; 
     UCSRB = (1<<TXEN) | (1<<RXEN); 
     UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); 
    } 
    
    void send_char(unsigned char s) 
    { 
     while (!(UCSRA & (1<<UDRE))); 
     UDR = s; 
    } 
    
    void send_string(char *s) 
    { 
     while(*s != '\0') 
      { 
       send_char(*s); 
       s++; 
      } 
    } 
    
    void waitms(uint16_t s) 
    { 
      
     uint16_t i; 
     uint8_t j; 
     TCCR0 |= (1<<CS01) | (1<<CS00);  //Vorteiler 64 
     TIMSK |= (1<<TOIE0); 
      
     for(i=0;i<s;i++) 
      {
       count = 0; 
       TCNT0 = 6;                 // Timer auf 6 vorladen, da (16000000/64)^-1 = 0.000004s 
       while(count != 1)
        {}
        
      }                           // -> 1ms = 0.000004s*250 
      
     TIMSK |= (0<<TOIE0); 
    } 
      
    SIGNAL(SIG_OVERFLOW0) 
    { 
     count = 1; 
    } 
      
    int main(void) 
    { 
     sei(); 
     unsigned int i; 
     char a = "Hallo Welt"; 
     i = 0; 
     init_usart(); 
     do 
      { 
       send_string(a); 
       waitms(1000); 
      } 
      while (i == 0);  
    }
    Gruß
    Spurius

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus