www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik c++ timer programmierhilfe


Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich hab mir einen Timer nachgebaut. Der geht in Sekunden takt. ich 
will ihn aber in ms takt. Was muss ich in der .c verändern damit er das 
tut.
Hier ist die .c
/* Timer von 1-999 Sekunden

 * 3 7-Segment LEDs werden im Multiplexbetrieb angesteuert

#include <inttypes.h>    // uint8_t usw.
//#include <avr/io.h>
#include <avr/interrupt.h>  // Interrupts
#include <avr/signal.h>    // Interruptbehandlungsroutinen SIGNAL
#include <avr/delay.h>    // definiert _delay_ms und _delay_loop_2 
#include <avr/eeprom.h>    // EEPROM Zugriffe

#define delay_us(us)  _delay_loop_2 (((F_CPU/4000)*us)/1000)    // wartet µs
#define EEPROM  __attribute__ ((section (".eeprom")))        // für EEPROM-Zugriffe

/*
  Aufbau 7-Segment

//  Welcher Port an welchem Segement:
#define segm_a PD0
#define segm_b PD1
#define segm_c PD2
#define segm_d PD3
#define segm_e PD4
#define segm_f PD5
#define segm_g PD6

// Welcher Port an welcher Digit:
#define digit1 PC3    // Einer
#define digit2 PC4    // Zehner
#define digit3 PC5    // Hunderter

// An welchem Port sind Taster
#define btn_up    PB0
#define btn_down  PB1
#define btn_start  PB2

// An welchem Port hängt Relais
//#define relais PD7

// Ports definieren
#define port_segment  PORTD
#define port_digit    PORTC
#define port_keys    PORTB
#define dir_segment    DDRD
#define dir_digit    DDRC
#define dir_keys    DDRB
#define pin_keys    PINB

// Definiert, welche Segmente für die einzelnen Zahlenwerte aufleuchten sollen. HIGH-Aktiv
#define sign0 (1 << segm_a) | (1 << segm_b) | (1 << segm_c) | (1 << segm_d) | (1 << segm_e) | (1 << segm_f)
#define sign1 (1 << segm_b) | (1 << segm_c)
#define sign2 (1 << segm_a) | (1 << segm_b) | (1 << segm_g) | (1 << segm_e) | (1 << segm_d)
#define sign3 (1 << segm_a) | (1 << segm_b) | (1 << segm_g) | (1 << segm_c) | (1 << segm_d)
#define sign4 (1 << segm_f) | (1 << segm_g) | (1 << segm_b) | (1 << segm_c)
#define sign5 (1 << segm_a) | (1 << segm_f) | (1 << segm_g) | (1 << segm_c) | (1 << segm_d)
#define sign6 (1 << segm_a) | (1 << segm_f) | (1 << segm_g) | (1 << segm_e) | (1 << segm_d) | (1 << segm_c)
#define sign7 (1 << segm_a) | (1 << segm_b) | (1 << segm_c)
#define sign8 (1 << segm_a) | (1 << segm_b) | (1 << segm_c) | (1 << segm_d) | (1 << segm_e) | (1 << segm_f) | (1 << segm_g)
#define sign9 (1 << segm_a) | (1 << segm_b) | (1 << segm_c) | (1 << segm_d) | (1 << segm_g) | (1 << segm_f)

uint8_t num[] = { sign0, sign1, sign2, sign3, sign4, sign5, sign6, sign7, sign8, sign9 };
uint16_t startwert EEPROM;          // Speicherplatz für letzten Startwert im EEPROM
volatile uint16_t   display_value=0;    // Startwert. 
volatile uint8_t    run=0;          // =0 Counter Stop; =1 Counter läuft
volatile uint8_t    relais=0;        // =0 Relais off, =1 Relais on
volatile uint8_t    key_up=0,        // Puffer für Tastendrücke
          key_down=0,
          key_start=0;

/**
  @brief  Gibt Zahlenwert auf 7 Segment Display aus 
  @param   zahl
  @return  none
*/
void ausgabe (uint16_t zahl)
{
  uint16_t output = zahl;
  uint16_t warten = 500;    // Enable Zeit für einzelnes Segment. Zeit in der LED leuchten
  
  // Hunderter-Dezimalstelle
  if (zahl >= 100)
  {
    port_segment = relais | num[output/100];  // Zahlenwert darstellen zzgl. Zustand für PB7
    port_digit = (1 << digit3);          // 3. Digit HIGH
    delay_us(warten);              // LEDs müssen gewisse Zeit leuchten
    port_digit = 0;                // 3. Digit HIGH
  }
   output = output % 100;
  
  // Zehner-Dezimalstelle
  if (zahl >= 10)
  {
    port_segment = relais | num[output/10];    // Zahlenwert darstellen zzgl. Zustand für PB7
    port_digit = (1 << digit2);          // 2. Digit HIGH
    delay_us(warten);              // LEDs müssen gewisse Zeit leuchten
    port_digit = 0;                // 2. Digit HIGH
  }
   output = output % 10;
  
  // einer Dezimalstelle 
  port_segment = relais | num[output];      // Zahlenwert darstellen zzgl. Zustand für PB7
  port_digit =  (1 << digit1);          // 1. Digit HIGH
  delay_us(warten);                // LEDs müssen gewisse Zeit leuchten
  port_digit =  0;                // 1. Digit HIGH

  sei();              // Interrupts zulassen
}

/**
  @brief  Interruptbehandlung für Timer zum Displayrefresh
  @param   none
  @return  none
*/
SIGNAL (SIG_OVERFLOW0)
{
  cli();            // Interrupts nicht zulassen
  ausgabe (display_value);  // Zahl darstellen
}

