Forum: Mikrocontroller und Digitale Elektronik MAX7219: 3-Segment-Anzeige macht Probleme


von Constantin Alexandru M. (azzuro)


Angehängte Dateien:

Lesenswert?

Hallo,
ich hab ein Problem mit meinem MAX7219-Baustein und komme nicht weiter.
Über meinem Atmega8535 mit einem Quarzoszillator von 4,096 MHz steuere 
ich einen MAX7219-Baustein und dieser soll drei 7-Segment-Anzeigen 
betreiben. Die Anzeige soll im Sekunden-Takt von 0 bis 100 in 10er 
Schritten anzeigen. Es wird zwar etwas angezeigt, aber es sind eher 
irgendwelche Hieroglyphen und die Helligkeit der einzelnen Segmente ist 
auch unterschiedlich. Das C-Programm sollte eigentlich funktionsfähig 
sein, da ich es hier aus dem Forum bezogen habe. Die Hardware sollte 
auch passen.
Schaltung und Board sind im Anhang.

Weiß einer einen Rat?

Quellcode:
1
#define F_CPU 4096000L
2
#define max7219_PORT PORTB
3
#define max7219_DDR DDRB
4
#define max7219_CLK PB7
5
#define max7219_LOAD PB6
6
#define max7219_DIN PB5
7
8
#include <avr/io.h>
9
#include <util/delay.h>
10
#include <stdint.h>
11
#include <string.h>
12
#include <stdlib.h>
13
14
void long_delay (uint8_t ms) 
15
{
16
    for (; ms>0; ms--) _delay_ms (10);
17
}
18
19
void max7219_clock_out(unsigned char Data)
20
{
21
  char i;  
22
  for(i=0;i<8;i++) {  
23
      max7219_PORT &= ~(1<<max7219_CLK); //Clock auf Low
24
      if(Data & (1<<7)) {
25
    max7219_PORT |= (1<<max7219_DIN);
26
      } else{
27
    max7219_PORT &= ~(1<<max7219_DIN);
28
      }
29
      Data <<= 1;
30
      max7219_PORT |= (1<<max7219_CLK); //Clock auf High, Daten werden übernommen
31
  }
32
  return;
33
}
34
35
void max7219_send(unsigned char Data, unsigned char Register)
36
{
37
  //Register &= 0x0F; //Obere 4 Bits der Adresse werden nciht gelesen.
38
  max7219_PORT &= ~(1<<max7219_LOAD); // LOAD auf Low (Chip aktivieren)
39
  max7219_clock_out(Register); //Adresse senden
40
  max7219_clock_out(Data); //Daten senden
41
  max7219_PORT |= (1<<max7219_LOAD); // LOAD auf High. Steigende Flanke an High übernimmt Daten in Adressiertes Register.
42
}
43
44
void max7219_set_decodemode(unsigned char Decodemode) {max7219_send(Decodemode, 0x09);}
45
void max7219_intensity(unsigned char Intensity) {max7219_send(Intensity, 0x0A);}
46
void max7219_set_scanlimit(unsigned char Scanlimit) {max7219_send(Scanlimit, 0x0B);} 
47
48
void max7219_shutdown(void) {max7219_send(0x00, 0x0C);} 
49
void max7219_wakeup(void) {max7219_send(0x01, 0x0C);} 
50
51
void max7219_displaytest_on(void) {max7219_send(0x01, 0x0F);} 
52
void max7219_displaytest_off(void) {max7219_send(0x00, 0x0F);} 
53
54
void max7219_nop(void) {max7219_send(0x00, 0x00);}
55
56
57
58
void max7219_clear(void)
59
{
60
  for(char i=1;i<9;i++){
61
    max7219_send(0b00000000, i);
62
  }
63
}
64
65
void max7219_init(void)
66
{
67
  max7219_DDR |= (1<<max7219_DIN) | (1<<max7219_LOAD) | (1<<max7219_CLK); // Die 3 Steurpins zu Ausgängen machen
68
  max7219_PORT &= ~( (1<<max7219_DIN) | (1<<max7219_CLK) ); // Clock und DIN auf Low Level
69
  max7219_PORT |= (1<<max7219_LOAD); //LOAD (CS bei 7221) auf High
70
  max7219_set_decodemode(0); //Keine BCD Wandler. Aller Segmente können individuell angesprochen werden.
71
  max7219_set_scanlimit(2); //Alle zeichen aktivieren
72
  max7219_intensity(15);  //Helligkeitsstufe 8 ist ein gutes Mittelmaß
73
  max7219_clear(); //Display zunächst leeren.
74
  max7219_wakeup();
75
}
76
77
//Tabelle für Hexadezimalzaheln
78
static const unsigned char Symbol[] = {0b01111110,0b00110000,0b01101101,0b01111001,0b00110011,0b01011011,0b01011111,0b01110000,0b01111111,0b01111011,0b01110111,0b00011111,0b01001110,0b00111101,0b01001111,0b01000111};
79
80
void max7219_hex(unsigned char Number, unsigned char Position)
81
{
82
  unsigned char Segments;
83
84
  if(Number > 15) {Segments = 0x00;}
85
  else {Segments = Symbol[Number];}
86
87
88
  max7219_send(Segments, Position);
89
}
90
91
void max7219_disp_uint8(uint8_t Number)
92
{
93
  char Digits = 3; //Maximal 3 Stellen (255)
94
     if(Number<10)   {Digits = 1;}
95
  else if(Number<100)  {Digits = 2;}
96
  
97
  char i;
98
  
99
  for(i=1;i<=Digits;i++)
100
  {  
101
    max7219_hex(Number%10,i);
102
    Number/=10;
103
  }
104
  for(;i<=3;i++){max7219_send(0b00000000, i);} //Führende Nullen nicht anzeigen
105
}
106
107
108
int main (void) 
109
{
110
   DDRA  = 0x00;
111
   DDRB  = 0xE0;
112
   DDRC  = 0xFF;
113
   DDRD  = 0xFB;
114
   
115
   PORTC = 0xFB;
116
   max7219_init ();
117
   
118
   while(1) 
119
   {   
120
       max7219_hex (16, 1);
121
       max7219_hex (16, 2);
122
       max7219_hex (0, 3);
123
       long_delay (100);
124
125
       max7219_hex (16, 1);
126
       max7219_hex (1, 2);
127
       max7219_hex (0, 3);
128
       long_delay (100);
129
130
       max7219_hex (16, 1);
131
       max7219_hex (2, 2);
132
       max7219_hex (0, 3);
133
       long_delay (100);
134
135
       max7219_hex (16, 1);
136
       max7219_hex (3, 2);
137
       max7219_hex (0, 3);
138
       long_delay (100);
139
140
       max7219_hex (16, 1);
141
       max7219_hex (4, 2);
142
       max7219_hex (0, 3);
143
       long_delay (100);
144
       
145
       max7219_hex (16, 1);
146
       max7219_hex (5, 2);
147
       max7219_hex (0, 3);
148
       long_delay (100);
149
    
150
       max7219_hex (16, 1);
151
       max7219_hex (6, 2);
152
       max7219_hex (0, 3);
153
       long_delay (100);
154
155
       max7219_hex (16, 1);
156
       max7219_hex (7, 2);
157
       max7219_hex (0, 3);
158
       long_delay (100);
159
    
160
       max7219_hex (16, 1);
161
       max7219_hex (8, 2);
162
       max7219_hex (0, 3);
163
       long_delay (100);
164
    
165
       max7219_hex (16, 1);
166
       max7219_hex (9, 2);
167
       max7219_hex (0, 3);
168
       long_delay (100);
169
    
170
       max7219_hex (1, 1);
171
       max7219_hex (0, 2);
172
       max7219_hex (0, 3);
173
       long_delay (100);
174
   }
175
   return 0;                
176
}

