Forum: Mikrocontroller und Digitale Elektronik LED Matrix (AtMega2560)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Lehner P. (gruffi)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo µC.net Gemeinde,
nach Jahren des mitlesens und ausmärzen meiner Fehler in meinen 
Schaltungen, mithilfe der Posts in eurem Forum, habe ich mich nun 
dennoch angemeldet, da ich bei meinem aktuellen Projekt, einer 3x5 LED 
Matrix im Multiplexbetrieb, wohl einen Fehler drinnen habe, welchen ich 
nicht,... finde?

Trotzdem ich einige der Themen mir durchgelesen habe, auf welche auch 
öfters verwiesen wird bei diesem LED Matrix Thema, kann ich meinen 
Fehler einfach nicht finden.
Nun zu meinem Projekt / Problem:

Ich arbeite mit einem Arduino Mega2560 r3 Bord(µC ist natürlich der 
AtMega2560).
Als Programmierumgebung benutze ich das AVR Studio (Atmel Studio 6.1).

Ich habe mir meine Schaltung nach dem Berechnen der Vorwiderstände der 
LED, Basistransistorwid,... in Eagle gezeichnet und sie anschließend mal 
gelötet, as usual.
(siehe Anhang LED Matrix Eagle sch)

Als SRG nutze ich einen normalen 8bit Zähler (weil ich den zuhause 
hatte)
Die Reihen schalte ich mit PNP (Q1 bis Q5).
Die Spalten mit NPN (T1 bis T3).
T4 dient als Schalter um beim Hochzählen des Zählers die LED ausschalten 
zu können.

Das Bord sowie die Schaltung versorge ich beim Programmieren über USB.
Beim Normalen Betrieb, um mir um die Versorgungsleistung keine Gedanken 
machen zu müssen, über mein Netzgerät und die Strombuchse am Bord.

Die Schaltung funktioniert soweit.
Meines erachtens, ist der Hund wohl in meinem C-Code begraben...

Bevor ich hier lang und breit meinen Code poste wollte ich fragen wie es 
üblich bzw sinnvoll ist, ein Hauptprogramm (LED_Matrix) und eine eigene 
Header+Source Datei (LED_Matrix_MUX.c & .h) hier im Forum zu posten? 
(jeweils ca 150 bis 200 Zeilen)

Zum Code:
Zum Testen der Matrix habe ich anfangs einige "Muster" definiert, welche 
im ca 5 Sekundentakt durchlaufen sollten. Dies hat mit meinem Code zum 
Multiplexen auch funktioniert, allerdings nur mit einem "_delay_ms(1)".

Es ist mir klar, dass in den meisten Fällen ein "delay" eine schlechte 
Art zu programmieren ist, ist zum ausprobieren aber recht praktisch. 
Darum wollte ich anschließend das "delay" durch eine Interrupt Routine 
ersetzen.
Gesagt getan. Timer initialisiert, ISR usw angelegt.

Doch nun funktioniert der Teil mit dem Multiplexen nicht mehr, der Code 
wurde natürlich mit dem Umstellen vom "delay" auf den Timer/ISR 
angepasst.
Ich vermute, dass hier der Fehler in meinem Programm ist.
Bisher hatte ich noch nichts mit Timern zu tun, vlt liegt also das 
Problem in dessen Config oder daran wie ich die ISR verwende.

Mit meiner ISR setze ich meine eigene Interrupt Variable und zähle eine 
Variable zum "Musterwechsel" hoch.
Meine eigene Interrupt Variable nutze ich in meinem Hauptprogramm 
(Globale Variable) und in meiner "LED_Matrix_MUX".
Hier eine Frage:
Kann ich eine Varibale, welche im Hauptprogramm als Globale Variable 
angelegt ist, in meiner LED_Matrix_MUX.c / .h mittels "extern" ebenfalls 
verwenden?

Hierzu sei noch gesagt, dass ich den Timer (genauergesagt die ISR) auch 
zum bestimmen der Zeit nutze, wann das Muster gewechselt werden sollte 
und das funktioniert.


