Forum: Compiler & IDEs Interrupt nicht deaktivierbar


von Athlon N. (athlon)


Lesenswert?

Hallo!
Ich hab grad damit begonnen, mich in die Materie der MC Programmierung 
einzuarbeiten.
Verwende einen Attiny 2313A und Atmel Studio 6.

Folgendes möcht ich machen:
Durch Verwendung des Analog Comparators soll mit Hilfe eines 
Phototransistors ein Interrupt ausgelöst werden, wenn das Umgebungslicht 
eine gewisse Schwelle unterschreitet. Das funktioniert auch schon.

Dann soll in der Interrupt Routine des AC´s eine LED aktiviert und ein 
Flag gesetzt werden.

In der While Schleife im Main wird bei gesetztem Flag ein Timer im CTC 
Modus aktiviert. Außerdem wird das AC Interrupt Bit 0 gesetzt.
Erreicht der Timer/Counter den definierten Wert, wird wieder ein 
Interrupt ausgelöst und die LED wieder deaktiviert und der Timer 
gestoppt.
Das funktioniert auch schon.

Nun hab ich allerdings das Problem, dass der AC wieder ein Interrupt 
auslöst, wenn das Umgebungslicht einen gewissen Wert unterschreitet, 
obwohl ich das Interruptbit auf 0 gesetzt habe.
1
//Analog Comparator
2
  ACSR = 0<<ACIE; //clear the interrupt bit
3
  ACSR = 0<<ACD; //power ON analog comparator
4
  ACSR = 0<<ACBG; //use AIN0 as positive Input
5
  ACSR = 0<<ACIC; //Input Capture disabled
6
  ACSR = 0<<ACIS0; //Interrupt Mode (Output Toggle)
7
  ACSR = 0<<ACIS1; //Interrupt Mode (Output Toggle)
8
  ACSR = 1<<ACIE; //Enable Interrupts again
9
    
10
  //16 bit Timer1 Register A
11
  TCCR1B &= ( (0<<CS12) | (0<<CS11) | (0<<CS10)); //Stop Timer/Counter (Timer 1 Register A and B uses the same Clock)
12
  TCCR1A = 0<<COM1A1; //Normal port operation - OC1A disconnected
13
  TCCR1A = 0<<COM1A0; //Normal port operation - OC1A disconnected
14
  TCCR1A = 0<<WGM13;
15
  TCCR1A = 1<<WGM12; //CTC1 - CTC mode with Top OCR1A
16
  TCCR1A = 0<<WGM11; //disable PWM11
17
  TCCR1A = 0<<WGM10; //disable PWM10
18
19
  OCR1AH = 0x00; //compare register high
20
  OCR1AL = 0x98; //compare register low
21
    
22
  sei(); //Global Interrupts enabled
23
  
24
  
25
    while(1)
26
    {
27
    if(flag == 1)
28
    {
29
      cli();
30
      flag = 0;
31
      TIMSK = 1<<OCIE1A; //Timer, Output Compare A Match Interrupt enable  
32
      ACSR = 0<<ACIE; //Disable Analog Comparator Interrupts
33
      ACSR = 1<<ACD; //Disable Analog Comparator
34
      TCCR1B |= ( (0<<CS12) | (1<<CS11) | (1<<CS10)); //start timer/counter
35
      sei();
36
    }                 
37
    }
38
  
39
  return 0;
40
}
41
42
ISR(ANA_COMP_vect)
43
{
44
  cli();
45
  PORTD = 1<<PORTD2; //enable LED
46
  flag = 1;
47
  sei();
48
}
49
50
ISR(TIMER1_COMP1_vect)
51
{
52
  cli();
53
    
54
  PORTD = 0<<PORTD2; //disable LED
55
      
56
  TCCR1B &= ( (0<<CS12) | (0<<CS11) | (0<<CS10)); //Stop Timer/Counter
57
  sei();
58
}

Könntet Ihr mal bitte drüberschauen?

Lg

von Peter II (Gast)


Lesenswert?

entferne erstmal sei und cli aus dem ISRs. Das gehört dort nicht rein.

von Peter II (Gast)


Lesenswert?

TCCR1B &= ( (0<<CS12) | (0<<CS11) | (0<<CS10)); //Stop Timer/Counter

so löscht man auch keine Bits.

siehe Bitmanipulation

von Hans (Gast)


Lesenswert?

Athlon N/a schrieb:
> 0<<

Bringt nichts wenn eine Zuweisung oder eine Veroderung erfolgt.

von Athlon N. (athlon)


Lesenswert?

Ok, habs mal geändert:
1
  //Analog Comparator
2
  ACSR = 0<<ACIE; //clear the interrupt bit
3
  ACSR = 0<<ACD; //power ON analog comparator
