Forum: Mikrocontroller und Digitale Elektronik Interrupt Eingänge bei mega8 richtig verwenden - HILFE!


von Pat F. (breaker87)


Lesenswert?

Hey Leute!

Ich würde gerne mit meinem ATmega8 folgendes realisieren:

Durch das setzen einer Variablen soll der INT0-Eingang "freigegeben" 
werden.
Nachdem einmal ein Impuls über INT0 "herein kommt", soll INT0 
deaktiviert und dafür

der INT1-Eingang aktiviert werden. Weiters wird ein Timer gestartet, 
welcher so lange

läuft, bis eine bestimmte Taste gedrückt wird. Über den INT1 Eingang 
kommen

laufend Impulse. Nach einem Tastendruck (die vorher gesetzte Variable 
wird wieder

gelöscht) soll dann dieser Eingang (und der Timer) wieder deaktiviert 
werden...

Leider schaffe ich es nicht, das Programm zum laufen zu bringen...

Hier mal meine bisherigen "Ergebnisse":
1
#include <mega8.h>
2
#include <LCDlib2x16.h>
3
#include <stdio.h>
4
           
5
//Definiton der Ein- bzw. Ausgaenge
6
#define Links     !PINC.0  //Active High Taster --> Links  
7
#define Rechts    !PINC.1  //Active High Taster --> Rechts   
8
#define Enter     !PINC.2  //Active High Taster --> Enter   
9
#define Back      !PINC.3  //Active High Taster --> Back
10
11
#define LCD_SIZE 16    //Zeichen pro Zeile im Display
12
13
14
// Welcome string to display on a 16 char-LCD:
15
const char Fstmsg[16]=// 
16
{'M','e','s','s','u','n','g','>','s','t','a','r','t',' ','K','2'};
17
18
19
// Declare your global variables here:
20
unsigned char n;  // global count variable
21
long zeit=0;
22
long zeitarray[20];
23
long aktuellezeit;
24
void time_convert(unsigned long hundertstel, unsigned char zeile);
25
void messfunktion(void);
26
void LCD_puts(char *pStr1, char *pStr2, unsigned char);
27
void initSFR(void);
28
int run=0;  //countvariable  
29
bit runLCD=0;
30
bit erster=0;  //sobald der erste Laeufer im Ziel ist wird diese
31
               //Variable 1 gesetzt...