Als Info noch, was beim Multiplexen passieren sollte und was bei "delay" 
und "timer/ISR" wirklich passiert.

Meine Matrix:
LED's
A | B | C
D | E | F
G | H | I
J | K | L
M | N | O

Hier die "Matrix", welche ein "X" darstellen sollte
(Led welche nicht leuchten sollten entfallen)

A | - | C
D | - | F
- | H | -
J | - | L
M | - | O

Matrix mit "delay"
(alter Code)

A | - | C
D | - | F
- | H | -
J | - | L
M | - | O

Matrix mit "Timer/ISR"
(angepasster Code)

A | B | C
D | E | F
- | - | -
J | K | L
M | N | O

Den C Code poste ich, sobald ich die Gepflogenheiten diesbezüglich hier 
im Forum erfahren habe ;-)

Danke schonmal für die Mühe, mir helfen zu wollen ;-)

Beste Grüße Phil

: Bearbeitet durch User
von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Lehner P. schrieb:
> ausmärzen
ausmerzen.
Auch wenn es evtl tatsächlich vom März kommt, in den die schlechtesten 
Lämmer zu Lammbraten umfunktioniert wurden...

Lehner P. schrieb:
> (siehe Anhang LED Matrix Eagle sch)
Bei den Q1...5 ist C und E vertauscht

Lehner P. schrieb:
> Kann ich eine Varibale, welche im Hauptprogramm als Globale Variable
> angelegt ist, in meiner LED_Matrix_MUX.c / .h mittels "extern" ebenfalls
> verwenden?
Wo "im Hauptprogramm"?
BTW: wenn dein Programm nicht funktioniert dann solltest das mal 
anhängen.

von Marc V. (Firma: Vescomp) (logarithmus)


Bewertung
0 lesenswert
nicht lesenswert
Lehner P. schrieb:
> Matrix mit "Timer/ISR"
> (angepasster Code)
>
> A | B | C
> D | E | F
> - | - | -
> J | K | L
> M | N | O

> Den C Code poste ich, sobald ich die Gepflogenheiten diesbezüglich hier
> im Forum erfahren habe ;-)

 Nicht nötig, der Zeiger für Reihen wird richtig angesteuert, aber der
 Zeiger für Spalten wahrscheinlich nicht.

von Lehner P. (gruffi)


Bewertung
0 lesenswert
nicht lesenswert
@ Lothar Miller
Wer Rechtschreibfehler findet, darf sie behalten, aber Danke Lothar 
Miller ;-)

Ja hatte bei den PNP schon so meine zweifel, aber da die Matrix erst 
funktionierte, dachte ich wirds schon passen. Werde das ansonsten 
ändern.

Ich habe in meinem Main.c die Variable "short InterruptT0var" global 
angelegt.
In meiner Matrix.c wollte ich diese Variable ebenso verwenden. Dort habe 
ich sie mit "extern short InterruptT0var" angelegt (ebenso im 
zugehörigen .h File).
Kann ich so auf den Wert dieser Variable auch in einem Sourcefile 
zugreifen?

Oder würde dies nur funktionieren wenn ich diesen Wert übergebe (Bspw 
mit einem Pointer)?

@Marc Vesely

Hab mich bei meinem ersten Post vertan, es handelt sich um ein H nicht 
um ein X... sry
werde das noch editieren.

Das Problem der Matrix liegt meines erachtens daran, dass in meinem 
Aufruf für das Multiplexen, nur der erste Wert angenommen wird.

---------

Ich schreib hier mal meinen Code rein, sollte es nicht passen den Code 
so anzufügen, so sagt mir bitte wie es hier im Forum richtig gemacht 
wird.

In meinem Source File verwende ich in der switch-case einmal ein 
weiteres switch-case und anschließend eine if-else if.
Begründung:
Um auszuschließen, dass es sich hierbei um den Fehler handelt, jedoch 
habe ich bei beiden das gleiche Problem, dass eben in der "inneren 
switch-case(casecount)" immer nur der erste Aufruf ausgeführt wird...
Liegt dies daran, das meine Variable "InterruptT0var" von mir falsch 
verwendet / angelegt wird?