4
  ACSR = 0<<ACBG; //use AIN0 as positive Input
5
  ACSR = 0<<ACIC; //Input Capture disabled
6
  ACSR = 0<<ACIS0; //Interrupt Mode (Output Toggle)
7
  ACSR = 0<<ACIS1; //Interrupt Mode (Output Toggle)
8
  ACSR = 1<<ACIE; //Enable Interrupts again
9
    
10
  //16 bit Timer1 Register A
11
  TCCR1B &= ~( (1<<CS12) | (1<<CS11) | (1<<CS10)); //Stop Timer/Counter
12
  TCCR1A = 0<<COM1A1; //Normal port operation - OC1A disconnected
13
  TCCR1A = 0<<COM1A0; //Normal port operation - OC1A disconnected
14
  TCCR1A = 0<<WGM13;
15
  TCCR1A = 1<<WGM12; //CTC1 - CTC mode with Top OCR1A
16
  TCCR1A = 0<<WGM11; //disable PWM11
17
  TCCR1A = 0<<WGM10; //disable PWM10
18
19
  OCR1AH = 0x00; //compare register high
20
  OCR1AL = 0x98; //compare register low
21
    
22
  sei(); //Global Interrupts enabled
23
  
24
  
25
    while(1)
26
    {
27
    if(flag == 1)
28
    {
29
      cli();
30
      flag = 0;
31
      TIMSK = 1<<OCIE1A; //Timer, Output Compare A Match Interrupt enable  
32
      ACSR = 0<<ACIE; //Disable Analog Comparator Interrupts
33
      ACSR = 1<<ACD; //Disable Analog Comparator
34
      TCCR1B |= ( (0<<CS12) | (1<<CS11) | (1<<CS10)); //start timer/counter
35
      sei();
36
    }                 
37
    }
38
  
39
  return 0;
40
}
41
42
43
ISR(ANA_COMP_vect)
44
{
45
  PORTD = 1<<PORTD2; //enable LED
46
  flag = 1;
47
}
48
49
ISR(TIMER1_COMP1_vect)
50
{
51
  //if(PIND & (1<<PIND1))
52
    
53
  PORTD = 0<<PORTD2; //disable LED
54
      
55
  TCCR1B &= ~( (1<<CS12) | (1<<CS11) | (1<<CS10)); //Stop Timer/Counter
56
}

Hans schrieb:
> Athlon N/a schrieb:
>> 0<<
>
> Bringt nichts wenn eine Zuweisung oder eine Veroderung erfolgt.

Meinst du beim deaktiveren des Interrupts?

von Peter II (Gast)


Lesenswert?

PORTD = 0<<PORTD2; //disable LED

das macht auch nicht wirklich das was du willt. Da kannst du auch gleich 
PORTD = 0 schreiben.

TCCR1B |= ( (0<<CS12) | (1<<CS11) | (1<<CS10)); //start timer/counter

ist genauso unsinn. Denke doch mal drüber nach was du schreibst.

von Peter II (Gast)


Lesenswert?

Peter II schrieb:
> TCCR1B |= ( (0<<CS12) | (1<<CS11) | (1<<CS10)); //start timer/counter
>
> ist genauso unsinn. Denke doch mal drüber nach was du schreibst.

sorry, meinste es nicht so schlimmt. Das Problem ist das du CS12 mit 
dieser anweisung nicht löschen kannst. Wenn es vorher 1 ist, bleibt es 
auch 1.

von Uwe (de0508)


Lesenswert?

Hallo,

noch ein Tipp, welche Werte haben wohl die Register ACSR und TCCR1A ?

ACSR = 1<<ACIE
TCCR1A = 0 richtig !


> ACSR = 1<<ACIE;
> TCCR1A = 0<<WGM10;

von Bernd S. (bernds1)


Lesenswert?

Auch ganz oben beim Anfang sind viele 0<<ACIE usw. Dort trifft das auch 
zu.
Mach eine Veroderung der einzelnen Bits und weise das ganze Byte auf 
einmal dem Register zu (z.B. ACSR).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Athlon N/a schrieb:
> ACSR = 0<<ACIE; //clear the interrupt bit
>   ACSR = 0<<ACD; //power ON analog comparator
>   ACSR = 0<<ACBG; //use AIN0 as positive Input
>   ACSR = 0<<ACIC; //Input Capture disabled
>   ACSR = 0<<ACIS0; //Interrupt Mode (Output Toggle)
>   ACSR = 0<<ACIS1; //Interrupt Mode (Output Toggle)
>   ACSR = 1<<ACIE; //Enable Interrupts again
>
>   //16 bit Timer1 Register A
>   TCCR1B &= ( (0<<CS12) | (0<<CS11) | (0<<CS10)); //Stop Timer/Counter (Timer 1 
Register A and B uses the same Clock)
>   TCCR1A = 0<<COM1A1; //Normal port operation - OC1A disconnected
>   TCCR1A = 0<<COM1A0; //Normal port operation - OC1A disconnected
>   TCCR1A = 0<<WGM13;
>   TCCR1A = 1<<WGM12; //CTC1 - CTC mode with Top OCR1A
>   TCCR1A = 0<<WGM11; //disable PWM11
>   TCCR1A = 0<<WGM10; //disable PWM10

