Forum: Mikrocontroller und Digitale Elektronik MAX7219 (Verständnis) Problem (angeschlossen an Mega 16)


von Ich (Gast)


Lesenswert?

Ich versuche mich gerade an dem 7-Segment Display Treiber MAX7219. Ich 
habe ein Sieben-Segment Display angeschlossen, die restlichen 7 sind 
nicht angeschlossen. Die Hardware passt auch (mehrere mal überprüft, mit 
mehreren Aufbauten auf dem Steckbrett tats genauso nicht), darum vermute 
ich, dass ich das Datenblatt nicht ganz kapiere.
Hier im Forum schwirrt zwar einiges an Quellcode zum 7219 herum, aber 
ich wollte das eigentlich selber machen.

Hier meine Ansätze:

Wenn ich das richtig verstanden habe funktioniert der 7219 so:
Man legt LOAD auf 0 und schiebt 16 Bits an Daten-/Steuerbits rein. Nach 
jedem Datenbit muss eine Clock-High-Flanke kommen, damit die Bits ins 
Schieberegister kommen.
CLOCK ist zuvor auf 0, ich setz ihn einmal auf 1 und dann wieder auf 0, 
der uC läuft bei 8MHZ, KANN also gar nicht über den unterstützen 10MHZ 
des 7219 liegen und ich habe immer wieder Pausen von ca. 1ms zum Testen 
ins Programm eingebaut.
Das Format der Daten ist im Datenblatt so angegeben (vom MSB zum LSB):
4 Don't Care Bits, 4 Register Bits, 8 Datenbits.

Der Controller ist ein Mega 16.

Ich habe meinen Quellcode hoffentlich gut kommentiert und ihr seht 
gleich, was ich bezwecken will, wenn nicht, bitte nachfragen!


Die main.c
1
#include "io.h"    
2
#include <avr/io.h>
3
4
int main(void) {
5
  int counter;
6
7
  DDRA = 0xff;
8
  load('L');
9
10
  
11
  // Die ersten 4 Bits des 16 Bit langen Signals sind Don't Cares, also egal ob 0 oder 1
12
  for(counter = 0; counter <= 3; counter++) {
13
    din('L');
14
    clock();
15
  }
16
17
  // Nun die 4 Bits fuers Register, in dem fall 0001 => Digit 0
18
  for(counter = 0; counter <= 2; counter++) {  // die ersten 3 bits = 0
19
      din('L');
20
      clock();
21
  }
22
  din('H');          // das vierte bit = 1
23
  clock();
24
25
  // Nun die 8 Datenbits, in dem Fall 1000 0010 => DP gesetzt (MSB) und eine 2 auf dem Display
26
  din('H');
27
  clock();
28
  for(counter = 0; counter <= 4; counter++) {  // bits 2...6 = 0
29
      din('L');
30
      clock();
31
  }
32
  din('H');  // bit 1 = 1
33
  clock();
34
  din('L');  // bit 0 = 0
35
  clock();
36
37
  // Nun noch den LOAD hochnehmen und wieder runter und es müsste klappen....
38
  load('H');
39
  wait(1);
40
  load('L');
41
  while(1){};
42
}

Die io.c
1
#define F_CPU 8000000L
2
#include "io.h"
3
#include <stdlib.h>
4
#include <avr/io.h>
5
#include <util/delay.h>
6
// Port Definitonen für CLK (Clock), LOAD und DIN (Data IN)
7
#define MAX7219_PORT PORTA
8
#define MAX7219_CLOCK PA2
9
#define MAX7219_LOAD PA1
10
#define MAX7219_DIN PA0
11
12
int clock() {      //Clock Signal Erzeugen, High-Low
13
  MAX7219_PORT |= (1<<MAX7219_CLOCK);  // H
14
  wait(1);
15
  MAX7219_PORT &= ~(1<<MAX7219_CLOCK);  // L
16
  wait(1);
17
  return(0);  
18
}
19
20
int load(unsigned char signal) {
21
  if(signal == 'H') {
22
    MAX7219_PORT |= (1<<MAX7219_LOAD);
23
    wait(1);
24
  }
25
  if(signal == 'L') {
26
    MAX7219_PORT &= ~(1<<MAX7219_LOAD);
27
    wait(1);
28
  }
29
30
  return(0);
31
}
32
33
int din(unsigned char signal) {
34
  if(signal == 'H') {
35
    MAX7219_PORT |= (1<<MAX7219_DIN);
36
    wait(1);
37
  }
38
  if(signal == 'L') {
39
    MAX7219_PORT &= ~(1<<MAX7219_DIN);
40
    wait(1);
41
  }
42
43
  return(0);
44
}
45
46
int wait(int time) {
47
  for(; time > 0; time--) { 
48
    _delay_ms(1);
49
  }
50
  
51
  return(0);
52
53
}
Die io.h
1
extern int clock();
2
extern int load(unsigned char signal);
3
extern int din(unsigned char signal);
4
extern int wait(int time);
Und hier noch der Compileraufruf:
avr-gcc -mmcu=atmega16 -Wall -Os -funsigned-bitfields -funsigned-char 
-fshort-enums -std=gnu99 -c main.c -o main.o
avr-gcc -mmcu=atmega16 -Wall -Os -funsigned-bitfields -funsigned-char 
-fshort-enums -std=gnu99 -c io.c -o io.o
avr-gcc -mmcu=atmega16 -Wall -Os -funsigned-bitfields -funsigned-char 
-fshort-enums main.o io.o -o max7219.elf
avr-objcopy -O ihex -j .text -j .data max7219.elf max7219.hex

Ich hoffe ihr könnt mir hierbei helfen!

von Ich (Gast)


Lesenswert?

Arghs, das wichtigste am ganzen hab' ich doch glatt vergessen! 
Entschuldigung!