Hier der Großteil des Codes
(die USART Befehle müsst ihr nicht beachten, die hauen hin ;-) )

Hauptprogramm (main)
1
#include <avr/io.h>      //für PORT,...
2
#include <util/delay.h>    //für delay (sollte ersetzt werden)
3
#include <avr/interrupt.h>  //für interruptfunktionen
4
#include "usart.h"      //für send & recive //für eine ausgabe über putty
5
#include "LED_Matrix_3x5_MUX.h"  //für eigene MUX Funktionen
6
7
8
//Für Interrupskonfig
9
#ifndef TIMER0_OVF_vect // Für ältere WinAVR Versionen z.B. WinAVR-20071221
10
#define TIMER0_OVF_vect TIMER0_OVF0_vect
11
#endif
12
13
//Globale Variablen
14
short interruptT0var=0, autocount=0;
15
16
/*
17
*  Der Overflow Interrupt Handler wird aufgerufen, wenn TCNT0 von 255 auf 0 wechselt (256 Schritte),
18
*  Interrupt Aktion alle   (16000000/64)/256 Hz = 976,6 Hz   bzw.   1/976,6 s = 1,024 ms     
19
*/
20
ISR (TIMER0_OVF_vect)
21
{
22
  interruptT0var=1;    //Setzen einer eigenen Iterrupvariable
23
  autocount++;      //Autocount für Musterwechsel
24
  TCNT0 &= 0b00000000;  //Rücksetzen des Timer Zählregisters
25
  TIFR0 = (1<<TOV0);    //Löschen des Interrupt Flag Overflow Timer 0
26
}
27
28
/* 
29
*  getkey gibt folgendes zurück:
30
*  0, wenn keine Taste gedrückt ist
31
*  1, wenn die Taste gedrückt ist
32
*/
33
int getkey(void)
34
{
35
  if (PINC & (1<<0) )
36
  {
37
    return 0;
38
  }
39
  else
40
  {
41
    return 1;
42
  }
43
}
44
45
46
int main(void)
47
{
48
  // Timer 0 konfigurieren
49
  TCCR0B |= 0b00000011;  // Prescaler none(001), 8(010), 64(011), 256(100), 1024(101)
50
              // 16MHz/Prescaler/256= 7813Hz => 0,13ms
51
  
52
  // Overflow Interrupt erlauben
53
  TIMSK0 |= (1<<TOIE0);
54
  
55
  // Global Interrupts aktivieren
56
  sei();
57
  
58
  //Taster auf PORTC
59
  DDRC=0x00;    //PortC als Eingang
60
  PORTC=0x01;    //PullUp von Pin 0 eingeschaltet
61
  
62
  //Leds auf PORTA
63
  DDRA=0xFF;  //PORTA als Ausgang definieren
64
  
65
  /*
66
  *  Zähler Info
67
  *  PORTA0 = Reset ->  a high voltage level on the MR
68
  *            line resets all counters to their zero state
69
  *  
70
  *  PORTA1 = Count ->  All counter stages are master-slave flip-flops. The
71
  *            state of the stage advances one count on the negative
72
  *            transition of each clock pulse;
73
  */
74
  
75
  //Rücksetzen des Zählers
76
  PORTA=0b00000001;
77
  PORTA=0b00000000;
78
  
79
  //Definition der Variablen
80
  
81
  char eingabemuster [10] = {0};
82
  int short zahlmuster=0, taster=0, progwechsel=0;
83
  long entprellt=0;
84
    
85
  //Initialisierung der seriellen Ausgabe
86
  usart0Init(USART_BAUDRATE_9600,USART_NO_PARITY,USART_1_STOP_BIT);
87
  
88
  //fertigen eines string um ihn mit sendstring ausgeben zu können
89
  //snprintf(text, 50,"\n\rUmgewandeltes Zeichen: (ASCII CODE) %d \n\r", zahl7s)
90
  
91
  //Beginn des eig Programs  
92
  while(1)  //Ausgabeinfo
93
  {
94
    
95
    //Ausgabe welche Muster im Sourcefile hinterlegt sind
96
    VorhandeneMuster();
97
    
98
    //Abfrage des gewünschten Musters
99
    /*
100
    *do
101
    *{
102
    *usart0ReceiveStringBlocking(eingabemuster,10);
103
    *zahlmuster=atoi(eingabemuster);
104
    *} while ((zahlmuster<0||zahlmuster>8));
105
    */
106
  
107
    //Ausgabe Info
108
    usart0SendStringBlocking("\n\rMit jedem Tastendruck, wird ein neues Muster gezeigt\n\r");
109
    
110
    //Hauptprogram
111
    while(1)
112
    {
113
      //Aufruf der LEDMatrix Ansteuerung
114
      MatrixMux(zahlmuster);
115
      
116
      //nach Programmwechsel Entprellt und progwechsel rücksetzten 
117
      if (progwechsel>0)
118
      {
119
        entprellt=0;  //Für gleiche Tasterzeiten
120
        progwechsel=0;
121
      }
122
      
123
      //Abfrage des Taster (mit nachfolgender Entprellung)
124
      taster=getkey();
125
      if (taster==1)
126
      {
127
        entprellt++;
128
      }
129
      
130
      //Wenn Taster eine gewisse Zeit (entprellt mal) gedrückt ist == entprellt
131
      if (entprellt>=40000)  //2,5ms+Prellen
132
      {
133
        zahlmuster++;  //Muster hochzählen
134
        entprellt=0;  //Entprellen rücksetzen
135
        progwechsel++;  //Programmwechsel vorgeben
136
      } 
137
      
138
      //Autocount zum automatischen wechseln des Musters
139
      if (autocount==5000)  //Bei ISR alle 1,024ms = ca 5 Sekunden
140
      {
141
        zahlmuster++;
142
        autocount=0;
143
      }
144
      
145
      //Mustercounter nach Durchlauf wieder zurücksetzen
146
      if (zahlmuster>8)
147
      {
148
        zahlmuster=0;
149
      }
150
      
151
    }  //while Hauptprogam
152
            
153
  }  //while AusgabeInfo  
154
155
}  //main