Das ist kompletter Humbug.  Die Register werden ja jedesmal komplett
überschrieben.  ACSR wird am Ende also nur ACIE gesetzt haben, und
TCCR1A steht auf 0.  Schreib das so:
1
ACSR = (1 << ACIE);
2
TCCR1A = (1 << WGM12);

Wenn du unbedingt noch kommentieren willst, was alles nicht gesetzt
ist, dann so:
1
ACSR = /* !ACD | !ACBG | !ACI | */ (1 << ACIE) /* | !ACIC | !ACIS0 | !ACIS1 */;

Die Bibliothek bietet noch den Makro _BV() als Abkürzung für das
Bitgeschiebe.  Meiner Meinung nach lässt er sich geringfügig besser
lesen als eine Anhäufung von (1 << BIT).

WGM12 ist nicht im Register TCCR1A angesiedelt, sondern in TCCR1B.

Zu guter Letzt liegt der Verdacht noch nahe, dass dein "flag" nicht
volatile deklariert ist.  Die Deklaration hast du uns aber
vorenthalten.

von Athlon N. (athlon)


Lesenswert?

Auweia, da hab ich ja wirklich nen Blödsinn gemacht...
Hier nochmal alles und ausgebessert:
1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3
4
volatile int8_t flag = 0;
5
6
int main(void)
7
{
8
  cli(); //Global Interrupts disabled
9
  
10
  //Port Directions
11
  DDRA |= 0b00000001; //A0 as Output - MOS2 Supply
12
  DDRA &= 0b11111101; //A1 as Input - DIP switch #1
13
  DDRB &= 0b11111110; //B0 as Input - positive Analoginput - AIN0
14
  DDRB &= 0b11111101; //B1 as Input - negative Analoginput - AIN1
15
  DDRD &= 0b11111110; //D0 as Input - DIP switch #3
16
  DDRD &= 0b11111101; //D1 as Input - DIP switch #2
17
  DDRD |= 0b00000100; //D2 as Output - LED Supply
18
    
19
  //Enabling Ports (output) - Set pull Up Resistor (Input)
20
  PORTA &= 0b11111110; //A0 MOS2 supply Bit
21
  PORTA &= 0b11111101; //A1 deactivate pull Up Resistor - DIP #1
22
  PORTB &= 0b11111110; //B0 deactivate pull Up Resistor - AIN0
23
  PORTB &= 0b11111101; //B1 deactivate pull Up Resistor - AIN1
24
  PORTD &= 0b11111110; //D0 deactivate pull Up Resistor - DIP #3
25
  PORTD &= 0b11111101; //D1 deactivate pull Up Resistor - DIP #2
26
  PORTD &= 0b11111011; //D2 LED Voltage supply
27
    
28
  //Analog Comparator
29
  ACSR &= 0b11110111; //clear the interrupt bit
30
  ACSR &= 0b01111111; //power ON analog comparator
31
  ACSR &= 0b10111111; //use AIN0 as positive Input
32
  ACSR &= 0b11111011; //Input Capture disabled
33
  ACSR &= 0b11111110; //Interrupt Mode (Output Toggle)
34
  ACSR &= 0b11111101; //Interrupt Mode (Output Toggle)
35
  ACSR |= 0b00001000; //Enable Interrupts again
36
    
37
  //16 bit Timer1 Register B
38
  TCCR1B &= 0b11111000; //Stop Timer/Counter
39
  TCCR1B &= 0b11101111; //WGM13
40
  TCCR1B |= 0b00001000;//WGM12 - CTC mode with Top OCR1A
41
42
  OCR1AH = 0x05; //compare register high
43
  OCR1AL = 0x98; //compare register low
44
    
45
  sei(); //Global Interrupts enabled
46
  
47
  
48
    while(1)
49
    {
50
    if(flag == 1)
51
    {
52
      cli();
53
      flag = 0;
54
      TIMSK |= 0b00100000; //Timer, Output Compare B Match Interrupt enable  
55
      ACSR &= 0b11110111; //Disable Analog Comparator Interrupts
56
      TCCR1B |= 0b00000101; //start timer/counter with Clock/1024 Prescaler CS12=0, CS11=1, CS10=1
57
      sei();
58
    }                 
59
    }
60
  
61
  return 0;
62
}
63
64
ISR(ANA_COMP_vect)
65
{
66
  PORTD |= 0b00000100; //enable LED
67
  flag = 1;
68
}
69
70
ISR(TIMER1_COMP1_vect)
71
{
72
  
73
  PORTD &= 0b11111011;
74
    
75
  //PORTD = 0<<PORTD2; //disable LED
76
      
77
  TCCR1B &= 0b11111000; //Stop Timer/Counter 
78
79
80
}

