interrupt nutzen

OP #6513674
Lesenswert?

Hallo,

ich bin ziemlich neu in dem Thema und wollte eine 7 Segment anzeige dazu 
bringen, von 0 hochzuzählen mit einer Pause von jeweils 1000ms zwischen 
dem Wechsel.
Jedoch will ich keine Delay Funktion nutzen, sondern die Interrupts 
nutzen.
Ich habe jetzt einen Code geschrieben, jedoch funktioniert dieser nicht.

Die Bitmasken sind aufjedenfall richtig. Beim ausführen sehe ich 
garnichts, weshalb ich denke dass meine Interrupt Routine garnicht 
aufgerufen wird.

Edit: Es handelt sich um einen AtMega328PB
1
#include <avr/interrupt.h>
2
#include <avr/io.h> 
3

4

5

6
uint8_t PC_Bitmaske[10] = {0b00111,0b01111,0b00111,0b00111,0b01111,0b10111,0b10111,0b00111,0b00111,0b00111};
7
uint8_t PD_Bitmaske[10] = {0b11000011,0b11111011,0b10100111,0b10110011,0b10011011,0b10010011,0b10000011,0b11011011,0b10000011,0b10010011};
8

9
  
10
uint8_t timer_counter = 0;
11
uint8_t number = 0;
12

13

14
ISR(TIMER0_OVF_vect) 
15
  {
16
  
17
  number++;  
18
  
19
  while(timer_counter < 100){
20
    
21
    timer_counter++;
22
    
23
  }
24
    
25
  PORTC = PC_Bitmaske[number];    // 7 Segmentanzeige des Zählwerts (Ziffer) 
26
  PORTD = PD_Bitmaske[number];  
27
    
28
  if(number == 9){    // Rotierenden Ziffernwert für Anzeige 0..9 iterieren (inkrementiern, prüfen, bei Überlauf zurücksetzen)
29
  number = -1;
30
  }
31
    
32
  }
33

34

35
int main(void)
36
{
37
  // 7 Segment Anzeige initialisieren (Alle LEDs aus, restliche Bits passend für Input und Tristate)
38
  DDRC = 0x18;
39
  PORTC = 0xFF;
40
  DDRD = 0x7C;
41
  PORTD = 0x7C; 
42
  
43
  // Timer/Counter 0 initialisieren: CTC Modus, Prescaler 1/1024, Interrupt-Intervall 10 ms
44
  TCCR0A = (1<<WGM01); 
45
  TCCR0B =    (1<<CS02)|(1<<CS00) ; 
46
  OCR0A = 156;
47
  TIMSK0 = 0b00000010; 
48
  //Interrupts global freigeben
49
  sei();
50
  
51
  
52
    while (1) 
53
    {
54
  
55
    }
Gast #6513730
Lesenswert?

1
while(timer_counter < 100){
2
    
3
    timer_counter++;
4
    
5
  }

Was soll das? Das zählt im ersten Interrupt einmal bis 100 und verweilt 
dann da fröhlich. Wenn du die 10ms zählen willst um auf 1s zu kommen, 
solltest du das anders machen.

Und du benutzt einen Capturewert und rufst den Overflowvector auf.
Gast #6513739
Lesenswert?

1
#include <avr/interrupt.h>
2
#include <avr/io.h> 
3

4

5

6
uint8_t PC_Bitmaske[10] = {0b00111,0b01111,0b00111,0b00111,0b01111,0b10111,0b10111,0b00111,0b00111,0b00111};
7
uint8_t PD_Bitmaske[10] = {0b11000011,0b11111011,0b10100111,0b10110011,0b10011011,0b10010011,0b10000011,0b11011011,0b10000011,0b10010011};
8

9
  
10
volatile uint8_t timer_counter = 0;
11

12

13
ISR(TIMER0_COMPA_vect){
14
  uint8_t number;
15
  timer_counter += 10; //10ms vergangen
16
  if(timer_counter == 10000) //nach 10s
17
    timer_counter = 0;
18
    
19
  number = (timer_counter - timer_counter%1000)/1000;  
20
  PORTC = PC_Bitmaske[number];    // 7 Segmentanzeige des Zählwerts (Ziffer) 
21
  PORTD = PD_Bitmaske[number];  
22
  
23
 }
24

25

26
int main(){
27
  // 7 Segment Anzeige initialisieren (Alle LEDs aus, restliche Bits passend für Input und Tristate)
28
  DDRC = 0x18;
29
    PORTC = 0xFF;
30
   DDRD = 0x7C;
31
    PORTD = 0x7C; 
32
  
33
    // Timer/Counter 0 initialisieren: CTC Modus, Prescaler 1/1024, Interrupt-Intervall 10 ms
34
    TCCR0A = (1<<WGM01); 
35
    TCCR0B =    (1<<CS02)|(1<<CS00) ; 
36
    OCR0A = 156;
37
    TIMSK0 = 0b00000010; 
38
    //Interrupts global freigeben
39
    sei();
40
 
41
    while (1) 
42
    {
43
  
44
    }
45

46

47
}



probier mal das
#6513752
Lesenswert?

Jürgen V. schrieb:
> Hallo,
>
> ich bin ziemlich neu in dem Thema und wollte eine 7 Segment anzeige dazu
> bringen, von 0 hochzuzählen mit einer Pause von jeweils 1000ms zwischen
> dem Wechsel.
> Jedoch will ich keine Delay Funktion nutzen, sondern die Interrupts
> nutzen.

Prnzipiell richtig.

> Ich habe jetzt einen Code geschrieben, jedoch funktioniert dieser nicht.

Das oft der Fall ;-)

