Forum: Mikrocontroller und Digitale Elektronik Gesetztes Bit bleibt nicht aktiv. ISR löscht Bit.


von Alexander G. (illness)


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

von Achim M. (minifloat)


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

von Alexander G. (illness)


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);

.....

von Achim M. (minifloat)


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.

von Simon K. (simon) Benutzerseite


Lesenswert?

> atomische
atomare?

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.