Forum: Mikrocontroller und Digitale Elektronik ATmega644 16bit Timer Compare Interrupt


von Nick O. (lpt)


Lesenswert?

Hallo zusammen ich brauche mal etwas Hilfe.

Ich will einen Timer Programmieren der von 50ms bis zu 10min einstellbar 
sein soll.

Das Problem ist das mein Interrupt sich in der Simulation aufhängt.
Er durchläuft ein paar mal hintereinander die ISR und startet dann das 
gesamte Programm  neu. Das soll heißen er beendet eine Endlosschleife 
und beginnt mit der Initaliesierung des Programms. Seinen Compare Wert 
erreicht er in der Simulation aber nie.

In Echt macht sich der Fehler etwas anders bemerkbar.
Der Controller wird beim erreichen des Eingestellten Timerwert 
zurücksetzt (Reset). Das soll er aber eigentlich nicht.

Das Beispielprogramm womit ich im Augenblick experimentiere soll 
eigentlich nur 1x Blinken wenn Aufnahme gesetzt ist.
1
//****************************************************************************************************
2
//*****                                               *****
3
//*****                    Interrupt                       *****
4
//*****                                               *****
5
//****************************************************************************************************
6
//                 ***Wenn Timer Interrupt auslöst dann ausführen***
7
//                 -------------------------------------------------
8
  ISR (TIMER1_COMPA__vect)                // Interrupt Vektorvariable vom Timer1 Compare
9
    {
10
      Time = Time + 1;              // Time um 1 erhöhen
11
12
      if (Time == Durchlauf)            // Time = die Anzahl wie oft der Interrupt 
13
        {                    // Durchlaufen werden soll
14
/*
15
      Aufnahme = 0;
16
      Zustand = 0x07;      // Zustand = Aufnahme
17
      PortD_OUT();      // LED setzen
18
      _delay_ms(1000);      // Warten damit LED Zeit hat zum aufleuchten
19
      Zustand = 0x00;      // Zustand = Aufnahme
20
      PortD_OUT();      // LED setzen
21
*/
22
23
          Aufnahme = 1;            // Merker für Aufnahmen setzen
24
      //    Time    = 0;            // Time zurücksetzen
25
        }
26
    }
27
28
//****************************************************************************************************
29
//*****                                               *****
30
//*****                    Hauptprogramm                     *****
31
//*****                                               *****
32
//****************************************************************************************************
33
int main (void) 
34
  {
35
    DDRA = 0xBA;                  // PortA PIN 0, 2, 6 als Eingang
36
                            // PortA alle anderen Pins als Ausgang 
37
    
38
    DDRB = 0xFF;                  // PortB alle Pins als Ausgang
39
40
    DDRC = 0xFF;                  // PortC alle Pins als Ausgang
41
42
//----------------------------------------------------------------------------------------------------
43
//                 ***Init Funktionen***
44
//                ---------------------
45
    vdip1_init();                    // VNC1L Initialisierung
46
    AD_Wandler_init();                // AD-Wandler Initialisierung
47
//    Timer_init;                    // Timer Interrupt wird später Initialisiert
48
49
....
50
...
51
..
52
.
53
54
55
//                 ***init Interrupt für Timer***
56
//                 ------------------------------  
57
  cli();                        //alle Interrupts sperren um 16Bit Register zu beschreiben
58
  
59
  TCCR1A = 0x00;                    //keine PWM und keine Interrupt Ausgabe
60
  TCCR1B = Vorteiler;                  //Compare Modus & Vorteile setzen
61
//                Vergleichs- Regiser setzen
62
  OCR1AH = Byte1;                    // 16 Bit Compare Register A obere  8 Bits 
63
  OCR1AL = Byte0;                    // 16 Bit Compare Register A untere 8 Bits
64
  
65
  sei();                        // alle Interrups wieder freigeben 
66
67
  TIMSK1 |= (1<< OCIE1A);               // Compare Interrupt aktivieren//*/
68
69
// ****************************************************************************************************
70
// *****            Hauptschleife zum messen der Signale                   *****
71
// ****************************************************************************************************
72
73
74
75
while (1)
76
{
77
  if (Aufnahme == 1)                  // Wenn Datenlogger aufnehmen soll
78
    {
79
      cli();                        //alle Interrupts sperren um 16Bit Register zu beschreiben
80
81
      Aufnahme = 0;
82
83
    //  Zustand = 0x07;      // Zustand = Aufnahme
84
      PORTD = 0xFF;
85
    //  PortD_OUT();      // LED setzen
86
      _delay_ms(300);      // Warten damit LED Zeit hat zum aufleuchten
87
88
    //  Zustand = 0x00;      // Zustand = Aufnahme
89
      PORTD = 0x00;
90
    //  PortD_OUT();      // LED setzen
91
  
92
      sei();                        // alle Interrups wieder freigeben 
93
    }
94
}
95
//                ***Aktiv ENDE***
96
//====================================================================================================
97
//    abfahren ();                    // Stop Taster auswerten
98
99
  return 0;
100
  }