> Die Bitmasken sind aufjedenfall richtig. Beim ausführen sehe ich
> garnichts, weshalb ich denke dass meine Interrupt Routine garnicht
> aufgerufen wird.

Du hast einige grundlegende Dinge beim Thema Interrupt noch nicht 
verstanden. Lies den Artikel Interrput.
1
 while(timer_counter < 100){
2
    
3
    timer_counter++;
4
    
5
  }

Sowas ist sinnlos und hat in einer ISR nix zu suchen.

Das Multiplexen bzw. die Anzeige der Zahl macht man sinnvollerweise in 
der ISR, den Rest außerhalb. Für das einfache Beispiel kann man aber 
auch alles in der ISR machen. Siehe Anhang.

Dein wesentlicher Fehler ist der falsche Interrupt. Im CTC-Modus wird 
der Overflow praktisch NIE ausgelöst. Bei CTC muss man den COMPA nutzen.
Angehängte Dateien:
Gast #6513799
Lesenswert?

#include <avr/interrupt.h>
#include <avr/io.h>

volatile uint8_t timer_counter = 0;

ISR(TIMER0_COMPA_vect){
  timer_counter += 10; //10ms vergangen
  if(timer_counter == 10000) //nach 10s
    timer_counter = 0;
 }

int main(){

  uint8_t PC_Bitmaske[10] = 
{0b00111,0b01111,0b00111,0b00111,0b01111,0b10111,0b10111,0b00111,0b00111 
,0b00111};
  uint8_t PD_Bitmaske[10] = 
{0b11000011,0b11111011,0b10100111,0b10110011,0b10011011,0b10010011,0b100 
00011,0b11011011,0b10000011,0b10010011};
    // 7 Segment Anzeige initialisieren (Alle LEDs aus, restliche Bits 
passend für Input und Tristate)
    DDRC = 0x18;
  PORTC = 0xFF;
  DDRD = 0x7C;
  PORTD = 0x7C;

    // Timer/Counter 0 initialisieren: CTC Modus, Prescaler 1/1024, 
Interrupt-Intervall 10 ms
    TCCR0A = (1<<WGM01);
    TCCR0B =    (1<<CS02)|(1<<CS00) ;
    OCR0A = 156;
    TIMSK0 = 0b00000010;
    //Interrupts global freigeben
    sei();

    while (1)
    {
  uint8_t number;
  number = (timer_counter - timer_counter%1000)/1000;
    PORTC = PC_Bitmaske[number];    // 7 Segmentanzeige des Zählwerts 
(Ziffer)
    PORTD = PD_Bitmaske[number];
    }
}


So ist es noch n ticken schöner, sofern die Anzeige asynchron umschalten 
darf.
OP #6513895
Lesenswert?

Ich habe mir das Thema noch einmal neu angeschaut mit dem Interrupt und 
gemerkt dass ich die Funktion nicht richtig verstanden habe.
Jetzt habe ich das Thema verstanden und meinen Code verbessert. Jetzt 
klappt es auch mit dem hochzählen!
1
ISR(TIMER0_COMPA_vect)
2
  {
3
        
4
    if(timer_counter<100)
5
      {
6
        timer_counter++;
7
      } 
8
    
9
    else
10
    {
11
      timer_counter = 0;
12
      
13
      number++;  
14
      
15
      if(number == 10)
16
      {    
17
        number = 0;
18
      }
19
    }
20
    
21
  PORTC = PC_Bitmaske[number];    // 7 Segmentanzeige des Zählwerts (Ziffer) 
22
  PORTD = PD_Bitmaske[number];  
23
    
24
  
25
  }

als nächstes versuche ich mal ein numpad zu benutzen. wünscht mir glück 
:D

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