: Verschoben durch User
von Constantin Alexandru M. (azzuro)


Lesenswert?

Hat einer diesbezüglich eine Idee was ich anders machen könnte?

von Max7219 (Gast)


Lesenswert?

************************************************************************
>Es wird zwar etwas angezeigt, aber es sind eher
>irgendwelche Hieroglyphen und die Helligkeit der einzelnen Segmente ist
>auch unterschiedlich. Das C-Programm sollte eigentlich funktionsfähig
>sein, da ich es hier aus dem Forum bezogen habe.
************************************************************************
Hieroglyphen deuten auf fehlerhafte Kommunikation.

In _init() nach _intensity() ein displaytest(on) ein delay() und ein 
displaytest(off) einfügen.

bei funktionierender Kommunikation wird _init() mit _displaytest(on) 
alle Display-Segmente während delay() leuchten lassen.

von Constantin Alexandru M. (azzuro)


Lesenswert?

Max7219 schrieb:
> In _init() nach _intensity() ein displaytest(on) ein delay() und ein
> displaytest(off) einfügen.

Hab ich jetzt gemacht, aber die LEDs der Segmente sind stattdessen bei 
max7219_displaytest_on() ausgegangen. Ich habe mal dooferheitshalber die 
DIN in max7219_clock_out () mal vertauscht, da leuchteten die LEDs aber 
dauerhaft, also kann es an der DIN schon mal nicht liegen.