Das merkwürdige ist das es genau so vor ein paar Tagen noch funktioniert 
hat.
Ich hab bloß noch mal denn Controller wechseln müssen und etwas an ein 
paar Funktonen geändert und jetzt klappt es nicht mehr.

Ich benutze einen ATmega644 mit 12Mhz.

Es wäre echt nett wenn mir jemand helfen kann.

mfg
LPT

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Der Codefetzen ist nicht vollständig. Es fehlt als wichtige Information, 
wie die Variable Aufnahme definiert ist. Stichwort volatile und 
atomar

Die cli/sei Klammer in main() um das _delay_ms(300) würde ich kritisch 
hinterfragen. Einen Timer will man normalerweise durchlaufen lassen und 
nicht 300ms lang ausbremsen.

Die 1s Pause in der ISR ist derzeit zwar auskommentiert, lässt aber 
übles ahnen für den Nicht-Testcode. Mit Interrupts/Timern programmiert 
man anders: nebenläufig statt aufeinanderfolgend. Wenn du meinst in der 
ISR einen Delay zu brauchen, ist was faul und die Programmlogik muss 
überarbeitet werden.

Es würde IMHO helfen, wenn du besser in eigenen Worten beschreibst, was 
du machen willst, bevor du ausformulierten Code schreibst.

von Nick O. (lpt)


Lesenswert?

Sorry war gestern Abend etwas spät als ich das geschrieben habe.

Mein Programm soll ohne Interrupfunterbrechung 17 Werte aufnehmen.

Danach wird der Timerinterrupt aktiviert. Der Interrupt aktiviert den 
nächsten Aufnahmezyklus. In der Pausen Zeit wird der USB-Stick mit denn 
Messdaten beschrieben

Dass das dem Interrupt Betreib etwas wiederspricht ist mir auch klar.

Was das auskommentiert in der ISR angeht, dass gehört dort eigentlich 
nicht hin.
Und war nur dafür da, um zu sehen ob der Interrupt überhaupt 
abgearbeitet wird. Sprich bei Interrupt LED aufblinken lassen. Das hätte 
ich wieder löschen sollen bevor ich es Online setze.

Die Variable Aufnahme ist Global angelegt und zumindest in der 
Simulation funktioniert es.

Allerdings ist mir nicht ganz klar ob der Abschnitt
"***init Interrupt für Timer***"

vor der main stehen muss oder ob ich sie auch als Funktion aufrufen 
kann.

Weil in main wollte ich eigentlich erst festlegen welche Einstellung ich 
vornehmen will.

1
  switch (Timerwert)