Hier mein Sourcefile LED_Matrix_3x5_MUX
***Header***
1
#ifndef LED_MATRIX_3X5_MUX_H_
2
#define LED_MATRIX_3X5_MUX_H_
3
4
//defines der Zähler für bestimmte Muster
5
#define LED12 91
6
#define LEDX 164
7
#define LEDI0I 160
8
#define LEDECKEN 174
9
#define LEDFLAGGE1 160
10
#define LEDFLAGGE2 228
11
#define LEDSTREIFENLAENGS 234
12
etc...
13
 
14
15
16
void MatrixMux(int MusterNr);
17
void VorhandeneMuster(void);
18
19
extern short interruptT0var;
20
21
#endif /* LED_MATRIX_3X5_MUX_H_ */

***Sourcefile***
1
#include <avr/io.h>        //Für PORT,...
2
#include <avr/interrupt.h>    //Für Interrupfunkltionen
3
#include "LED_Matrix_3x5_MUX.h"  //für eigene MUX Funktionen
4
#include "usart.h"        //für ein ausgabe über putty
5
#include <util/delay.h>      //Für delay (eliminieren)
6
7
//Für Interruptkonfig
8
#ifndef TIMER0_OVF_vect 
9
#define TIMER0_OVF_vect TIMER0_OVF0_vect // Für ältere WinAVR Versionen z.B. WinAVR-20071221
10
#endif
11
12
13
14
//Globale Variable zum richtigen Ablauf der "Count" im switch case
15
short casecount =0;
16
extern short interruptT0var;
17
18
//Ausgabeder vorhandenen Muster
19
void VorhandeneMuster(void)
20
{
21
  usart0SendStringBlocking("\n\r\n\rEs sind folgende Muster verfuegbar:");
22
  usart0SendStringBlocking("\n\rEckpunkte = 1\n\r");
23
  usart0SendStringBlocking("\n\rein H = 2\n\r");
24
  usart0SendStringBlocking("\n\rein X = 3\n\r");
25
  usart0SendStringBlocking("\n\rFlagge 1 = 4\n\r");
26
  usart0SendStringBlocking("\n\rFlagge 1 = 5\n\r");
27
  usart0SendStringBlocking("\n\rStreifen Laengs = 6\n\r");
28
  usart0SendStringBlocking("\n\rStreifen quer = 7\n\r");
29
}
30
31
//Reset des Zählers
32
void ResetCount(void)
33
{
34
  PORTA=0b00000001;
35
  PORTA=0b00000000;
36
}
37
38
//Funktion zum Setzten des Zählers für auszugebende Muster
39
void Count (int count)
40
{  
41
  cli();  //Interrupt off
42
  
43
  if (interruptT0var==1)
44
  {
45
    //Ausschalten der LED um die Matrix beim Hochzählen nicht 
46
    //dauernd alle LED zu beleuchten
47
    PORTA=0b00000000;
48
    
49
    //Rücksetzen des Zählers
50
    ResetCount();
51
    
52
    //Hochzählen auf den neuen "LED_M" Wert
53
    int i=0;
54
    for (i=0;i<count;i++)
55
    {
56
      PORTA=0b00000010;
57
      PORTA=0b00000000;
58
    }
59
    //Wiedereinschalten der LED Matrix
60
    PORTA=0b00000100;
61
    
62
    casecount++;    //Hochzählen der Variable für die case(MusterNr)
63
    interruptT0var=0;  //eigene Interruptvariable rücksetzen
64
  }
65
  
66
  sei();  //Interrupt on
67
  
68
}
69
70
71
/*
72
*  Beim MUX ist darauf zu achten, dass so wenige Schritte wie möglich
73
*  abgearbeitet werden müssen, damit die Zahlen möglichst hell sind 
74
*  nach meinem try and error
75
*/
76
void MatrixMux(int MusterNr)
77
{
78
  
79
  switch (MusterNr)
80
  {
81
    case 0:
82
      Count(LED12);
83
      casecount=0;  //Rücksetzten der casecount Variable
84
    break;
85
    case 1: //Muster Eckpunkte
86
      Count(LEDECKEN);
87
      casecount=0;
88
    break;
89
    case 2:  //Muster H
90
      switch (casecount)
91
      {
92
        case 0:
93
          Count(LEDI0I);
94
        break;
95
        case 1:
96
          Count(LED12);
97
          casecount=0;
98
        break;
99
      }
100
    break;
101
    case 3:  //Muster X
102
      if (casecount==0)
103
      {
104
        Count(LEDX);
105
      }
106
      else if (casecount==1)
107
      {
108
        Count(LED12);
109
      }
110
      casecount=0;
111
    break;
112
    case 4:  //Muster Flagge 1
113
      Count(LEDFLAGGE1);
114
      casecount=0;
115
      
116
    break;
117
    case 5: //Muster Flagge 2 
118
      Count(LEDFLAGGE2);
119
      casecount=0;
120
      
121
    break;
122
    case 6: //Muster Streifen laengs
123
      Count(LEDSTREIFENLAENGS);
124
      casecount=0;
125
    break;
126
    case 7: //Muster Streifen quer
127
      if (casecount==0)
128
      {
129
        Count(LED00);
130
      }
131
      else if (casecount==1)
132
      {
133
        Count(LED02);
134
      }
135
      else if (casecount==2)
136
      {
137
        Count(LED11);
138
      }
139
      else if (casecount==3)
140
      {
141
        Count(LED20);
142
      }
143
      else if (casecount==4)
144
      {
145
        Count(LED04);
146
      }
147
      else if (casecount==5)
148
      {
149
        Count(LED13);
150
      } 
151
      else if (casecount==6)
152
      {
153
        Count(LED22);
154
      }
155
      else if (casecount==7)
156
      {
157
        Count(LED24);
158
      }
159
      casecount=0;
160
    break;
161
    
162
    case 8: //Muster aus
163
      ResetCount();
164
      casecount=0;
165
      interruptT0var=0;  //eigene Interruptvariable rücksetzen
166
    break;
167
      
168
  }  //switch (MusterNr)
169
  
170
}  //void MatrixMux