von Constantin Alexandru M. (azzuro)


Lesenswert?

Kann es vielleicht an der Taktfrequenz von 4,096 MHz liegen, das der 
MAX7219-Baustein durcheinander kommt?

von google (Gast)


Lesenswert?

Die Leitungsführung auf dem Board erscheint suboptimal. Spendiere den 
Logik-Eingängen (DIN, CLK, LOAD) des MAX7219 mal Pullup-Widerstände.

von Max7219 (Gast)


Angehängte Dateien:

Lesenswert?

Wenn displaytest nicht richtig funktioniert läuft der max7219 nicht 
richtig.

Zum Verständnis und als Beispiel:

http://ee.cleversoul.com/max7219-source.html
********************************************

Anpassen an AVR :
***************
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>

von Constantin Alexandru M. (azzuro)


Lesenswert?

google schrieb:
> Die Leitungsführung auf dem Board erscheint suboptimal. Spendiere
> den
> Logik-Eingängen (DIN, CLK, LOAD) des MAX7219 mal Pullup-Widerstände.

Operation gelungen, Patient tot. :) Von VCC (Pin 19) bin ich mit 3 
Pull-Up-Widerständen a 10k auf DIN (Pin 1), LOAD (Pin 12) und CLK (Pin 
13) gegangen. Kein Erfolg, gleiches Fehlerbild.

: Bearbeitet durch User
von Dietrich L. (dietrichl)


Lesenswert?

google schrieb:
> Die Leitungsführung auf dem Board erscheint suboptimal.

Dem schließe ich mich an.
Allerdings fehlt mir ein ordentliches GND-Layout. Die GND-Leitungen sind 
so mickrig, dass beim Schalten der LEDs Spannungsabfälle am GND 
auftreten, die für ein ordentliche Kommunikation zu groß sein können.
Als ersten Test kannst Du mal den GND vom MAX mit dem GND vom µC mit 
einem "ordentlichen" Draht verbinden.
Ob das dann für die anderen Funktionen auch reichen wird, sei aber noch 
dahingestellt. Wenn nicht, dann wirst Du ein neues Layout oder ein 
zusätzliches GND-Netzwerk aus Draht brauchen.

Gruß Dietrich

von Constantin Alexandru M. (azzuro)


Lesenswert?

Dietrich L. schrieb:
> Als ersten Test kannst Du mal den GND vom MAX mit dem GND vom µC mit
> einem "ordentlichen" Draht verbinden.

Einen Draht habe ich nun vom MAX7219 (Pin 9) zum GND des uC's gezogen 
und der Fehler ist immer noch da. Aber das müsste nicht das Problem 
sein, ich hab bei der Layout-Erstellung noch einen GND Polygon über die 
ganze Platine gezogen.

: Bearbeitet durch User
von Constantin Alexandru M. (azzuro)


Lesenswert?

Bei mir ist die MISO des uC's sowohl für die ISP-Programmierung als auch 
für den MAX7219-Baustein als I/O-Pin (LOAD) zuständig. Könnte vielleicht 
bei der Programmierung dadurch der MAX7219-Baustein beeinflusst worden 
sein?