Mein Problem nun ist, dass am Display nicht angezeigt wird. Wie gesagt, 
Hardware muss in Ordnung sein, sprich es liegt an der Software.

von Daniel P. (ppowers)


Lesenswert?

Hihi, dass ist ja mal ein kreativer Ansatz, die Daten in den Chip zu 
clocken :-)

Also ich hab mir Deinen Code jetzt nicht im Detail angeschaut, aber als 
ich damals einen Driver für den MAX7219 geschrieben habe, hatte ich noch 
eine Initialsierungsfunktion, die so unwichtige Dinge wie Scan Limit, 
Code-B-Decoding, Helligkeit usw. bei dem MAX eingestellt hat. Vermisse 
ich bei Dir irgendwie.
Außerdem hat der MAX auch sowas wie einen "display Test Mode", mit dem 
man checken kann, ob alle Digits funktionieren. Vielleicht solltest Du 
das Datenblatt mal GANZ lesen, wenn Du Deinen Code schon nicht mit 
fremden Beispielen vergleichen möchtest. :-)

Viel Erfolg!

von Peter D. (peda)


Lesenswert?

Ich wrote:

> Hier im Forum schwirrt zwar einiges an Quellcode zum 7219 herum, aber
> ich wollte das eigentlich selber machen.

Kannst Du machen. Sei aber nicht böse, daß sich das keiner anguckt, wenn 
es einen hohen Umständlichkeitsgrad übersteigt.


Die Wahl von Port A ist natürlich äußerst unglücklich.
Die meisten Beispiele nehmen PB5 und PB7.
Da liegt nämlich das SPI und das ist dann ganz ganz traurig, wenn es 
nicht mit dem SPI-IC MAX7219 spielen darf.

Aber auch Software-SPI kann man erheblich einfacher machen.


Peter

von Ich (Gast)


Lesenswert?

Daniel P.,
Arghs, daran lag es. Ja, das hätte mir einiges an Zeit und dummen Fragen 
erspart, wenn ich das mal getan hätte...
Jetzt funktioniert es.

Peter Dannegger,
SPI kommt noch, ich möchte die IC erstmal verstehen und mit den Bits 
jonglieren, als säss' ich vor drei Umschaltern und gebe dem so immer 
sein H/L ;) und das bevor ich mit SPI anfange, wenn es dann 
funktioniert, wird das basteln wie jetzt gleich langweilig.

Vielen Dank! :)

von Sven (Gast)


Lesenswert?

Hallo Ich,

mit Deinem Code habe ich mich nicht genau befasst, um ehrlich zu sein 
ist der mir ein wenig zu komplex um einen MAX7119 / MAX7121 anzusteuern. 
Und darin liegt vielleicht auch der Fehler - denn der MAX7119 
unterscheidet sich in einem Detail zum MAX7121, nämlich dem 
Übertragungsprotokoll der Daten. Guck mal in Datenblatt nach (Seite 5 
unter PIN 12). Beim MAX7119 (LOAD) musst Du die Daten bei LOAD = Low 
"reinschieben", und wenn LOAD (PIN 12) auf High gesetzt wird dann werden 
die letzten 16 Bits interpretiert. Beim MAX7121 muss /CS (PIN12) auf Low 
gesetzt werden, die 16 Bits "reingeschoben" werden und /CS wieder auf 
High gesetzt werden um die Daten zu interpretieren.

Wie geschrieben habe Deinen Code nur kurz "überflogen", warum schibest 
Du erst 4 Bits rein, dann 2 - komisch. Du musst doch einfach nur 2 Bytes 
in den MAX schieben, nämlich das Address- und das Datenbyte. Das ist ein 
maximal ein 20-Zeiler in AVR-GCC.

Fazit: Eine MAX7119-Routine funktioniert nicht für einen MAX7121, und 
umgekehrt.

Ich dieser Text hilft ein wenig ....

von Ich (Gast)


Lesenswert?

Sven, am Load lags nicht. Wie geschrieben, es lag daran, dass ich mich 
nicht komplett mit dem Datenblatt befasst habe und somit die ganzen 
"Einstellungen" verpennt habe. Jetzt funktionierts :)

Nochmals vielen Dank!

von Peter D. (peda)


Lesenswert?

Sven wrote:

> Fazit: Eine MAX7119-Routine funktioniert nicht für einen MAX7121, und
> umgekehrt.

Das ist natürlich großer Quatsch mit Soße.

Schau Dir dochmal das Taktdiagramm an.
Der MAX7219 will die L-H-Flanke am Ende, während des Schiebens ists 
wurscht.
Der MAX7221 will auch die L-H-Flanke am Ende, aber wärend des Schiebens 
muß L sein.

Also:
MAX7221-Code funktioniert immer auch für den MAX7219!

Man kann aber den Code so schreiben, daß er nur für den MAX7219 
funktioniert.
Es spart aber weder Code noch Zeit, ob man das Load nun am Anfang oder 
am Ende auf L setzt.


Peter

von Udo (Gast)


Lesenswert?

Sven schrieb:
> Beim MAX7119 (LOAD) musst Du die Daten bei LOAD = Low
> "reinschieben", und wenn LOAD (PIN 12) auf High gesetzt wird dann werden
> die letzten 16 Bits interpretiert.

Sorry Sven, aber das stimmt so nur für den 7221, beim 7219 reicht es, am 
Ende der Datenübertragung 1 mal Load auf Low und dann wieder auf High zu 
schalten.
Mit der steigenden Flanke des Load-Signals werden dann die Daten, die 
bis dahin eingetaktet wurden, in das Latch übernommen.

Gruß
Udo

von Udo (Gast)


Lesenswert?

ups, Peter war schneller....

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.