32
int laeuferNR=1;
33
bit Messung_ready;
34
bit Messung_running;
35
36
// Timer 0 overflow interrupt service routine
37
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
38
{  
39
   if(!Messung_running){
40
      zeit++;
41
      TCNT0=0x06;}
42
   else
43
   {;}
44
} 
45
46
// External Interrupt 0 service routine
47
interrupt [EXT_INT0] void ext_int0_isr(void)
48
{
49
// Place your code here
50
   TCCR0=0x03;
51
   Messung_running=1;
52
}
53
54
// External Interrupt 1 service routine
55
interrupt [EXT_INT1] void ext_int1_isr(void)
56
{
57
// Place your code here
58
   TCCR0=0x03;
59
   messfunktion();
60
}
61
62
void main(void)
63
{  
64
   bit x=0;
65
   initSFR();
66
   // Global enable interrupts
67
   #asm("sei")
68
   
69
   InitLCD(); // initialize LCD; auto increment cursorposition
70
   delay(10); // wait 250 ms before first write
71
   // write to LCD (cursor is at 1. pos. after initialization) 
72
   
73
   SetCursLCD(1);
74
   for(n=0;n<16;n++)   // write first 8 chars of welcome message
75
      {WrCharLCD(Fstmsg[n]);}
76
   
77
   SetCursLCD(17);
78
   for(n=0;n<16;n++)   // write first 8 chars of welcome message
79
      {WrCharLCD(Fstmsg[n]);}
80
81
   while (1)       // do forever
82
   {  
83
      if(Enter)
84
      {  Messung_ready=1;
85
         GICR|=0x40;
86
         MCUCR=0x01;
87
         GIFR=0x40; }
88
      else if(Back)
89
      {  Messung_ready=0;}
90
      else
91
      {  
92
         while(Messung_running && Messung_ready)
93
           {if(x=0)
94
           {   GICR|=0x80;
95
               MCUCR=0x04;
96
               GIFR=0x80;}
97
           else
98
               {time_convert((zeitarray[1]+zeit),1);
99
                time_convert(zeitarray[laeuferNR]+zeitarray[0],2);
100
                delay(10);}
101
      }    }
102
   }// End of while 
103
104
} //End of main
105
106
void time_convert(unsigned long hundertstel, unsigned char zeile)
107
{
108
   unsigned long int stunden, minuten, sekunden,
109
   minutenR, sekundenR, hundertstelR;
110
   unsigned char time[16],x;
111
   
112
   SetCursLCD(1);
113
   hundertstel = hundertstel / 10;
114
   hundertstelR =  hundertstel % 100; //hundertstel
115
   sekunden  = hundertstel / 100; //ganze sekunden
116
   sekundenR = sekunden % 60; //sekunden
117
   minuten   = sekunden / 60; //ganze minuten
118
   minutenR  = minuten % 60; //minuten
119
   stunden   = minuten / 60; //ganze Stunden
120
   
121
   sprintf(time, "%i. %02d:%02d:%02d,%02d ", 
122
123
laeuferNR,stunden,minutenR,sekundenR,hundertstelR);
124
125
   if(zeile==0){ 
126
      LCD_puts(time,time,0);}
127
128
   if(zeile==1){   
129
      LCD_puts(time,time,1);}
130
131
   if(zeile==2){   
132
      LCD_puts(time,time,2);}
133
     
134
}  //time_convert                              
135
136
void messfunktion(void)
137
{
138
   if(!erster) {
139
     zeitarray[1]=zeit;
140
     zeit=0;
141
     erster=1; }
142
   else {
143
    laeuferNR++;
144
    zeitarray[laeuferNR]=zeit; }
145
} 
146
 
147
void initSFR(void)
148
{
149
// Declare your local variables here
150
151
//Allgemeine Definitionen des Mikrocontrollers
152
// Port B initialization
153
PORTB=0x00;
154
DDRB=0x3F;
155
// Port C initialization
156
PORTC=0x7F;
157
DDRC=0x00;
158
// Port D initialization 
159
PORTD=0xFF;
160
DDRD=0x00;  
161
// Analog Comparator initialization
162
ACSR=0x80;
163
SFIOR=0x00;
164
// External Interrupt(s) initialization
165
// INT0: On
166
// INT0 Mode: Any change
167
// INT1: On
168
// INT1 Mode: Any change
169
GICR|=0x00;
170
MCUCR=0x00;
171
GIFR=0x00;  
172
// Timer/Counter 0 initialization
173
// Clock source: System Clock
174
// Clock value: 16000,000 kHz
175
TCCR0=0x03;  //Prescaler 64 --> 0x01 = Standartwert
176
TCNT0=0x06;  //Vorladen mit 6 
177
// Timer(s)/Counter(s) Interrupt(s) initialization
178
TIMSK=0x01;
179
}          
180
/**Funktion um einzelne Zeichen eines Arrays auszugeben **/
181
void LCD_puts(char *pStr1, char *pStr2, unsigned char zeile)
182
{                       
183
    unsigned char count=0;
184
    
185
   if((zeile==1)||(zeile==0))
186
   { 
187
    SetCursLCD(1);
188
    while (*pStr1)
189
    { WrCharLCD(*pStr1++);
190
      count++;}
191
    while (count++ < LCD_SIZE)
192
    { WrCharLCD(' '); }
193
    delay(2);
194
    count = 0;
195
    }
196
    else
197
   if((zeile==2)||(zeile==0))
198
   {
199
    SetCursLCD(17);
200
    while (*pStr2)
201
    { WrCharLCD(*pStr2++);
202
      count++; }
203
    while (count++ < LCD_SIZE)
204
    { WrCharLCD(' ');}
205
   }
206
}