von Karl M. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

auf die Schnelle was mir aufgefallen ist:
Der Datentype zu |interruptT0var| ist nicht vollständig und die Timer 
ISR kann den Wert nicht ändern.

Stichwort: volatile

Warum wird das Multiplexen der LED nicht in der Timer ISR durchgeführt ?
volantile

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Lehner P. schrieb:
> @ Lothar Miller Wer Rechtschreibfehler findet, darf sie behalten
Das war kein Rechtschreibfehler, sondern ein Verständnisproblem (so wie 
z.B. anderswo "Standart"). Deshalb hatte ich das kurz mal erwähnt...

> Danke Lothar Miller ;-)
Keine Ursache,  man lernt nie aus.

> Ja hatte bei den PNP schon so meine zweifel, aber da die Matrix erst
> funktionierte, dachte ich wirds schon passen. Werde das ansonsten
> ändern.
Ja, denn du betreibst die Transistoren im Inversbetrieb. Das bringt 
insbesondere einen Nachteil mit sich, dass die Stromverstärkung nur noch 
ca. 10 statt 300 ist. Deine Vorwiderstände sind dafür falsch 
berechnet...


BTW:
1
Antwort schreiben
2
Wichtige Regeln - erst lesen, dann posten!
3
.... 
4
    * Längeren Sourcecode nicht im Text einfügen,
5
      sondern als Dateianhang

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Bewertung
0 lesenswert
nicht lesenswert
Lehner P. schrieb:
> Das Problem der Matrix liegt meines erachtens daran, dass in meinem
> Aufruf für das Multiplexen, nur der erste Wert angenommen wird.

 Sage ich doch.
 Ohne mich durch deinen Code zu wühlen:
 Spalten werden richtig umgeschaltet aber der zugehörige Wert wird
 nicht übernommen bzw. aktualisiert.

von Lehner P. (gruffi)


Bewertung
0 lesenswert
nicht lesenswert
Zu meinem vorherigen Post:
ich kann ihn leider nicht mehr editieren...

Karl M. schrieb:
> Der Datentype zu |interruptT0var| ist nicht vollständig und die Timer
> ISR kann den Wert nicht ändern.
>
> Stichwort: volatile

Was heißt "nicht vollständig"?
Und warum kann eine ISR den Wert einer Variable nicht ändern?

Das "Problem" mit "volatile" sollte ich umgehen können wenn ich in den 
Projekt Properties in der Toolchain unter AVE/GNU C Compiler Optimation 
den Optimation Level auf "none" setzte oder? Hab ich nämlich dafür so 
eingestellt.
Wenn ich in meinem Code "volatile" verwende, ändert sich nichts.


Karl M. schrieb:
> Warum wird das Multiplexen der LED nicht in der Timer ISR durchgeführt ?

Wäre meine ISR dann nicht relativ lange? Und sollte man dies nicht 
vermeiden?


Lothar M. schrieb:
> Ja, denn du betreibst die Transistoren im Inversbetrieb. Das bringt
> insbesondere einen Nachteil mit sich, dass die Stromverstärkung nur noch
> ca. 10 statt 300 ist. Deine Vorwiderstände sind dafür falsch
> berechnet...

Stimmt, die hab ich kervehrt eingebaut... die LED leuchten jetzt auch 
generell etwas heller, Danke für den Tipp.


Lothar M. schrieb:
> BTW:Antwort schreiben
> Wichtige Regeln - erst lesen, dann posten!
> ....
>     * Längeren Sourcecode nicht im Text einfügen,
>       sondern als Dateianhang

Wird in Zukunft berücksichtigt!


Nun wieder zum Problem:

Die Variable "InterruptT0var", wird in meinem Programm, so wie ich es 
wollte, in der ISR geändert.
Das sehe ich, wenn ich mir die Speicherstelle ansehe und daran, dass 
wenn ich sie in der ISR auf "0" setze, keine LED mehr leuchten.
Wohl eben, weil ich die Optimation ausgeschaltet habe.

-> main
1
/*
2
*  Der Overflow Interrupt Handler wird aufgerufen, wenn TCNT0 von 255 auf 0 wechselt (256 Schritte),
3
*  Interrupt Aktion alle   (16000000/64)/256 Hz = 976,6 Hz   bzw.   1/976,6 s = 1,024 ms     
4
*/
5
ISR (TIMER0_OVF_vect)
6
{
7
  interruptT0var=1;    //Setzen einer eigenen Iterrupvariable
8
  autocount++;      //Autocount für Musterwechsel
9
  TCNT0 &= 0b00000000;  //Rücksetzen des Timer Zählregisters
10
  TIFR0 = (1<<TOV0);    //Löschen des Interrupt Flag Overflow Timer 0
11
}

-> header
1
extern short interruptT0var;

-> source
1
//Globale Variable zum richtigen Ablauf der "Count" im switch case
2
short casecount =0;
3
extern short interruptT0var;


Mein Problem dürfte also im folgenden liegen:
Mit "casecount", zähle ich eine Variable hoch, welche aussagen sollte, 
welche LED im aktuellen Muster eingeschaltet werden sollte.
Was aber nicht passiert...

--> MatrixMux ist die Funktion, welche das "übergebene" Muster an LED 
ansteuern sollte, jedoch wird immer nur der erste "Count" 
Funktionsaufruf ausgeführt.
Bei Muster H eben die beiden äußeren Spalten, nicht jedoch der zweite 
case, die mittlere LED.
1
void MatrixMux(int MusterNr)
2
{
3
  
4
  switch (MusterNr)
5
  {
6
    case 0:
7
      Count(LED12);
8
      casecount=0;  //Rücksetzten der casecount Variable
9
    break;
10
    case 1: //Muster Eckpunkte
11
      Count(LEDECKEN);
12
      casecount=0;
13
    break;
14
    case 2:  //Muster H
15
      switch (casecount)
16
      {
17
        case 0:
18
          Count(LEDI0I);
19
        break;
20
        case 1:
21
          Count(LED12);
22
          casecount=0;
23
        break;
24
      }
25
    break;
26
    case 3:  //Muster X


In meiner Count Funktion, würde ich diese Variable, nach einem 
Durchlauf, aber immer um Eins erhöhen...?
1
//Funktion zum Setzten des Zählers für auszugebende Muster
2
void Count (int count)
3
{  
4
  cli();  //Interrupt off
5
  
6
  if (interruptT0var==1)
7
  {
8
    //Ausschalten der LED um die Matrix beim Hochzählen nicht 
9
    //dauernd alle LED zu beleuchten
10
    PORTA=0b00000000;
11
    
12
    //Rücksetzen des Zählers
13
    ResetCount();
14
    
15
    //Hochzählen auf den neuen "LED_M" Wert
16
    int i=0;
17
    for (i=0;i<count;i++)
18
    {
19
      PORTA=0b00000010;
20
      PORTA=0b00000000;
21
    }
22
    //Wiedereinschalten der LED Matrix
23
    PORTA=0b00000100;
24
    
25
    casecount++;    //Hochzählen der Variable für die case(MusterNr)
26
    interruptT0var=0;  //eigene Interruptvariable rücksetzen
27
  }
28
  
29
  sei();  //Interrupt on
30
  
31
}


Da müsste der Wurm drinnen sein, aber ich sehe ihn nicht  ;-)

Danke für die bisherigen schnellen und hilfreichen Antworten.

von Jan L. (ranzcopter)


Bewertung
0 lesenswert
nicht lesenswert
Lehner P. schrieb:
>> Stichwort: volatile
>
> Was heißt "nicht vollständig"?
> Und warum kann eine ISR den Wert einer Variable nicht ändern?

ich glaube, er meint

"A variable should be declared volatile whenever its value can be 
changed by something beyond the control of the code section in which it 
appears, such as a concurrently executing thread."

von Lehner P. (gruffi)


Bewertung
0 lesenswert
nicht lesenswert
Info @ all:

Mein Programm läuft jetzt, Danke nochmal an die hilfreichen Antworten!

Mein Fehler lag hier:

In meiner inneren Switch hatte ich die Variable "casecount" nullgesetzt, 
natürlich ist das immer passiert, sobald case "0" abgearbeitet worden 
war.
1
case 2:  //Muster H
2
      switch (casecount)
3
      {
4
        case 0:
5
          Count(LEDI0I, interruptT0var);
6
        break;
7
        case 1:
8
          Count(LED12, interruptT0var);
9
        break;
10
                                casecount=0; <-- Fehler!
11
      }
12
    break;


Richtiggestellt sieht der Code so aus:
Nun wird die "casecount" Variable erst nach der letzten inneren switch 
case Anweisung nullgesetzt.
1
case 2:  //Muster H
2
      switch (casecount)
3
      {
4
        case 0:
5
          Count(LEDI0I, interruptT0var);
6
        break;
7
        case 1:
8
          Count(LED12, interruptT0var);
9
          casecount=0; <-- Richtig
10
        break;
11
      }
12
    break;

Ich sollte meine Augen eben aufmachen beim lesen und schreiben :-D

Einen gemütlichen "Abend" noch an alle.


PS: Eine Frage hätte ich noch, wie löst man es sauber in der ISR den 
neuen Zählerstand auszugeben? Tipps? :-)