Das Problem besteht leider immer noch. Flag wurde als volatile 
definiert.

von Peter II (Gast)


Lesenswert?

Athlon N/a schrieb:
> Das Problem besteht leider immer noch. Flag wurde als volatile
> definiert.

ich glaube du hast immer noch nicht verstanden was du überhaupt machst

 PORTA &= 0b11111110; //A0 MOS2 supply Bit
 PORTA &= 0b11111101; //A1 deactivate pull Up Resistor - DIP #1

was soll das?

von Athlon N. (athlon)


Lesenswert?

Das PORTA Register besteht doch aus 8 bit. Nun sag ich PORTA = PORTA & 
0b11111110

Das heißt, das letzte bit wird 0 gesetzt und alle anderen Bits bleiben 
so wie sie waren.
Sollte so doch gehn oda?

von Peter II (Gast)


Lesenswert?

Athlon N/a schrieb:
> Das heißt, das letzte bit wird 0 gesetzt und alle anderen Bits bleiben
> so wie sie waren.
> Sollte so doch gehn oda?

aber welchen welchen Startwert geht du denn aus? Wenn PORTA nach dem 
init 0 ist, dann bringen deine Befehle nichts.

von Athlon N. (athlon)


Lesenswert?

Das MOS2 Supplybit soll hier 0 gesetzt werden, das brauch ich erst wenn 
der Rest funktioniert. Egal welchen Startwert PORTA beim init hat, PORT 
A0 wird 0 gesetzt.
Diese Befehle sind hier unnötig das stimmt, ich kann mir so aber quasi 
notieren, welche Ports wie eingestellt sind.

von Falk B. (falk)


Lesenswert?

@  Athlon N/a (athlon)

>volatile int8_t flag = 0;

Warum int? uint reicht, ist hier aber egal.