2
    {
3
  // Zeiteinstellung = 1  Pausen-Zeit = 10ms
4
      case 1:  Durchlauf = 1;            // 1 x 10ms
5
          Vorteiler = 0x0A;          // Vorteiler = 8
6
          Byte1     = 0x00;  //0x07;          // Vergleichswert = 1901
7
          Byte0     = 0x9F;  //0x6D;
8
          break;
9
...
10
..
11
.
12
      // Zeiteinstellung = 8  Pausen-Zeit = 10min
13
      case 8:  Durchlauf = 120;          // 120 x 5s          
14
          Vorteiler = 0x0D;          // Vorteiler = 1024
15
          Byte1     = 0x1C;          // Vergleichswert = 7327
16
          Byte0     = 0x9F;
17
          break;

von Karl H. (kbuchegg)


Lesenswert?

ALso:
Mit den Code Fetzen kann man immer noch nichts anfangen.
Bei solchen Problem ist es nicht ungewöhnlich, dass das eigentliche 
Problem genau in den Teilen sitzt, die du nicht zeigst.

Ein 'Selbst-Reset' kann zb auf einen zwar freigegebenen Interrupt 
hindeuten, für den es aber keine ISR gibt.
Nur: Wie soll das jemand überprüfen, wenn du nicht den ganzen Code 
zeigst?

von Nick O. (lpt)


Lesenswert?

Das ganze Programm sind etwa 1500 Zeilen und das meiste ist dafür 
verantwortlich denn USB-Stick zu beschreiben.

Aber ich stelle mal denn ganzen Code von der Interrupt Test Datei 
online.
Da ist der Original Text stark reduziert und trotzdem sind noch eine 
Menge Variabelenleichen drin. Aber das Programm ist einfach zu groß um 
das jemandem zuzumuten.

Aber vielleicht kann ja jemand damit etwas anfangen.
1
//****************************************************************************************************
2
// Initialiesierung
3
#define F_CPU 1000000UL                  // Taktrate (12MHz) festlegen
4
#include <avr/io.h>                       // Datei für Ein und Ausgänge  
5
#include <stdlib.h>                    // Standart LIB
6
#include <util/delay.h>                      // Ersetzt durch delay.c
7
//#include <stdint.h>                      // Für ADWandler aber damals schon auskommentiert
8
#include <string.h>                       // Stingfunktionen
9
#include <stdio.h>                        // Standardfunktionen
10
#include <avr/interrupt.h>                // Datei für Interrupt
11
12
//#include "delay.c"                         // Pausen-Funktionen
13
14
//****************************************************************************************************
15
// Definebereich der Ein- und Ausgabe Port's
16
17
//                 ***Definebereich der Multipleyer Freigaben***
18
//                 ---------------------------------------------
19
#define MUX_Digi_U    PORTC = 0x00                // MUX auf Digi Spannungsaufnahme setzen
20
#define MUX_Schalter1  PORTC = (1<<PIN6)              // MUX auf "Schalter1 abfrage"  setzen
21
#define MUX_LED      PORTC = (1<<PIN6) | (1<<PIN5)        // MUX auf "LED setzen" setzen
22
#define MUX_Schalter2  PORTC = (1<<PIN6) | (1<<PIN5) | (1<<PIN4)  // MUX auf "Schalter2 abfragen" setzen
23
24
25
//----------------------------------------------------------------------------------------------------
26
//                 ***Definebereich I/O PORT für VDIP1 Komunikation***
27
//                ---------------------------------------------------
28
#define S_RE_VNC  PORTA |=  (1<<PIN3)                // VDIP1 Reset setzen
29
#define R_RE_VNC  PORTA &= ~(1<<PIN3)                // VDIP1 Reset zurücksetzen
30
31
#define S_SCLK     PORTA |=  (1<<PIN4)                // VDIP1 Clock Setzen
32
#define R_SCLK    PORTA &= ~(1<<PIN4)                // VDIP1 Clock Rücksetzen
33
34
#define S_SDI    PORTA |=  (1<<PIN5)                // VDIP1 Seriel-Daten-In Setzen
35
#define R_SDI    PORTA &= ~(1<<PIN5)                // VDIP1 Seriel-Daten-In Rücksetzen
36
37
// SDO_VNC      PORTA     (    PIN6)                // VDIP1 Seriel-Daten-Out
38
                                  // wird in der Funktion 
39
                                  // SDO_VNC(void) realiesiert
40
41
#define S_CS_VNC  PORTA |=  (1<<PIN7)                // VDIP1 Freigeben
42
#define R_CS_VNC  PORTA &= ~(1<<PIN7)                // VDIP1 Sperren
43
44
//****************************************************************************************************
45
//*****                                               *****
46
//*****                  Variablenbereich                     *****
47
//*****                                               *****
48
//****************************************************************************************************
49
//                ***Variablen für main***
50
//                ------------------------
51
char Aufnahme = 0;                    // Merker für die Aufnahme (wird vom Timer gesetzt)
52
char Aktiv    = 0;                    // Merker für Aktiv 
53
          //char Ende    = 0;          // Merker für das Abfahren des Gerätes
54
char Stoerung = 0;
55
char x=1;  //***Wieder löschen
56
//             ***Adressierung für Unterfunktion PortD_IN***
57
//            ---------------------------------------------
58
char Digi_U     = 0;                    // Adressenzuweisung für die Funktion PortD_IN
59
char Schalter1 = 1;                    // Adressenzuweisung für die Funktion PortD_IN
60
char Schalter2 = 2;                    // Adressenzuweisung für die Funktion PortD_IN
61
62
//----------------------------------------------------------------------------------------------------
63
//                 ***Variablen für Schalter***
64
//                ----------------------------
65
unsigned char n_Stromwerte;                // Anzahl der zu messenden Ströme
66
unsigned char Strom_Kanal;                // Zur Zeit gemessener Stormkanal
67
unsigned char n_Spannungswerte;              // Anzahl der zu messenden Spannungen
68
unsigned char Spannungs_Kanal;              // Zur Zeit gemessener Spannungskanal
69
unsigned char Zustand;                  // zur ansteuerung der LED's
70
unsigned char Timerwert;                // für Timereinstellung
71
unsigned char Wert = 0;                  // Einlesewert
72
73
//----------------------------------------------------------------------------------------------------
74
//                ***Variablen für Timer***
75
//                -------------------------
76
unsigned char Timerwert;                // Abtastzeit
77
unsigned char Timer  = 0;                // Variablen für Timer
78
unsigned int  Durchlauf;                // Variablen für Timer Wie Timer durchlaufzähler
79
unsigned int  Time;                    // Zähler für die Anzahl der Timerdurchläufe
80
unsigned char Vorteiler;                 // Vorteiler für Interrupt
81
unsigned char Byte1;                   // Vergleichswert für Timerinterrupt (höhes Byte)
82
unsigned char Byte0;                  // Vergleichswert für Timerinterrupt (nidriges Byte)
83
84
//----------------------------------------------------------------------------------------------------
85
//                ***Variablen für VDIP1***
86
//                -------------------------
87
char Daten_Typ0 = 0;                  // Daten  Byte lesen
88
char Daten_Typ1 = 1;                  // System Byte lesen
89
90
char NEU    = 0;                  // Neue Text Datei erzeugen
91
char ALT    = 1;                  // Alte Text Datei erweitern
92
93
char vdip1_fehl     = 1;                  // Variable für Prüfanweisung Fehler Chack
94
char vdip1_ok     = 2;                  // Variable für Prüfanweisung OK   Chack
95
char vdip1_Echo    = 3;                  // Variable für Prüfanweisung Echo   Chack
96
char vdip1_Promt   = 4;      //????          // Variable für Prüfanweisung Promtzeichen Chack
97
//                ***Wiederhohlversuche***
98
unsigned int durchlaufrate = 50;            // max Anzahl der Zugriffversuche auf das VDIP1
99
unsigned int R_W_Versuche  =500;            // max Anzahl der R/W Versuche von einem Byte
100
unsigned int Kommversuche  =  5;            // max Anzahl an Kommunikationsversuchen je Zeichen
101
unsigned int Sendeversuche = 30;            // max Anzahl der Echo Versuche
102
                            // bzw der Versuch Datei anlegen oder zu erweitern
103
//----------------------------------------------------------------------------------------------------
104
//               ***Variablen für AD_Wandlung***
105
//              -------------------------------
106
unsigned int n = 0;                    // n ist für die Ablage in Messwerte notwendig
107
char Adresse;                      // Adresse für Strom- oder Spannungs- Kanal
108
char Geschwindigkeit = 0x87;              // Wandlergeschwindigkeit
109
//----------------------------------------------------------------------------------------------------
110
//                 ***Datenfelder***
111
//                -----------------
112
char *Dateiname[] = {"Datalog.txt"};          // Datei Name in der die Daten gespeichert werden
113
char Einstellungen[3];                  // Einstellwerte des Datenloggers
114
115
volatile char lese_buffer[15];                 // Empfangsbuffer   (15Byte groß) Globalveränderbar
116
unsigned char sende_buffer[20];                 // Sendebuffer     (20Byte groß) Globalveränderbar
117
118
unsigned char Messfeld[800];              // Feld für maximale Aufzeichnungsgeschwindigkeit
119
                            // (800 Messwerte aufnehmen und dann an USB senden)
120
121
unsigned char Messwert[17];                // ein Feld für 8 Anal Stromwerte    8 x 1Byte
122
                            //        8 Anal Spannungswerte  8 x 1Byte
123
                            //        8 Digi Spannungswerte   1 x 1Byte 
124
                            //                    ---------
125
                            //                    17x 1Byte
126
127
//****************************************************************************************************
128
//*****                                               *****
129
//*****                    Funktionen deklarieren                 *****
130
//*****                                               *****
131
//****************************************************************************************************
132
133
//                 ***Funktionen zur PORT Ein und Ausgabe***
134
//                 -----------------------------------------
135
char SDO_VNC(void);                    // init SDO VDIP-Out(Daten vom µC zurücklesen)
136
void PortD_OUT(void);                  // Daten am PortD ausgeben
137
unsigned char PortD_IN(char);              // Daten am PortD einlesen
138
139
140
//                 ***Funktionen für Datenspeichern***
141
//                 -----------------------------------
142
char USB_Datei_anlegen (void);               // Verbindung zum Sick prüfen und Datei anlegen 
143
char USB_Datei_erweitern (char*, unsigned int);      // USB Datei erweitern 
144
145
//                 ***Funktionen für VDIP1***
146
//                 --------------------------
147
//char SDO_VNC(void);    // siehe PORT Ein/Ausgabe  // init SDO (Dateneingang vom µC) 
148
void vdip1_init(void);                  // init VDIP1
149
char vdip1_Echocheck (void);              // VDIP1 auf Echo Prüfen
150
151
char SPI_byte_lesen(char);                // Byte über SPI einlesen
152
char vdip1_byte_lesen(void);               // Byte von dem VDIP1 lesen und Status auswerten
153
char vdip1_string_lesen(char *);
154
char vdip1_pruefen(char);                // String aus dem VDIP1 lesen und auswerten
155
156
char SPI_byte_schreiben(char);              // Byte über SPI schreiben
157
char vdip1_byte_schreiben(char);             // Byte in das VDIP1 schreiben
158
char vdip1_befehl_schreiben(unsigned char*);      // String in das VDIP1 schreiben
159
char vdip1_txtfile_schreiben(char *, char *, char, unsigned int);// Text   Dabei-Daten auf USB schreiben
160
char vdip1_bin_file_scheiben(char *, char *, unsigned int);     // Binäre Datei-Daten auf USB schreiben
161
162
//                 ***Funktionen für AD-Wandlung***
163
//                 --------------------------------
164
void AD_Wandler_init(void);                // init AD-Wandler
165
unsigned char AD_Wandler (void);              // AD-Wandlerfunktion für PortA Kanal 0
166
167
//                 ***Funktionen für Störungsauswertung***
168
//                 ---------------------------------------
169
void stoerung (char);                  // Störung setzen und auf Quit warten
170
void abfahren (void);                  // Messgerät abfahren
171
172
void init_Timer (void);
173
//****************************************************************************************************
174
//*****                                               *****
175
//*****                    Interrupt                       *****
176
//*****                                               *****
177
//****************************************************************************************************
178
//                 ***Wenn Timer Interrupt auslöst dann ausführen***
179
//                 -------------------------------------------------
180
  ISR (TIMER1_COMPA__vect)                // Interrupt Vektorvariable vom Timer1 Compare
181
    {
182
      Time = Time + 1;              // Time um 1 erhöhen
183
184
      if (Time == Durchlauf)            // Time = die Anzahl wie oft der Interrupt 
185
        {                    // Durchlaufen werden soll
186
          Aufnahme = 1;            // Merker für Aufnahmen setzen
187
          Time    = 0;            // Time zurücksetzen
188
        }
189
    }
190
191
192
193
//****************************************************************************************************
194
//*****                                               *****
195
//*****                    Hauptprogramm                     *****
196
//*****                                               *****
197
//****************************************************************************************************
198
int main (void) 
199
  {
200
    DDRA = 0xBA;                  // PortA PIN 0, 2, 6 als Eingang
201
                            // PortA alle anderen Pins als Ausgang 
202
    
203
    DDRB = 0xFF;                  // PortB alle Pins als Ausgang
204
205
    DDRC = 0xFF;                  // PortC alle Pins als Ausgang
206
207
//----------------------------------------------------------------------------------------------------
208
//                 ***Init Funktionen***
209
//                ---------------------
210
    vdip1_init();                    // VNC1L Initialisierung
211
    AD_Wandler_init();                // AD-Wandler Initialisierung
212
//    Timer_init;                    // Timer Interrupt wird später Initialisiert
213
214
//----------------------------------------------------------------------------------------------------
215
//                ***Starttaster abfragen***
216
//                --------------------------
217
/*
218
  while (Aktiv == 0)                  // Auf Starttaster warten
219
    {
220
      if (vdip1_Echocheck ())            // VDIP1 USB Stick überprüfen
221
        {
222
          Stoerung = 1;            // Wenn Störung: Störung setzen und
223
        }
224
  
225
      if ( Stoerung == 1)
226
        {
227
          stoerung (Stoerung);        // Störung auswerten        
228
        }
229
        else
230
          {
231
            abfahren ();          // Stop Taster auswerten
232
            Zustand = 0x01;          // Zustand = Bereit
233
            PortD_OUT();          // LED setzen
234
            _delay_ms(1000);          // Warten damit LED Zeit hat zum aufleuchten
235
236
            Aktiv = PortD_IN (Schalter2);  // PortD (Taster Start) einlesen und
237
            Aktiv = Aktiv & 0x10;       // Maskieren
238
239
            if (Aktiv)            // Wenn Starttaster gedrückt dann
240
              {
241
                Aktiv = 1;        // Aktiv = 1
242
                Aufnahme = 1;      // Es bebinnt sofort ein Aufnahmezyklus
243
                            // Der Interrupttimer startet dann die nächsten
244
                Zustand = 0x02;      // Zustand = Aufnahme
245
                PortD_OUT();      // LED setzen
246
              }
247
          }
248
    }
249
//*/  
250
//----------------------------------------------------------------------------------------------------
251
//                 ***Die Stromeinstellung einlesen***
252
//                -----------------------------------
253
     Wert        = PortD_IN (Schalter2);      // PortD (Stromkanaleinstellung) einlesen
254
  n_Stromwerte    = Wert & 0x0F;            // Wert Maskieren und in "n_Stromwerte" ablegen
255
  
256
  if (n_Stromwerte == 9)                // Wenn die 9 Eingestellt ist
257
    {
258
      n_Stromwerte = 8;              // wird eine 8 geschrieben da 9 nicht vergeben
259
    }
260
//                 ***Die Spannungseinstellung einlesen***
261
//                ---------------------------------------
262
  Wert       = PortD_IN (Schalter1);      // Schalter für Spannungskanälen abfragen
263
  n_Spannungswerte = Wert & 0x0F;            // Wert Maskieren und in "n_Spannungswerte" ablegen
264
  
265
  if (n_Spannungswerte == 9)              // Wenn die 9 Eingestellt ist
266
    {
267
      n_Spannungswerte = 8;            // wird eine 8 geschrieben da 9 nicht vergeben
268
    }
269
//                 ***Die Timereinstellung einlesen***
270
//                -----------------------------------
271
  Wert       = PortD_IN (Schalter1);      // Schalter für Timereinstellung abfragen
272
  Wert       = Wert & 0xF0;            // Wert Maskieren
273
  Timerwert     = Wert >> 4;            // Wert um 4Bit Schiften und in "Timerwert" ablegen
274
275
//----------------------------------------------------------------------------------------------------
276
/*
277
//       ***Datei auf USB-Stick anlegen und die Einstellwerte des Datenloggers ablegen***
278
//      --------------------------------------------------------------------------------
279
280
//                ***Basisdaten erstellen***
281
//                --------------------------
282
  Einstellungen[0] =   n_Stromwerte;          // Anzahl der Stromwerte 
283
  Einstellungen[1] =   n_Spannungswerte;        // Anzahl der Spannungswerte
284
  Einstellungen[2] =   Timerwert;            // Timereinstellung
285
286
//                ***USB Datei anlegen***
287
//                -----------------------
288
  if (USB_Datei_anlegen ())              // USB Datei anlegen und Basisdaten schreiben
289
    {
290
      Stoerung = 1;                // bei Fehler setze Stoerung
291
    }
292
293
  if ( Stoerung == 1)
294
    {
295
      stoerung (Stoerung);            // Störung auswerten        
296
    }
297
//*/
298
//----------------------------------------------------------------------------------------------------
299
300
//                ***Timereinstellung vornehmen***
301
//                --------------------------------
302
  switch (Timerwert)
303
    {  //Zeiteinstellung = 0  Pausen-Zeit = 0
304
      case 0:  Durchlauf = 0xFF;          // immer Messung starten
305
          break;
306
307
      // Zeiteinstellung = 1  Pausen-Zeit = 10ms
308
      case 1:  Durchlauf = 1;            // 1 x 10ms
309
          Vorteiler = 0x0A;          // Vorteiler = 8
310
          Byte1     = 0x00;  //0x07;          // Vergleichswert = 1901
311
          Byte0     = 0x9F;  //0x6D;
312
          break;
313
314
      // Zeiteinstellung = 2  Pausen-Zeit = 50ms        
315
      case 2:  Durchlauf = 1;            // 1 x 50ms
316
          Vorteiler = 0x0A;          // Vorteiler 8
317
          Byte1     = 0x25;          // Vergleichswert 9505
318
          Byte0     = 0x21;
319
          break;
320
321
      // Zeiteinstellung = 3  Pausen-Zeit = 100ms  
322
      case 3:  Durchlauf = 1;            // 1 x 100ms
323
          Vorteiler = 0x0A;          // Vorteiler 8
324
          Byte1     = 0x4A;          // Vergleichswert =19010
325
          Byte0     = 0x42;
326
          break;
327
328
      // Zeiteinstellung = 4  Pausen-Zeit = 1s  
329
330
331
      case 4:  Durchlauf = 1;            // 1 x 1s  
332
          Vorteiler = 0x0C;          // Vorteiler = 256
333
          Byte1     = 0x17;          // Vergleichswert = 5909
334
          Byte0     = 0x15;
335
          break;
336
337
      // Zeiteinstellung = 5  Zeit = 5s  
338
      case 5:  Durchlauf = 1;            // 1 x 5s
339
          Vorteiler = 0x0D;          // Vorteiler = 1024
340
          Byte1     = 0x1C;          // Vergleichswert = 7327
341
          Byte0     = 0x9F;
342
          break;
343
344
      // Zeiteinstellung = 6  Pausen-Zeit = 30s  
345
      case 6:  Durchlauf = 6;            // 6 x 5s
346
          Vorteiler = 0x0D;          // Vorteiler = 1024
347
          Byte1     = 0x1C;          // Vergleichswert = 7327
348
          Byte0     = 0x9F;
349
          break;
350
351
      // Zeiteinstellung = 7   Pausen-Zeit = 1min
352
      case 7:  Durchlauf = 12;            // 12 x 5s
353
          Vorteiler = 0x0D;          // Vorteiler = 1024
354
          Byte1     = 0x1C;          // Vergleichswert = 7327
355
          Byte0     = 0x9F;
356
          break;
357
358
      // Zeiteinstellung = 8  Pausen-Zeit = 10min
359
      case 8:  Durchlauf = 120;          // 120 x 5s          
360
          Vorteiler = 0x0D;          // Vorteiler = 1024
361
          Byte1     = 0x1C;          // Vergleichswert = 7327
362
          Byte0     = 0x9F;
363
          break;
364
365
      // Zeiteinstellung = 9   Sonderfunktion
366
      // zur Zeit noch unbenutzt (selbe Einstellung wie case 8:)
367
      case 9:  Durchlauf = 120;          // 120 x 5s          
368
          Vorteiler = 0x0D;          // Vorteiler = 1024
369
          Byte1     = 0x1C;          // Vergleichswert = 7327
370
          Byte0     = 0x9F;
371
          break;
372
    }
373
374
//----------------------------------------------------------------------------------------------------
375
376
377
378
// ****************************************************************************************************
379
// *****            Hauptschleife zum messen der Signale                   *****
380
// ****************************************************************************************************
381
382
init_Timer ();
383
384
while (1)
385
{
386
  Aufnahme = Aufnahme;
387
388
  if (Aufnahme == 1)                  // Wenn Datenlogger aufnehmen soll
389
    {
390
      cli();                        //alle Interrupts sperren um 16Bit Register zu beschreiben
391
392
      Aufnahme = 0;
393
394
    //  Zustand = 0x07;      // Zustand = Aufnahme
395
      PORTD = 0xFF;
396
    //  PortD_OUT();      // LED setzen
397
      _delay_ms(300);      // Warten damit LED Zeit hat zum aufleuchten
398
399
    //  Zustand = 0x00;      // Zustand = Aufnahme
400
      PORTD = 0x00;
401
    //  PortD_OUT();      // LED setzen
402
  
403
      sei();                        // alle Interrups wieder freigeben 
404
    }
405
}
406
//                ***Aktiv ENDE***
407
//====================================================================================================
408
//    abfahren ();                    // Stop Taster auswerten
409
410
  return 0;
411
  }
412
//****************************************************************************************************
413
//*****                                               *****
414
//*****                    Funktionen                       *****
415
//*****                                               *****
416
//****************************************************************************************************
417
//                 ***init Interrupt für Timer***
418
//                 ------------------------------  
419
void init_Timer (void)
420
  {
421
  cli();                        //alle Interrupts sperren um 16Bit Register zu beschreiben
422
  
423
  TCCR1A = 0x00;                    //keine PWM und keine Interrupt Ausgabe
424
  TCCR1B = Vorteiler;                  //Compare Modus & Vorteile setzen
425
//                Vergleichs- Regiser setzen
426
  OCR1AH = Byte1;                    // 16 Bit Compare Register A obere  8 Bits 
427
  OCR1AL = Byte0;                    // 16 Bit Compare Register A untere 8 Bits
428
  
429
  sei();                        // alle Interrups wieder freigeben 
430
431
  TIMSK1 |= (1<< OCIE1A);               // Compare Interrupt aktivieren
432
  
433
  return;
434
  }
435
436
//****************************************************************************************************
437
// Daten am PortD ausgeben
438
//****************************************************************************************************
439
void PortD_OUT(void)                  // Byte ausgeben
440
  {
441
    MUX_LED;                    // Multiplexer auf LED's setzen
442
    DDRD  = 0xFF;                  // PortD als Ausgang
443
    PORTD = ~Zustand;                // Daten auf PortD ausgeben
444
445
  return;
446
  }
447
448
449
//****************************************************************************************************
450
// Daten am PortD einlesen
451
//****************************************************************************************************
452
unsigned char PortD_IN(char Adresse)          // Byte lesen
453
  {
454
    unsigned char Input;
455
456
    DDRD  = 0x00;                  // PortD als Eingang
457
    PORTD = 0xFF;                  // PortD Pull-Up Widerstände aktivieren
458
    
459
    switch (Adresse)
460
      {
461
        case 0:  MUX_Digi_U;            // Wenn Adresse 0 Digitale Spannungs einlesen
462
            break;
463
464
        case 1:  MUX_Schalter1;          // Wenn Adresse 1 Schalter1 einlesen
465
            break;
466
467
        case 2:  MUX_Schalter2;          // Wenn Adresse 2 Schalter2 einlesen
468
            break;
469
      }
470
  
471
    _delay_us(100);                 // 100µs Pause  
472
473
    Input = ~PIND;                  // PortD Einlesen und Invertieren da Low aktiv
474
475
  
476
    PortD_OUT();                  // nach dem Einlesen wieder zurückschalten auf 
477
                            // LED's und auf Ausgabe
478
  return Input;
479
  }

Für denn Interrupt unnötige Funktionen (wie zum Beispiel USB Verwaltung, 
an und Abfahren, Messwerterfassung) habe ich mal weg gelassen, damit es 
auch noch etwas überschaubar bleibt. Im Augenblick sollen nur die LEDs 
blinken wenn ich eine Zeit einstelle.

Wie schon geschrieben benutze ich einen ATmega644.
Ich bin für jeden Tipp dankbar.

mfg
LPT

von Falk B. (falk)


Lesenswert?


von swen (Gast)


Lesenswert?

ohje...
sag mal was soll das? schon mal aufgefallen, das du beim posten ein 
möglichkeit hast code als datei hochzuladen?

du machst dir damit deinen eigenen thread kaputt. so hilft dir keiner..

ist nur gut gemeint
swen

von Karl H. (kbuchegg)


Lesenswert?

So wird das schwierig dir zu helfen.

Was ich tun würde:
Neues Projekt anfangen.
Und dann sukzessive, Schritt für Schritt, ein Subsystem nach dem anderen 
vom alten Projekt in das Neue übernehmen und dort einbauen. Nach jeder 
einzelnen Übernahme ausgiebig testen, ob Anomalien auffallen. Erst dann, 
wenn ich denke, dass der neu hinzugekommene Teil keine Probleme 
verursacht, kommt das nächste Subsystem dazu.

von Grrrr (Gast)


Lesenswert?

Es wird günstig sein, wenn Du den Code reduzierst. Also alles entfernen 
was mit dem fraglichen Timer und seinem Interrupt nichts zu tun hat. 
Kein Code für USB oder AD-Wandlung. Das Ergebnis muss kompilierbar sein.

Damit erfahren wir auch ob das Problem nur mit der Timerprogrammierung 
und Auswertung selbst zu tun hat oder ob auch der Rest bei dem Problem 
eine Rolle spielt.

von Grrrr (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Neues Projekt anfangen.

Oder so.

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
Noch kein Account? Hier anmelden.