: Bearbeitet durch User
von Karl M. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke Jan,

Jan L. schrieb:
> ich glaube, er meint
>
> "A variable should be declared volatile whenever its value can be
> changed by something beyond the control of the code section in which it
> appears, such as a concurrently executing thread."

ich dachte er (TE) würde sich mehr mit den MC und C beschäftigen und 
diesen Fehler in seinem Programm finden. Er ist nun immer noch 
vorhanden.


>Karl M. schrieb:
>> Warum wird das Multiplexen der LED nicht in der Timer ISR durchgeführt ?

>Wäre meine ISR dann nicht relativ lange? Und sollte man dies nicht
>vermeiden?

Ja und ich will ja auch nicht, dass die LED flackern, sondern die LED 
mit einer definierten Umschaltzeit "bedient" werden.

Wenn man für die Ausgabe zwei LED Framepuffer verwendet, dauert dise 
auch nicht lange. Im Hauptprogramm wird das Muster berechnet und in den 
nicht benutzen LED Framepuffer geschrieben, ist das Muster vollständig, 
wird der LED Framepuffer umgeschaltet.
Dein gesamtes Programm wird durch diese Maßnahmen strukturierter, besser 
lesbar und besser wartbar.

von Lehner P. (gruffi)


Bewertung
0 lesenswert
nicht lesenswert
Karl M. schrieb:
> Ja und ich will ja auch nicht, dass die LED flackern, sondern die LED
> mit einer definierten Umschaltzeit "bedient" werden.
>
> Wenn man für die Ausgabe zwei LED Framepuffer verwendet, dauert dise
> auch nicht lange. Im Hauptprogramm wird das Muster berechnet und in den
> nicht benutzen LED Framepuffer geschrieben, ist das Muster vollständig,
> wird der LED Framepuffer umgeschaltet.
> Dein gesamtes Programm wird durch diese Maßnahmen strukturierter, besser
> lesbar und besser wartbar.

Alles klar, dann werde ich meinen Code noch etwas umstrukturieren.



Habt ihr auch Tipps oÄ welchen Normen oder vlt auch Vorschriften oder 
Richtlinien solche Codes in der Industrie bzw in Firmen folgen?
Worauf muss man in der Softwareentwicklung bzw Hard&Software Engineering 
oder im Bereich der Embedded Software auf soetwas achten?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.