Gesetztes Bit bleibt nicht aktiv. ISR löscht Bit.

#2672896
Lesenswert?

Hi, schon wieder ein Problem was mich meine Berven kostet. Der Tiny 
macht mich ech zu schaffen....

Problem: in der main schleife setze ich ein bit, dieses wird aber sofort 
wieder zurück gesetzt. die led an dem pin blinkt nur kurz auf.
1
// Countdown 199 - 0 auf TOT-4301 (2,5 Stelliges 7-Segment von Pollin) 
2
// ATtiny2313
3

4
#include <avr/io.h>
5
#define  F_CPU 1000000UL 
6
#include <stdio.h>
7
#include <util/delay.h>
8
#include <avr/interrupt.h>
9

10
#define SETBIT(ADRESS, BIT) (ADRESS |=(1<<BIT))      //Makro zum Setzen eines Bits
11
#define CLEARBIT(ADRESS, BIT) (ADRESS &=~(1<<BIT))   //Makro zum Loeschen eines Bits
12
#define CHECKBIT(ADRESS, BIT) (ADRESS &(1<<BIT))     //Makro zum Pruefen eines Bits
13

14
volatile int leerlauf;
15
volatile unsigned int count =0;
16
volatile unsigned int mpx =0;
17

18
volatile unsigned char seg7[]={63,6,91,79,102,109,125,7,127,111};
19
volatile unsigned int zeit;
20
volatile unsigned char merker=0;
21
volatile unsigned char spalte=1;
22
volatile unsigned char z1;
23
char digit[];
24

25
struct zerlegung
26
{
27
  int zahl;
28
  int var;
29
  int zehner;
30
  int hunderter;
31
  int tausender;
32
  int zehntausender;
33
};
34

35
struct zerlegung ziffer;
36

37

38
ISR(TIMER0_OVF_vect)
39
{
40
    TCNT0 = 150; 
41
               
42
    count++;
43
  mpx++;
44

45
  if(mpx==1)  // Multiplexer
46
  {
47
    merker=0;
48

49
    if(spalte==1)
50
    {
51
      CLEARBIT(PIND,PIND1);
52
      SETBIT(PIND,PIND0);
53
      
54
      PORTB=~seg7[digit[1]] + z1;
55
      spalte=2;
56
      merker=1;
57
    }
58

59
    if(spalte==2 & merker==0)
60
    {
61
      CLEARBIT(PIND,PIND0);
62
      SETBIT(PIND,PIND1);
63
      
64
      
65
      PORTB =~seg7[digit[0]] + z1;
66
      spalte=1;
67
      merker=0;
68
    }          
69
  }
70
  if(mpx==1) mpx=0;    
71

72
}
73

74
void init(void)
75

76
{
77
  DDRA=0xff;
78
  DDRB=0xff;          // -> PORTB 0-6 = 7-Segment a-f | PORTB 7 = halbe stelle
79
  DDRD=0b11100011 ;       // -> PD0 -> Stelle 1, PD1 -> Stelle 2  
80
                // -> PD 5:7 -> Taster
81
                  
82
  TCCR0B = 0x02;        // Timerstart
83
    TCNT0 = 150;            // Startwert nachladen, 0xFA
84
                      // 250* 64us=16ms bis Overflow
85
      
86
  SREG = (1<<7);           // Allgemeine Interruptfreigabe;
87

88
    TIMSK=(1<<TOIE0);       // Freigabe Timer0 Iterrupt    
89
}  
90

91