/**
  @brief  Interruptbehandlung für Timer zur Tastenabfrage. 
      Für jede Taste erxistiert eine Variable, die inkrementiert wird, wenn Interrupt ausgelöst wird und Taste gedrückt ist
      Sind x Tastenimpulse zusammen, wird im Hauptprogramm die Taste als gedrückt angesehen
  @param   none
  @return  none
*/
SIGNAL (SIG_OVERFLOW2)
{
  cli();    // Interrupts nicht zulassen
  
  if (pin_keys & (1 << btn_up))    // Up-Taste gedrückt
    key_up++;
    
  if (pin_keys & (1 << btn_down))    // Down-Taste gedrückt
    key_down++;
    
  if (pin_keys & (1 << btn_start))  // Start-Taste gedrückt
    key_start++;
  
  sei();    // Interrupts zulassen
}

/**
  @brief  Interruptbehandlung für Timer für Sekundentakt bei gestartetem Counter
      Wird jede Sekunde einmal ausgelöst und dekrementiert den Zähler
  @param   none
  @return  none
*/
SIGNAL (SIG_OUTPUT_COMPARE1A)
{
  cli();              // Interrupts nicht zulassen
  TCNT1H=0;            // Timerstand zurücksetzen
  TCNT1L=0;
  
  display_value -= run;
}

int main(void)
{

  dir_digit = (1 << digit1) | (1 << digit2) | (1 << digit3);      // Ausgänge, für Digits
  dir_segment = 0xFF;                          // alles Ausgänge, für Segmente 
  dir_keys &= ~(1 << btn_up) & ~(1 << btn_down) & ~(1 << btn_start);  // Eingänge für Tasten

  // Timer für Displayrefresh
//  TCCR0 |= (1<<CS01);          //8-Bit Timer, Timer clock = system clock/8
  TCCR0 |= (1<<CS01) | (1<<CS00);    //8-Bit Timer, Timer clock = system clock/64
//  TCCR0 |= (1<<CS02);          //8-Bit Timer, Timer clock = system clock/256
//  TCCR0 |= (1<<CS02) | (1<<CS00);    //8-Bit Timer, Timer clock = system clock/1024
  TIFR |= (1<<TOV0);           //Clear TOV0 Timer/Counter Overflow Flag. clear pending interrupts
  TIMSK |= (1<<TOIE0);         //Enable Timer0 Overflow Interrupt

  // Timer für Tastenabfrage
  TCCR2 |= (1<<CS22) | (1<<CS20);    //8-Bit Timer, Timer clock = system clock/1024
  TIFR |= (1<<TOV2);           //Clear TOV2 Timer/Counter Overflow Flag. clear pending interrupts
  TIMSK |= (1<<TOIE2);         //Enable Timer2 Overflow Interrupt
  
  // Timer für Sekundentakt
  OCR1AH = 0x1E;            // 16Bit Timer Takt= 8MHz => 8.000.000/1024 = 7812,5 => 7,8125 Zählerschritte pro ms
  OCR1AL = 0x83;            // Vergleichswert laden: 1 Sekunde
  TIMSK |= (1<<OCIE1A);         // Interrupt wenn Timer Vergleichswert erreicht

  sei();              // Interrupts zulassen

  while (1)
  {
    if (key_up >= 50)        // Up-Taste gedrückt
    {
      display_value++;      // Wert +1
      if (display_value > 999)  // Wenn Überlauf => Wert=0
        display_value = 1;
      key_up = 0;          // Tastencounter leeren
    }
    if (key_down >= 50)      // Down-Taste gedrückt
    {
      if (display_value <= 1)    // Wenn Unterlauf => Wert=999
        display_value = 1000;
      display_value--;      // Wert -1
      key_down = 0;        // Tastencounter leeren
    }

    if (key_start >= 100)      // Start-Taste gedrückt
    {
      key_start = 0;        // Tastencounter leeren
      if (display_value == 0)    // wenn angezeigter Wert = 0 und Start gedrückt => ermittler zuletzt verwendeten Startwert und setze diesen
      {
        display_value = eeprom_read_word(&startwert);
      }
      else
      {
        run ^= 1;          // Wert XOR 1;  => Start/Stop
        if (run)          // Wenn Counter gestartet wird
        {
          if (display_value != eeprom_read_word(&startwert))    // wenn Start gedrückt und aktueller Startwert != letzter Startwert
            eeprom_write_word(&startwert, display_value);    // dann speichere neuen Startwert
        
          TCNT1H=0;            // Timerstand zurücksetzen, damit ab jetzt eine Sekunde zählt
          TCNT1L=0;
          TCCR1B = (1<<CS10)|(1<<CS12);  // Timer mit Div 1024 starten
          relais = 0x80;          // zusätzlich Relais HIGH 
        }
        else            // Counter angehalten
        {
          TCCR1B = 0;        // Timer Stop
          relais = 0x0;      // Relais LOW
        }
      }
    }

    if (display_value == 0)      // Timer abgelaufen
    {
      run = 0;          // Stop
      relais = 0x0;        // Relais LOW
    }
  }
}

Kann mir jemand Helfen ??????????

Autor: Uwe ... (uwegw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Zeilen
  // Timer für Sekundentakt
  OCR1AH = 0x1E;
  OCR1AL = 0x83;

lassen sich durch
OCR1A= 0x1E83;
ersetzen. Besser noch durch dezimal
OCR1A= 7811;
Hier wird festgelegt, wie weit der Zähler läuft. 7811 entspricht einer 
Sekunde, also änderst du den Wert auf 8, um etwa eine Milisekunde zu 
bekommen. Soll es genauer werden, sind noch weitere Änderungen nötig.

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke werde es gleich ausprobieren

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.