von asdfasd (Gast)


Lesenswert?

Die Software sieht funktionsfähig aus.

Die Hardware?  Naja.  Insbesondere der Kram rechts unten im Schaltplan 
ergibt überhaupt keinen Sinn: nen Poti am D-Eingang eines FF?!?  Der 
negierte Q an CLK der gleichzeitig auch noch vom 4093 getrieben wird 
(die treiben nun gegeneinander).  Das 2. FF flippt irgendwo rum (alle 
Eingänge unbeschaltet).  Ein Optokoppler der gleiche Potentiale koppelt. 
Und was soll die Block überhaupt erreichen?  Drei ICs um einen Takt an 
INT0/PD2 zu erzeugen?!?  Sind dir die Timer im Proz ausgegangen?

Btw, es wäre hilfreich, irgendwo auch mal Vcc zu spezifizieren - ich 
gehe von 5V aus, oder?  Wenn nicht, weisst du, warum der 7219 nicht 
will.

von asdfasd (Gast)


Lesenswert?

Was mir gerade noch auffällt: du scheinst nicht alle Vcc/GND Pins des 
Proz beschaltet zu haben ...

von Constantin Alexandru M. (azzuro)


Lesenswert?

@asdfasd

Du brauchst dir keine Sorgen um den unteren Schaltungsteil machen, das 
gehört nicht zu meiner oben definierten Frage und die Konzeption des 
Layouts ist logisch, da ich es vorher in anderen Gehversuche erfolgreich 
die Funktion testen konnte. Es handelt sich da nur um einen kapazitiven 
Taster mein junger Padawan. ;P

von Constantin Alexandru M. (azzuro)


Lesenswert?

Das ist doch egal mit dem uC, wenn da nur einmal VCC und GND 
angeschlossen sind. Die werden doch intern eh miteinander verbunden.

von asdfasd (Gast)


Lesenswert?

[der rechte untere Schaltungsblock]
> die Konzeption des Layouts ist logisch, da ich es vorher in anderen
> Gehversuche erfolgreich die Funktion testen konnte. Es handelt sich
> da nur um einen kapazitiven Taster

Über das Layout hab ich nichts gesagt, nur über die Schaltung an sich. 
Und ich bleibe dabei, sie ist Murks.

[nicht alle Vcc/GND-Pins angeschlossen]
> Das ist doch egal mit dem uC, wenn da nur einmal VCC und GND
> angeschlossen sind. Die werden doch intern eh miteinander verbunden.

Sagt wer?  Üblicherweise werden mehrere Vcc/GND-Pins eingesetzt, weil 
die interne Verdrahtung eben nicht ausreicht oder überhaupt vorhanden 
ist.

> mein junger Padawan

Das sagt der Richtige :-)

von Constantin Alexandru M. (azzuro)


Lesenswert?

Ich hab das Problem immer noch nicht gelöst und hab noch ein 
Fehlerprotokoll angelegt.

Fehlerprotokoll:
- Pull-up Widerstände DIN, CLK und LOAD
- Draht Masse uC <-> Masse MAX7219
- MAX7219 ausgewechselt
- Segmente sind neu
- Kurzschlussprüfung der einzelnen Segmente
- die 2 Kondensatoren hab ich noch raus genommen
- I_Set Widerstand über Poti verändert
- Messung von DIN, CLK und LOAD auf High- und Low-Pegel:
          |  Low  |  High  |
     -----------------------
     DIN  |  0V   | 4,995V |
     -----------------------
     CLK  |  0V   | 4,995V |
     -----------------------
     LOAD |  0V   | 4,995V |

Mir ist noch was aufgefallen, anscheinend wird das letzte Register- und 
Datenbit verschluckt. Im Programm sieht aber alles gut aus. Wie ist 
sowas nur möglich?

von Max7219 (Gast)


Angehängte Dateien:

Lesenswert?

C-Datei mit funktionierender static void Send( uint16_t data ) ergänzt.
init() abgeändert.
Auf Steckbrett gemäss typical application cirquit getestet.
Displaytest funktioniert und es zählt was.

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.