92
int main(void)
93
{
94
  zeit=124;
95
  init();  
96

97
    while(1)
98
  {    
99
    if(zeit<=99) z1 = 0; 
100
    if(zeit>=100) z1 = 128; 
101

102
    if((PIND & 0b00000100) == 0b00000100)
103
    {
104
    zeit=30;    
105
    }
106
      
107
    if(count >= 500)              
108
      {    
109
      count=0;
110
      zeit--;
111

112

113
      // Teilt eine 5 Stellige Zahl in einzelne Stellen auf
114
      // Ausgabe in der Variablen "digit[]"
115
      // digit[4] -> Erste Stelle
116
      // digit[0] -> Letzte Stelle
117

118
      ziffer.zahl = zeit;
119

120
      ziffer.zehner       = ziffer.zahl / 10;
121
      ziffer.hunderter     = ziffer.zahl / 100;
122
      ziffer.tausender     = ziffer.zahl / 1000;
123
      ziffer.zehntausender   = ziffer.zahl / 10000;
124

125
      digit[4] = ziffer.zehntausender;
126

127
      ziffer.var = ziffer.zehntausender * 10;
128
      digit[3] = ziffer.tausender - ziffer.var;
129

130
      ziffer.var = ziffer.tausender * 10;
131
      digit[2] = ziffer.hunderter - ziffer.var;
132

133
      ziffer.var = ziffer.hunderter * 10;
134
      digit[1] = ziffer.zehner - ziffer.var;
135

136
      ziffer.var = ziffer.zehner * 10;
137
      digit[0] = ziffer.zahl - ziffer.var;
138

139

140
      if(zeit>0) PORTD |= (1 << 5);   <----------------- HIER, das Bit will nicht bleiben
141
            
142
    }      
143
        
144
    leerlauf++;  
145
  }
146
   
147
}

bei anderen µCs ist mir das noch nicht passiert....

gruß Alex
#2672919
Lesenswert?

Das ist so bei den AVRs, dass sie das der entsprechenden ISR zugehörige 
Flag löschen. Aber das meinst du vermutlich garnicht.

Das Array "digit[]" sollte auch volatile sein, da schließlich in der ISR 
darauf zugegriffen wird. Dann solltest du die Größe von digit auf ein 
auf jeden Fall ausreichendes Maß festnageln; auf dem µC gibt es mit 
dieser Umgebung keine dynamische Speicherzuweisung und in der reinen 
Essenz der Programmiersprache C geht das auch nicht auf diese Art und 
Weise.

mfg mf
#2672923
Lesenswert?

ja, das mit dem volatile ist mir noch nicht ganz klar...bei meinem µC 
Board mit nem AT90CAN128 hab ich das noch nie gebraucht....

hab den fehler aber schon gefunden:

ich schreibe in der ISR:

CLEARBIT(PIND,PIND1);
SETBIT(PIND,PIND0);

das muss so sein:

CLEARBIT(PORTD,PORTD1);
SETBIT(PORTD,PORTD0);

.....
#2672938
Lesenswert?

Alexander G. schrieb:
> ja, das mit dem volatile ist mir noch nicht ganz klar

"volatile" ist ein Schlüsselwort. Flüchtig. Damit Teilst du dem Compiler 
mit, dass sich an der Variable auch zu Zeiten, zu denen ers nicht 
"sieht", etwas ändern könnte oder Fremdzugriffe stattfinden. Dies 
betrifft Schreiben und auch Lesen.

Hier zum Beispiel wird in der "main()" viel an "digit[]" rumgeorgelt. In 
der ISR sehe ich aber auch noch einen Zugriff. Gerade der GCC ist dafür 
bekannt, im Schreiben von Variableninhalten von Registern zurück in den 
RAM je nach Optimierungsstufe extrem faul zu sein. Es wird dann zum 
spätestmöglichen Zeitpunkt; manchmal auch garnicht zurückgespeichert.

Mit "volatile" behandelt der Compiler die Variable wie eine heiße 
Kartoffel. Idealerweise gibt es dazu beim AVR über Pointeradressierung 
eine elegante Methode. Das löst der Compiler dann so auf. 
16Bit-Operationen sind in der Prozessorarchitektur zum Glück als 
atomische(=nicht unterbrechbare) Operationen realisiert. Also einfach an 
die Kartoffel denken.
mfg mf

Ja, auf PINx-Register Schreiben ist Toggeln des PORTx-Registers an den 
Stellen, wo Bits gesetzt sind. Das ist auch erst seit ein paar Jahren 
so. Hab aber auch schon elegantere Lösungen dazu gesehen. Vorteil ist, 
dass man sich so ein paar Zyklen spart.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren