Forum: Mikrocontroller und Digitale Elektronik Code Ansteuerung LED Matrix mit TPIC-6B595


von Roy B. (roy_b)


Lesenswert?

Hallo,

ich sitze gerade über dem Code für die Ansteuerung einer LED Matrix.
Deren Spalten hängen an 3 aufgereiten TPIC-6B595 Schieberegistern und 5 
Zeilen werden jeweils über einen PNP Gen VCC gezogen.

Die Hardware funktioniert soweit ich es sagen kann. Das heißt wenn ich 
gemütlich im Code ein Bit Ausgebe und es dann durchschiebe, kann ich 
jede LED einzeln ansteuern.

Da nun aber das normale shiftOut der Arduino IDE recht langsem ist und 
die LEDs dadurch stark flackern, habe ich versucht einen schnelleren 
Coder zu verwenden und gleich auf die Matrix zu zuschneiden.

angelehnt an den Beitrag sus dem Arduinoforum
http://forum.arduino.cc/index.php?topic=181577.15

Fom Prinzip her scheint es zu funktionieren, es gibt nur ein mir 
unerklärliches Phänomen. Egal welches Bit in der Matrix gesetzt werden 
soll, augegeben wird immer dieses Bit und zusätzlich noch das gleiche 
Bit in den nächsten 2 Byte. Das ganze nicht nur innerhald einer Zeile, 
sondern auch Zeilenübergreifend.

Wenn ich mir jetzt mit dem Oszi die Daten und Clock Signale anschaue, 
sehen die sehr gut aus. Das Bitmuster passt. die Pegel sind nicht 
verwaschen.
Die Schieberegister geben auch glatte Pegel aus und die zusätzlich 
leuchtenden werden auch wirklich vom Schieberegister angesteuert, dass 
heißt, wenn ich an deren Ausgängen alles abziehe, zum Messen einen Pull 
Up mit ran halte, kommen saubere Pegel raus.
Ich kann mir das einfach nicht erklären.

Also der Code mit normal shiftOut funktioniert:
1
const int TastH = 17;       //Taster für Stunden
2
const int TastM = 16;       //Taster für Minuten
3
const int TastS = 15;       //Taster für Set
4
const int UHRSCL = 19;      //SCL zur Realtime Clock
5
const int UHRSDA = 18;      //SDA zur Realtime Clock
6
const int BRT = 14;         //Analog A0 für Helligkeitssensor
7
const int CKCLK = 2;        //Clock eingang von der Realtime Clock
8
const int dataPin = 11;  //Serial Daten Pin
9
const int LEDOE = 6;        //Output Enable der Schieberegister
10
const int clockPin = 13;      //Clock für Schieberegister
11
const int latchPin = 5;        //Letch enable für die Schieberegister
12
const int CSEL1 = 4;        //Reihe 1
13
const int CSEL2 = 7;        //Reihe 2
14
const int CSEL3 = 8;        //Reihe 3
15
const int CSEL4 = 9;        //Reihe 4
16
const int CSEL5 = 10;       //Reihe 5
17
const int DCF = 3;          //Pin für DCF Signal
18
19
byte LEDArray[5][3] = {
20
  {
21
    B10000000,
22
    B00000000,
23
    B00000000
24
  },
25
  {
26
    B00000000,
27
    B00000000,
28
    B00000000
29
  },
30
  {
31
    B00000000,
32
    B00000000,
33
    B00000000
34
  },
35
  {
36
    B00000000,
37
    B00000000,
38
    B00000000
39
  },
40
  {
41
    B00000000,
42
    B00000000,
43
    B00000000
44
  }
45
};
46
47
void setup() {
48
 
49
  pinMode(latchPin, OUTPUT);
50
  pinMode(dataPin, OUTPUT);
51
  pinMode(clockPin, OUTPUT);
52
  pinMode(LEDOE, OUTPUT);
53
  pinMode(CSEL1, OUTPUT);
54
  pinMode(CSEL2, OUTPUT);
55
  pinMode(CSEL3, OUTPUT);
56
  pinMode(CSEL4, OUTPUT);
57
  pinMode(CSEL5, OUTPUT);
58
}
59
60
void loop() {
61
  for (int i=0; i<5; i++){
62
    for (int j=0; j<3; j++){
63
      shiftOut(dataPin, clockPin, LSBFIRST, LEDArray [i][j]);
64
    }
65
    digitalWrite(LEDOE, HIGH);
66
    switch(i){
67
      case 0: digitalWrite(CSEL1, HIGH); digitalWrite(CSEL5, LOW); break;
68
      case 1: digitalWrite(CSEL2, HIGH); digitalWrite(CSEL1, LOW); break;
69
      case 2: digitalWrite(CSEL3, HIGH); digitalWrite(CSEL2, LOW); break;
70
      case 3: digitalWrite(CSEL4, HIGH); digitalWrite(CSEL3, LOW); break;
71
      case 4: digitalWrite(CSEL5, HIGH); digitalWrite(CSEL4, LOW); break;
72
    }
73
    digitalWrite(latchPin, LOW);
74
    digitalWrite(latchPin, HIGH);
75
    digitalWrite(LEDOE, LOW);
76
  }
77
}

Der schnellere nicht:
1
#define BitMaskCLK 0b00100000  //pin 13 = Clock Pin; Pin 13 ist bit 5 von Port B
2
#define BitMaskDAT 0b00001000  //pin 11 = Data Pin; Pin 11 ist bit 3 von Port B
3
#define BitMaskLAT 0b00100000  //pin 5 = Data Pin; Pin 5 ist bit 5 von Port D
4
#define BitMaskOE 0b01000000   //pin 6 = Data Pin; Pin 6 ist bit 6 von Port D
5
#define BitMaskR1 0b00010000   //pin 4 = Data Pin; Pin 4 ist bit 4 von Port D
6
#define BitMaskR2 0b10000000   //pin 7 = Data Pin; Pin 7 ist bit 7 von Port D
7
#define BitMaskR3 0b00000001   //pin 8 = Data Pin; Pin 8 ist bit 0 von Port B
8
#define BitMaskR4 0b00000010   //pin 9 = Data Pin; Pin 9 ist bit 1 von Port B
9
#define BitMaskR5 0b00000100   //pin 10 = Data Pin; Pin 10 ist bit 2 von Port B
10
11
12
const int TastH = 17;       //Taster für Stunden
13
const int TastM = 16;       //Taster für Minuten
14
const int TastS = 15;       //Taster für Set
15
const int UHRSCL = 19;      //SCL zur Realtime Clock
16
const int UHRSDA = 18;      //SDA zur Realtime Clock
17
const int BRT = 14;         //Analog A0 für Helligkeitssensor
18
const int CKCLK = 2;        //Clock eingang von der Realtime Clock
19
const int dataPin = 11;  //Serial Daten Pin
20
const int LEDOE = 6;        //Output Enable der Schieberegister
21
const int clockPin = 13;      //Clock für Schieberegister
22
const int latchPin = 5;        //Letch enable für die Schieberegister
23
const int CSEL1 = 4;        //Reihe 1
24
const int CSEL2 = 7;        //Reihe 2
25
const int CSEL3 = 8;        //Reihe 3
26
const int CSEL4 = 9;        //Reihe 4
27
const int CSEL5 = 10;       //Reihe 5
28
const int DCF = 3;          //Pin für DCF Signal
29
30
byte LEDArray[5][3] = {
31
  {
32
    B00000000,
33
    B0000000,
34
    B10000000
35
  },
36
  {
37
    B00000000,
38
    B00000000,
39
    B00000000
40
  },
41
  {
42
    B00000000,
43
    B00000000,
44
    B00000000
45
  },
46
  {
47
    B00000000,
48
    B00000000,
49
    B00000000
50
  },
51
  {
52
    B00000000,
53
    B00000000,
54
    B00000000
55
  }
56
};
57
void setup() {
58
 
59
  pinMode(latchPin, OUTPUT);
60
  pinMode(dataPin, OUTPUT);
61
  pinMode(clockPin, OUTPUT);
62
  pinMode(LEDOE, OUTPUT);
63
  pinMode(CSEL1, OUTPUT);
64
  pinMode(CSEL2, OUTPUT);
65
  pinMode(CSEL3, OUTPUT);
66
  pinMode(CSEL4, OUTPUT);
67
  pinMode(CSEL5, OUTPUT);
68
}
69
70
void loop() {
71
  for (int i=0; i<5; i++){
72
     for (int j=0; j<3; j++){
73
      byte bitt = 1;   //Variable die speichert, welches Bit wir gerade rausschreiben. Wir fangen beim LSB an.
74
      while(bitt) //Wenn wir die "1" 7 mal geschoben haben, ist sie vom LSB zum MSB gewandert. Beim 8. Mal ist das Bit dann links rausgeschoben und die Variable 0. Da 0 = false wird die Schleife abgebrochen
75
      {
76
        if (LEDArray[i][j] & bitt)  //ist das aktuelle Bit des herauszuschiebenden Wertes gesetzt?
77
          PORTB |= BitMaskDAT;   //ja: Datenpin HIGH
78
        else
79
          PORTB = (PORTB &~BitMaskDAT);  //nein: Datenpin LOW. "PORT &~BitMaskDAT" gibt alle Pins so zurück wie sie waren, außer der der in BitMaskDat gesetzt ist wird 0.
80
        bitt <<= 1;  //Schiebe die Merkervariable um eins nach links, jetzt ist das nächste Bit dran.
81
        PORTB |= BitMaskCLK;  // Clockpin auf High
82
        PORTB ^= BitMaskCLK;  //Toggle den Clockpin. Da er davor HIGH war, wird er jetzt wieder LOW.
83
84
      }
85
      PORTD |= BitMaskOE;  // OE Pin auf High
86
      PORTD |= BitMaskLAT;  // Latchpin auf High
87
      PORTD ^= BitMaskLAT;  //Toggle den Latchpin. Da er davor HIGH war, wird er jetzt wieder LOW.
88
      switch(i){
89
      case 0: PORTB = (PORTB &~BitMaskR5); PORTD |= BitMaskR1; break;
90
      case 1: PORTD = (PORTD &~BitMaskR1); PORTD |= BitMaskR2; break;
91
      case 2: PORTD = (PORTD &~BitMaskR2); PORTB |= BitMaskR3; break;
92
      case 3: PORTB = (PORTB &~BitMaskR3); PORTB |= BitMaskR4; break;
93
      case 4: PORTB = (PORTB &~BitMaskR4); PORTB |= BitMaskR5; break;
94
      }
95
      PORTD ^= BitMaskOE;  //Toggle den OE Pin. Da er davor HIGH war, wird er jetzt wieder LOW.
96
    }
97
  }
98
}