Ich würde mich echt freuen, wenn ihr mir weiter helfen könntet...


lg Patrick

von Stefan (Gast)


Lesenswert?

Bevor wieder jemand diesen dämlichen abgenutzen Glaskugel-Spruch bringt, 
frag ich mal ganz "normal": Was genau geht denn nicht ?!

von Pat F. (breaker87)


Lesenswert?

Also das Problem liegt daran, dass die Interrupts nicht so funktionieren 
wie sie sollten: sobald er erste interrupt (INT0) auftritt, wird der 
zweite Interrupt (INT1) nicht mehr erkannt... Beim nochmaligen auftreten 
von INT0 startet das Programm von vorne...

lg

von Pat F. (breaker87)


Lesenswert?

keiner eine Idee?

Ach ja, ich verwende CVAVR zum Programmieren und PonyProg zum 
Daten-überspielen...


lg

von Peter D. (peda)


Lesenswert?

Patrick F. wrote:

> läuft, bis eine bestimmte Taste gedrückt wird. Über den INT1 Eingang
> kommen
>
> laufend Impulse.

Schön für die Impulse, daß sie reinkommen.
Aber was sollen diese bewirken ?

Versuch mal offline in Ruhe die Funktion zu beschreiben, d.h. nicht so 
wirr, sondern daß man es auch versteht, und dann poste es.


>          GICR|=0x40;
>          MCUCR=0x01;
>          GIFR=0x40; }

Ich hab keine Lust, ständig im Datenblatt zu blättern.
Also verwende bitte statt kryptischer Hexwerte die im Datasheet 
vordefinierten Bitnamen und kommentiere, was Du damit bewirkst.


Peter

von Peter D. (peda)


Lesenswert?

Und Code natürlich immer als Dateianhang posten !

Mein Scrollfinger ist schon total verkrampft.


Peter

von Andreas Kramer (Gast)


Lesenswert?

Warum nimmst du nicht einfach die C Funktion bei :

// Global enable interrupts
   #asm("sei")

Soviel ich weiß ist die doch sei(); oder ? Ansonnsten würde ich einfach 
mal versuchen inerhalb des ersten Iterrupts den zu deaktivieren damit er 
nicht einfach neu starten kann und erst beim Benden des anderen wieder 
zu aktivieren wenn ich die Funktion richtig verstanden hab =). Ich sehe 
nicht das du irgendwo inerhalb des Interrupts den auch wieder 
deaktivierst wie oben geschrieben.

Gruß Andreas

von Pat F. (breaker87)


Angehängte Dateien:

Lesenswert?

Hab mir jetzt Zeit genommen und eine Beschreibung (inkl Skizze) 
verfasst, welche sich im Anhang befindet.
Den C-Code habe ich auch in den Anhang gegeben...


lg Patrick

von Andreas Kramer (Gast)


Lesenswert?

Warum lässt du nicht einfach den Timer dauerhaft laufen und sezt einfach 
mit dem Int0 den Timer auf 0 und die intern erhöte Varible auch und 
deaktivierst noch Int0. So damit ist teil eins fertig.

Jetzt nimmst du Int1 und sagst ihm die im timer verwendete variable in 
ein Array bsp mit nem Zeiger und erhöst hier noch eine 2te variable um 
zu wissen der wievielte Wert das ist damit dein Array nicht überläuft 
z.b. noch damit ne Begrenzung einbauen. Jetzt setzt du die Variable im 
Timer auf 0 und verschiebst den Zeiger weiter für das nächste Ergebniss. 
Oder du nimmst anstelle von dem Array einfach die benötigte Anzahl von 
Variablen z.B. 4 und dann ne Schleife die jeweils die timervariable in 
der richtigen Var speichert.

Gruß Andreas

von johnny.m (Gast)


Lesenswert?

@Andreas:
In CodeVision gibts kein sei(). Das #asm("sei") ist schon korrekt.

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.