>int main(void)
>{
>  cli(); //Global Interrupts disabled

Ist überflüssig, denn hier sind die Interrupts SICHER gesperrt, nach dem 
Reset.

>  //Port Directions
>  DDRA |= 0b00000001; //A0 as Output - MOS2 Supply
>  DDRA &= 0b11111101; //A1 as Input - DIP switch #1
>  DDRB &= 0b11111110; //B0 as Input - positive Analoginput - AIN0
>  DDRB &= 0b11111101; //B1 as Input - negative Analoginput - AIN1
>  DDRD &= 0b11111110; //D0 as Input - DIP switch #3
>  DDRD &= 0b11111101; //D1 as Input - DIP switch #2
>  DDRD |= 0b00000100; //D2 as Output - LED Supply

Schreibt man anders, damit man es besser lesen kann, siehe 
Bitmanipulation.

>  //Analog Comparator

Dito. Da sieht man nur schwer durch. Probiers mal so

  ACSR = (1<<ACIE);  // enable AC interrupts
  ACSR |= (1<<ACIF); //clear the interrupt bit

>ISR(ANA_COMP_vect)
>{
>  PORTD |= 0b00000100; //enable LED
>  flag = 1;
>}

OK.

Lass mal die Timer ISR erstmal weg. Dann muss wenigstens erstmal dr 
Analogcomparator reagieren.

von Karl H. (kbuchegg)


Lesenswert?

Du ersetzt eine bescheuerte Schreibweise durch eine andere.

Das ist doch alles Schwachsinn.

Wenn es dir so schwer fällt, da endlich mal eine ordentliche 
Schreibweise zu finden, dann mach dir von mir aus ein paar Makros
1
#define SET_BIT(reg,bit)  (reg) |= (1<<bit)
2
#define CLR_BIT(reg,bit)  (reg) &= ~(1<<bit)

und schreib dann
1
  CLR_BIT( ACSR, ACIE );
2
  CLR_BIT( ACSR, ACD );
3
  CLR_BIT( ACSR, ACBG ); //use AIN0 as positive Input
4
  CLR_BIT( ACSR, ACIC ); //Input Capture disabled
5
  CLR_BIT( ACSR, ACIS0 ); //Interrupt Mode (Output Toggle)
6
  CLR_BIT( ACSR, ACIS1 ); //Interrupt Mode (Output Toggle)
7
  SET_BIT( ACSR, ACIE ); //Enable Interrupts again

und für den Rest genauso. Aber eigentlich ist das Unsinn immer alle Bits 
eines Register unbedingt in Einzelanweisungen behandeln zu wollen.
Aber so wie du das machst, tappst du von einem unverständlichen Code in 
den nächsten.
Das kann doch kein Mensch mehr analysieren, was da wirklich abgeht!

von Karl H. (kbuchegg)


Lesenswert?

> Diese Befehle sind hier unnötig das stimmt, ich kann mir so aber
> quasi notieren, welche Ports wie eingestellt sind.

Das einzige was du tust ist, du erhöhst die Komplexität soweit, dass du 
sie nicht mehr überblicken kannst.

von Karl H. (kbuchegg)


Lesenswert?

Nur mal als Beispiel

Du schreibst
1
   DDRA |= 0b00000001; //A0 as Output - MOS2 Supply
2
   DDRA &= 0b11111101; //A1 as Input - DIP switch #1
3
   DDRB &= 0b11111110; //B0 as Input - positive Analoginput - AIN0
4
   DDRB &= 0b11111101; //B1 as Input - negative Analoginput - AIN1
5
   DDRD &= 0b11111110; //D0 as Input - DIP switch #3
6
   DDRD &= 0b11111101; //D1 as Input - DIP switch #2
7
   DDRD |= 0b00000100; //D2 as Output - LED Supply


Du brauchst Kommentare und ein gutes Auge um zu erkennen, welches Bit in 
jeder Zeile eigentlich das relevante ist und wo es daher am eigentlichen 
µC hardwaremässig zu finden ist.
1
#define MOS2_PIN      PA0    // am PORT A
2
#define DIP1_PIN      PA1    // an PORT A
3
#define DIP2_PIN      PD1    // am PORT D
4
#define DIP3_PIN      PD0    // am PORT D
5
#define LED_PIN       PD2    // am PORT D
6
#define POS_VOLT_PIN  PB0    // positive Spannung, Komperator
7
#define NEG_VOLT_PIN  PB1    // negative Spannung, Komperator
8
...
9
10
// Output
11
   DDRA |= ( 1 << MOS2_PIN );
12
   DDRD |= ( 1 << LED_PIN );
13
14
// Input Dip-Switches
15
   DDRA &= ~( 1 << DIP1_PIN );
16
   DDRD &= ~( 1 << DIP2_PIN );
17
   DDRD &= ~( 1 << DIP3_PIN );
18
19
   PORTA |= ( 1 << DIP1_PIN );
20
   PORTD |= ( 1 << DIP2_PIN );
21
   PORTD |= ( 1 << DIP3_PIN );
22
23
// Input Analog Input - Komperator
24
   DDRB &= ~( 1 << POS_VOLT_PIN | 1 << NEG_VOLT_PIN );
25
26
....
27
28
ISR(ANA_COMP_vect)
29
{
30
  PORTD |= ( 1 << LED_PIN );
31
  flag = 1;
32
}
33
34
ISR(TIMER1_COMP1_vect)
35
{
36
  PORTD &= ~( 1 << LED_PIN );
37
  TCCR1B &= ~( 1 << CS12 | 1 << CS11 | 1 << CS10 );
38
}

Mit ein paar #define, mit denen man den Pins Namen gibt, spart man nicht 
nur Kommentare sondern macht auch gleichzeitig den Code lesbarer. Denn 
dann steht da eben

  PORTD |= ( 1 << LED_PIN );

was man als C-Programmierer sofort als: Hier wird ein Pin auf 1 gesetzt 
liest. Welcher Pin? Der Pin an dem die LED hängt.
(Und in dem Fall sollte man für die Port-Namen dann nochmal dasselbe 
machen.

Aber so kriegt man Übersicht in seinen Code. Und dann kann man auch mit 
dem Code arbeiten.

von Peter D. (peda)


Lesenswert?

C ist nicht zeilensensitiv.
Schreibs einfach so:
1
//Analog Comparator
2
  ACSR = 0<<ACIE  //clear the interrupt bit
3
       | 0<<ACD   //power ON analog comparator
4
       | 0<<ACBG  //use AIN0 as positive Input
5
       | 0<<ACIC  //Input Capture disabled
6
       | 0<<ACIS0 //Interrupt Mode (Output Toggle)
7
       | 0<<ACIS1 //Interrupt Mode (Output Toggle)
8
       | 1<<ACIE; //Enable Interrupts again

Athlon N/a schrieb:
> OCR1AH = 0x00; //compare register high
>   OCR1AL = 0x98; //compare register low

Wer soll sowas verstehen?
Hast Du etwa 16 Finger?
1
#define F_CPU   8e6
2
#define blablub (F_CPU / 123.4e3 - 0.5) // schreib die Formel hin,
3
                                        // der Compiler kann besser rechnen als du
4
OCR1A = blablub;

von Karl H. (kbuchegg)


Lesenswert?

Ich würde da
1
   if(flag == 1)
2
    {
3
      cli();
4
      flag = 0;
5
      TIMSK |= 0b00100000; //Timer, Output Compare B Match Interrupt enable  
6
      ACSR &= 0b11110111; //Disable Analog Comparator Interrupts
7
      TCCR1B |= 0b00000101; //start timer/counter with Clock/1024 Prescaler CS12=0, CS11=1, CS10=1
8
      sei();
9
    }

sicherheitshalber vor dem Wiederzulassen der Interrupts auch as ACI Bit 
noch löschen. Nicht das währenddessen ein weiterer Intrerrupt vom 
Komperator aufgelaufen ist, der ein erneutes Triggern des Komperator 
Interrupts auslöst
1
   if(flag == 1)
2
   {
3
     cli();
4
     flag = 0;
5
6
     ACSR &= ~( 1 << ACIE );   // Interrupts disablen
7
     ACSR |= ( 1 << ACI );     // und eventuell noch aufgelaufene Interrupt
8
                               // Anforderungen löschen
9
10
     TIMSK |= ( 1 << OCIE1A );
11
     TCNT1 = 0;
12
     OCR1A = 1432;
13
     TCCR1B |= ( 1 << CS12 ) | ( 1 << CS10 );  // 1024
14
15
     sei();
16
   }



Anstatt
     OCR1A = 1432;
wärs noch besser, wenn du die gewünschte Zeit mittels des 
Timer-Prescalers (den 1024) in Beziehung zur F_CPU setzt. Der Compiler 
rechnet dir den Zahlenwert schon aus, wenn du eine Formel hast (und die 
musst du haben, schliesslich hast du das ja auch mit dem Taschenrechner 
rechnen können) und Zeit, F_CPU und die 1024 in der Formel vorgibst

von Athlon N. (athlon)


Lesenswert?

So danke für die zahlreichen Antworten.
Hier nochmal der etwas besser lesbare Code:
1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3
4
#define MOS2_PIN  PORTA0
5
#define LED_PIN    PD2
6
#define DIP1_PIN  PORTA1
7
#define DIP2_PIN  PD1
8
#define DIP3_PIN  PD0
9
#define ACPOS_PIN  PORTB0
10
#define ACNEG_PIN  PORTB1
11
12
#define F_CPU 1e6
13
14
15
volatile int8_t flag = 0;
16
17
int main(void)
18
{  
19
  //Port Directions
20
  DDRA |= (1<<MOS2_PIN); //Pin as Output - MOS2 Supply
21
  DDRD |= (1<<LED_PIN); //Pin as Output - LED Supply
22
  
23
  DDRA &= ~(1<<DIP1_PIN); //Pin as Input - DIP switch #1
24
  DDRD &= ~(1<<DIP2_PIN); //Pin as Input - DIP switch #2
25
  DDRD &= ~(1<<DIP3_PIN); //Pin as Input - DIP switch #3
26
  
27
  DDRB &= ~(1<<ACPOS_PIN); //Pin as Input - positive Analoginput - AIN0
28
  DDRB &= ~(1<<ACNEG_PIN); //Pin as Input - negative Analoginput - AIN1
29
  
30
  
31
  //Enabling Ports (output) - Set pull Up Resistor (Input)
32
  PORTA &= ~(1<<MOS2_PIN); //MOS2 supply Bit
33
  PORTD &= ~(1<<LED_PIN); //LED Voltage supply
34
  
35
  PORTA &= ~(1<<DIP1_PIN); //deactivate pull Up Resistor - DIP #1
36
  PORTD &= ~(1<<DIP2_PIN); //deactivate pull Up Resistor - DIP #2
37
  PORTD &= ~(1<<DIP3_PIN); //deactivate pull Up Resistor - DIP #3
38
  
39
  PORTB &= ~(1<<ACPOS_PIN); //deactivate pull Up Resistor - AIN0
40
  PORTB &= ~(1<<ACNEG_PIN); //deactivate pull Up Resistor - AIN1
41
    
42
  //Analog Comparator
43
  ACSR &= ~(1<<ACIE); //disable AC Interrupts
44
  ACSR &= ~(1<<ACD); //power ON analog comparator
45
  ACSR &= ~(1<<ACBG); //use AIN0 as positive Input
46
  ACSR |= (1<<ACIE); //Enable Interrupts again
47
    
48
  //16 bit Timer1
49
  TCCR1B &= ~( (1<<CS12) | (1<<CS11) | (1<<CS10)); //Stop Timer/Counter
50
  //Timer/Counter Mode
51
  TCCR1B &= ~(1<<WGM13); 
52
  TCCR1B |= (1<<WGM12); //CTC1 - CTC mode with Top OCR1A
53
  
54
  //Timer/Counter Compare Register
55
  OCR1A = ((F_CPU/1024)*2.5);
56
    
57
  sei(); //Global Interrupts enabled
58
  
59
  
60
    while(1)
61
    {
62
    if(flag == 1)
63
    {
64
      cli();
65
      flag = 0;
66
      TIMSK |= (1<<OCIE1A); //Timer, Output Compare A Match Interrupt enable  
67
      ACSR &= ~(1<<ACIE); //Disable Analog Comparator Interrupts
68
      ACSR &= ~(1<<ACI); //Clear the Interrupt flag
69
      TCCR1B |= ( (1<<CS12) | (1<<CS10)); //start timer/counter with Clock/1024 Prescaler
70
      sei();
71
    }                 
72
    }
73
  
74
  return 0;
75
}
76
77
//Function for activated Interrupt caused by analog comparator
78
ISR(ANA_COMP_vect)
79
{
80
  PORTD |= (1<<LED_PIN); //enable LED
81
  flag = 1;
82
  
83
}
84
85
ISR(TIMER1_COMP1_vect)
86
{
87
  //if(PIND & (1<<PIND1))
88
  
89
  PORTD &= ~(1<<LED_PIN); //disable LED
90
      
91
  TCCR1B &= ~( (1<<CS12) | (1<<CS11) | (1<<CS10)); //Stop Timer/Counter
92
}

Das Problem besteht aber leider immer noch.
Der Interrupt vom AC wird einfach nicht deaktiviert bzw. lässt sich 
nicht nur einmal ausführen.

Woran kann das liegen? :/

Lg

von Karl H. (kbuchegg)


Lesenswert?

>       ACSR &= ~(1<<ACI); //Clear the Interrupt flag


No.
Das hat schon seinen Grund warum ich

     ACSR |= ( 1 << ACI );     // und eventuell noch aufgelaufene 
Interrupt
                               // Anforderungen löschen

geschrieben habe.
Derartige Interrupt Flags werden gelöscht, indem man ein 1 Bit an die 
entsprechende Position im Register schreibt. Das war kein Tippfehler.


Aus dem Datenblatt
1
• Bit 4 – ACI: Analog Comparator Interrupt Flag
2
3
This bit is set by hardware when a comparator output event triggers
4
the interrupt mode defined by ACIS1 and ACIS0. The Analog Comparator
5
interrupt routine is executed if the ACIE bit is set and the I-bit in
6
SREG is set. ACI is cleared by hardware when executing the corresponding
7
interrupt handling vector. Alternatively, ACI is cleared by writing a
8
logic one to the flag.

Beachte den letzten Satz!

von Thomas E. (thomase)


Lesenswert?

Athlon N/a schrieb:
> ACSR &= ~(1<<ACI); //Clear the Interrupt flag
1. wird das Flag so nicht gelöscht. Sonden indem man da eine 1 
reinschreibt. Aber das nur am Rande.

Athlon N/a schrieb:
> ISR(TIMER1_COMP1_vect)

2. Stürzt dein Programm hier ab. D.h. nicht hier sondern beim Sprung in 
die nicht vorhandene Timer-ISR.

Der Interrupt-Vektor heisst TIMER1_COMPA_vect.

Das hat aber auch Mecker vom Compiler gegeben. Warnings sind nicht zum 
ignorieren da!

mfg.

von Athlon N. (athlon)


Lesenswert?

Ah tatsächlich, danke!

Das Problem besteht leider immer noch.
Komisch.. In die if Anweisung wird ja gesprungen, sonst würde der Timer 
nicht gestartet werden.
Gibt es noch eine andere Interrupteinstellung für den AC die ich 
übersehn hab?

Ich hab auch schon versucht den AC mittels
1
ACSR |= (1<<ACD);

zu deaktiveren. Das nützt aber auch nichts.

von Karl H. (kbuchegg)


Lesenswert?

Thomas Eckmann schrieb:

>> ISR(TIMER1_COMP1_vect)
>

> 2. Stürzt dein Programm hier ab. D.h. nicht hier sondern beim Sprung in
> die nicht vorhandene Timer-ISR.
>
> Der Interrupt-Vektor heisst TIMER1_COMPA_vect.

richtig, der ist mir im Zuge des Durcharbeitens des Codes auch schon 
aufgefallen, hab aber dann vergessen zu kontrollieren, ob beim Tiny2313 
der Vektor vielleicht wirklich anders heißt, denn ...

> Das hat aber auch Mecker vom Compiler gegeben. Warnings sind nicht zum
> ignorieren da!

von Athlon N. (athlon)


Lesenswert?

Thomas Eckmann schrieb:
> Athlon N/a schrieb:
>> ISR(TIMER1_COMP1_vect)
>
> 2. Stürzt dein Programm hier ab. D.h. nicht hier sondern beim Sprung in
> die nicht vorhandene Timer-ISR.
>
> Der Interrupt-Vektor heisst TIMER1_COMPA_vect.
>
> Das hat aber auch Mecker vom Compiler gegeben. Warnings sind nicht zum
> ignorieren da!

Danke!!! Das wars. Hab in der falschen Bibliothek nachgesehen -.-

Warnings hat er leider nicht ausgegeben :/. Hier der Output:
1
------ Build started: Project: Licht, Configuration: Debug AVR ------
2
Build started.
3
Project "Licht.cproj" (default targets):
4
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
5
Target "CoreBuild" in file "D:\Programme\Atmel\Atmel Studio 6.0\Vs\Compiler.targets" from project "D:\Projects and Stuff\Projects\AtmelProjects\Licht\Licht\Licht.cproj" (target "Build" depends on it):
6
  Task "RunCompilerTask"
7
    D:\Programme\Atmel\Atmel Studio 6.0\make\make.exe all 
8
    make: Nothing to be done for `all'.
9
  Done executing task "RunCompilerTask".
10
  Task "RunOutputFileVerifyTask"
11
        Program Memory Usage   :  262 bytes   12,8 % Full
12
        Data Memory Usage     :  1 bytes   0,8 % Full
13
  Done executing task "RunOutputFileVerifyTask".
14
Done building target "CoreBuild" in project "Licht.cproj".
15
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
16
Target "Build" in file "D:\Programme\Atmel\Atmel Studio 6.0\Vs\Avr.common.targets" from project "D:\Projects and Stuff\Projects\AtmelProjects\Licht\Licht\Licht.cproj" (entry point):
17
Done building target "Build" in project "Licht.cproj".
18
Done building project "Licht.cproj".
19
20
Build succeeded.
21
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

Sind die Warnings defaultmäßig deaktiviert??

von Karl H. (kbuchegg)


Lesenswert?

Athlon N/a schrieb:

> Warnings hat er leider nicht ausgegeben :/. Hier der Output:


LOL
1
  Task "RunCompilerTask"
2
    D:\Programme\Atmel\Atmel Studio 6.0\make\make.exe all 
3
    make: Nothing to be done for `all'.

Nothin to be done  - es gibt nichts zu tun.
Verändere mal deinen Code ein wenig, damit es was zu tun gibt. 
Leerzeichen rein/raus reicht schon.

> Sind die Warnings defaultmäßig deaktiviert??

EIn -Wall in den Compiler-flags hat noch nie geschadet.

von Athlon N. (athlon)


Lesenswert?

Hab grad gesehn dass er die Warnung eh ausgibt -.-

Hätt mir gedacht, dass die im Output Log etwas mehr hervorgehoben werden 
würde. Nun gut wieder etwas gscheider gworden.

Das ist vorerst mal alles, danke euch!!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> EIn -Wall in den Compiler-flags hat noch nie geschadet.

-Wall -Wextra

von Ingo (Gast)


Lesenswert?

Ich mach immer -Werror an, so geht der Code mit einer Warnung nicht zu 
kompilieren

von Athlon N. (athlon)


Lesenswert?

Jörg Wunsch schrieb:
> Karl Heinz Buchegger schrieb:
>> EIn -Wall in den Compiler-flags hat noch nie geschadet.
>
> -Wall -Wextra

Danke euch, was macht -Wextra? Konnte es in der Doku nicht finden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Athlon N/a schrieb:

> Danke euch, was macht -Wextra? Konnte es in der Doku nicht finden.

Du solltest natürlich die GCC-Doku lesen, nicht die für deine
Brotschneidemaschine. ;-)

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-W-262

von Athlon N. (athlon)


Lesenswert?

Jörg Wunsch schrieb:
> Athlon N/a schrieb:
>
>> Danke euch, was macht -Wextra? Konnte es in der Doku nicht finden.
>
> Du solltest natürlich die GCC-Doku lesen, nicht die für deine
> Brotschneidemaschine. ;-)
>
> http://gcc.gnu.org/onlinedocs/gcc/Warning-Options....

Aja tatsächlich :D.
Habs jetz in Atmel Studio unter -W gefunden. -Wextra habn sie dort wohl 
abgeschafft.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Athlon N/a schrieb:
> -Wextra habn sie dort wohl
> abgeschafft.

Nein, das ist bei denen nur noch nicht angekommen.  Gibt's ja auch erst
seit ca. 10 Jahren (in ChangeLog-2003 finde ich es auf die Schnelle das
erste Mal erwähnt).

von apr (Gast)


Lesenswert?

Die wirklich spannende Frage lautet ja: Warum macht -Wall nicht all?

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.