: Bearbeitet durch User
von Roy B. (roy_b)


Lesenswert?

Manchmal sieht man den Wald vor lauter Bäumen nicht, gerade als ich den 
Code nocheinmal Jemandem erklären wollte ist es mir aufgefallen.
Ich habe die Freigabe an die Pins nach jedem Byte gemacht und nicht 
aller drei Byte. Also die ganze Brühe mit OE und Latch innerhalb der 
Schleife mit j und nicht außerhalb.
Für die Nachwelt, wenn Jemand ein Codebeispiel für eine schnelle 
Serielle Ausgabe sucht:
1
void loop() {
2
  for (int i=0; i<5; i++){
3
    for (int j=0; j<3; j++){
4
      byte bitt = 1;   //Variable die speichert, welches Bit wir gerade rausschreiben. Wir fangen beim LSB an.
5
      while(bitt) //Wenn wir die "1" 7 mal geschoben haben, ist sie vom LSB zum MSB gewandert. Beim 8. Mal ist das Bit dann links rausgeschoben und die Variable 0. Da 0 = false wird die Schleife abgebrochen
6
      {
7
        if (LEDArray[i][j] & bitt)  //ist das aktuelle Bit des herauszuschiebenden Wertes gesetzt?
8
          PORTB |= BitMaskDAT;   //ja: Datenpin HIGH
9
        else
10
          PORTB = (PORTB &~BitMaskDAT);  //nein: Datenpin LOW. "PORT &~BitMaskDAT" gibt alle Pins so zurück wie sie waren, außer der der in BitMaskDat gesetzt ist wird 0.
11
        bitt <<= 1;  //Schiebe die Merkervariable um eins nach links, jetzt ist das nächste Bit dran.
12
        PORTB ^= BitMaskCLK;  // Clockpin auf High
13
        PORTB ^= BitMaskCLK;  //Toggle den Clockpin. Da er davor HIGH war, wird er jetzt wieder LOW.
14
      }
15
    }
16
    PORTD |= BitMaskOE;  // OE Pin auf High
17
    PORTD |= BitMaskLAT;  // Latchpin auf High
18
    switch(i){
19
      case 0: PORTB = (PORTB &~BitMaskR5); PORTD |= BitMaskR1; break;
20
      case 1: PORTD = (PORTD &~BitMaskR1); PORTD |= BitMaskR2; break;
21
      case 2: PORTD = (PORTD &~BitMaskR2); PORTB |= BitMaskR3; break;
22
      case 3: PORTB = (PORTB &~BitMaskR3); PORTB |= BitMaskR4; break;
23
      case 4: PORTB = (PORTB &~BitMaskR4); PORTB |= BitMaskR5; break;
24
    }
25
    PORTD ^= BitMaskLAT;  //Toggle den Latchpin. Da er davor HIGH war, wird er jetzt wieder LOW.
26
    PORTD ^= BitMaskOE;  //Toggle den OE Pin. Da er davor HIGH war, wird er jetzt wieder LOW.
27
  }
28
}

von John (Gast)


Lesenswert?

Roy B. schrieb:
> eine schnelle Serielle Ausgabe

Hat der Arduino kein SPI (Hardware)?

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.