Forum: Mikrocontroller und Digitale Elektronik wieder mal MAX7219 (Problem mit Programm oder Schaltung?)


von Martin B. (methusalem)


Lesenswert?

Moin,

ich bin nun seid zwei Tagen schon am rumprobieren und lese hier im Forum 
alles mögliche.

Ich habe einen ATmega8515 auf einem STK500 Board. Die LEDs des Boards 
sind mit Port C verbunden. Pin PB7 ist am Pin 13 (CLK) vom MAX7219. Pin 
PB5 am Pin 1 des MAX und Pin PB3 (LOAD) am Pin 12 des MAX. Ist also so 
verkabelt wie im Datenblatt des MAX auf seite 1 unten rechts.

Dann bin ich beim suchen auf diesen Beitrag gestoßen: 
Beitrag "MAX 7219 mit SPI ansteuern?"
Da hab ich dann einfach mal den Quelltext kopiert und an meinen 
ATmega8515 angepasst (PB3 statt PB2).

+5 Volt und GND werden auch vom STK500 zum MAX geholt.

Ich sende in meiner main() nur den Code für den LED Test an den MAX. 
Aber es bleibt alles dunkel. Ich hab die Schaltung jetzt schon zwei mal 
kontrolliert, kann aber keinen Fehler finden.

Da der kopierte Code ja bei Christian funktioniert und meine LEDs auch 
blinken (das Programm also offensichtlich durchläuft) tippe ich auf ne 
kaputte Schaltung oder einen Gedankenfehler beim initialisieren des MAX.

Gibts ne Möglichkeit die Schaltung zu testen?
1
#include <avr/io.h>
2
#include <avr/delay.h>
3
4
void SPI_MasterInit(void)
5
{
6
    /* LOAD (DDB3), MOSI (DDB5) und SCK (DDB7) als Ausgänge schalten */
7
  DDRB = (1<<DDB3)|(1<<DDB5)|(1<<DDB7);
8
9
    /* SPI einschalten, SPI Master aktivieren, Frequenz auf fck/16 */
10
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
11
12
    /* PullUp Wiederstände an SCK und SS aktivieren */
13
    PORTB |= (1 << PB5)|(1 << PB3);
14
}
15
16
void SPI_Transmit(char addr, char data) {
17
  PORTB &= ~(1 << PB3);         // LOAD auf low setzen
18
19
  SPDR = addr;                  // Byte in Register schreiben und damit Übertragung starten
20
  while(!(SPSR & (1<<SPIF)));   // Warten, bis SPIF gesetzt ist
21
  
22
  SPDR = data;                  // Byte in Register schreiben und damit Übertragung starten
23
  while(!(SPSR & (1<<SPIF)));   // Warten, bis SPIF gesetzt ist
24
25
  PORTB |= (1 << PB3);          // LOAD auf high setzen
26
}
27
 
28
int main (void) {
29
 
30
    DDRC  = 0xff;               // PORT C als Ausgang schalten
31
    PORTC = 0x00;               // alle LEDs an (invertiert wegen STK500)
32
33
    _delay_ms(1000);            // Pause
34
35
  SPI_MasterInit();           // SPI initialisieren
36
  SPI_Transmit(0x0F,0x00);    // Daten senden
37
   
38
    while(1){
39
        PORTC = 0xAA;           // LEDs blinken im wechsel
40
        _delay_ms(500); 
41
        PORTC = 0x55;
42
        _delay_ms(500); 
43
    };
44
45
    return 0;
46
}

von ... (Gast)


Lesenswert?

du solltest den 7219 erstmal initialisieren, ungefähr so:
1
.....
2
void max7219_Init(void) {
3
  transmit(0x0C,0x01);  // normal mode
4
  transmit(0x0A,0x01);  // set intensity 0x00 - 0x0F
5
  transmit(0x0B,0x07);  // scan digits 0-7, entsprechend deiner Schaltung
6
  transmit(0x09,0x00);  // no decoding, entsprechend deiner Schaltung
7
}
8
int main (void) {
9
 
10
    DDRC  = 0xff;               // PORT C als Ausgang schalten
11
    PORTC = 0x00;               // alle LEDs an (invertiert wegen STK500)
12
13
    _delay_ms(1000);            // Pause
14
15
  SPI_MasterInit();           // SPI initialisieren
16
  max7219_Init();
17
  SPI_Transmit(0x0F,0x00);    // Daten senden
18
......

von ... (Gast)


Lesenswert?

transmit heißt bei dir natürlich SPI_Transmit

von Martin B. (methusalem)


Lesenswert?

OK, Danke für den Hinweis. Das ist natürlich selten dämlich von mir. Da 
mach ich mir die ganze Zeit Gedanken über das initieren des ATmega und 
vergesse den MAX dabei.

Ich hab das jetzt nachgeholt und es hat sich was getan. Leider nicht 
das, was ich erwartet habe.

Wenn das Programm startet, dann leuchten erst alle LEDs an Port C des 
µC. Dann wird der 8515 und danach der MAX initialisiert. Dann sieht man, 
wie bei den 7-Segment Anzeigen kurz ein paar Segmente aufblinken. Das 
sind immer unterschiedliche. Und danach sind die auch sofort wieder 
dunkel.

Danach blinken dann die LEDs an Port C des µC wieder. Also bin ich in 
der Endlosschleife der main() angekommen.

Woran kann das jetzt liegen? Hat jemand ne Idee, wie ich den MAX testen 
kann?

Hier noch mal mein abgeänderter Code:
1
#include <avr/io.h>
2
3
#ifndef F_CPU
4
#define F_CPU 1843200
5
#endif
6
7
#include <util/delay.h>
8
9
void SPI_MasterInit(void)
10
{
11
    /* LOAD (DDB3), MOSI (DDB5) und SCK (DDB7) als Ausgänge schalten */
12
  DDRB = (1<<DDB3)|(1<<DDB5)|(1<<DDB7);
13
14
    /* SPI einschalten, SPI Master aktivieren, Frequenz auf fck/16 */
15
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
16
17
    /* PullUp Wiederstände an SCK und SS aktivieren */
18
    PORTB |= (1 << PB5)|(1 << PB3);
19
}
20
21
void SPI_Transmit(char addr, char data) {
22
    
23
    PORTB &= ~(1 << PB3);         // LOAD auf low setzen
24
25
    SPDR = addr;                  // Byte in Register schreiben und damit Übertragung starten
26
    while(!(SPSR & (1<<SPIF)));   // Warten, bis SPIF gesetzt ist
27
  
28
    SPDR = data;                  // Byte in Register schreiben und damit Übertragung starten
29
    while(!(SPSR & (1<<SPIF)));   // Warten, bis SPIF gesetzt ist
30
31
    PORTB |= (1 << PB3);          // LOAD auf high setzen
32
}
33
34
void max7219_Init(void) {
35
    SPI_Transmit(0x0C,0x01);  // normal mode
36
    SPI_Transmit(0x0A,0x08);  // set intensity 0x08
37
    SPI_Transmit(0x0B,0x01);  // scan digits 0-1
38
    SPI_Transmit(0x09,0xFF);  // Code B for all
39
}
40
41
int main (void) {
42
 
43
    DDRC  = 0xff;               // PORT C als Ausgang schalten
44
    PORTC = 0x00;               // alle LEDs an (invertiert wegen STK500)
45
46
    _delay_ms(1000);            // Pause
47
48
  SPI_MasterInit();           // SPI initialisieren
49
    max7219_Init();             // MAX initialisieren
50
51
  SPI_Transmit(0x01,0x01);    // Digit 1 auf Zahl 1
52
    SPI_Transmit(0x02,0x02);    // Digit 2 auf Zahl 2
53
54
    while(1){
55
        PORTC = 0xAA;           // LEDs blinken im wechsel
56
        _delay_ms(500); 
57
        PORTC = 0x55;
58
        _delay_ms(500); 
59
    };
60
61
    return 0;
62
}

von ... (Gast)


Lesenswert?

Martin Brehme schrieb:
> Pin PB3 (LOAD)

PB3 ist nicht der SS-Pin der SPI Einheit im ATmega8515.
Das kannst du natürlich so machen, musst aber dafür Sorge tragen, dass 
der SS-Pin des ATmega8515 (PB4) auf 1-Potential liegt, ansonsten 
schaltet die SPI-Einheit in den Slave-Modus.
1
/* LOAD (DDB3), MOSI (DDB5) und SCK (DDB7) als Ausgänge schalten */
2
    DDRB = (1<<DDB3)|(1<<DDB5)|(1<<DDB7)|(1<<DDB4);
3
 /* PullUp Widerstände an SCK und SS und PB3 aktivieren */
4
    PORTB |= (1 << PB5)|(1 << PB3)|(1 << PB4);

von ... (Gast)


Lesenswert?

btw. es ist immens wichtig, das direkt an dem V+ -Pin gegen GND-Pin des 
Max ein 10µF Kondensator geschaltet ist. Ansonsten macht der 7219 was er 
will.

von Martin B. (methusalem)


Lesenswert?

Danke für die beiden Hinweise. Das mit dem SS auf high hab ich - jetzt 
wo du es schreibst - irgendwo gelesen, aber leider nicht mehr auf dem 
Schirm gehabt.

Das mit dem Kondensator ist mir neu. Aber auch das werde ich heute abend 
ausprobieren.

Martin

von Martin B. (methusalem)


Lesenswert?

Hallo " ... (Gast) ",

sollten wir uns mal über den Weg laufen, erinner mich drann, das du ein 
Bier von mir bekommst. Der Kondensator wars! Man was hat mich das Nerven 
gekostet :-)

Nun gut. Nun kanns ja weitergehen ...

von ... (Gast)


Lesenswert?

Hallo Martin,

schön das es  jetzt funktioniert.

Das mit dem Kondensator steht aber auch im Datenblatt:

"Applications Information

Supply Bypassing and Wiring

To minimize power-supply ripple due to the peak digit
driver currents, connect a 10µF electrolytic and a 0.1µF
ceramic capacitor between V+ and GND as close to
the device as possible. The MAX7219/MAX7221 should
be placed in close proximity to the LED display, and
connections should be kept as short as possible to
minimize the effects of wiring inductance and electro-
magnetic interference. Also, both GND pins must be
connected to ground."

von Martin B. (methusalem)


Lesenswert?

Tja, was lerne ich daraus: In E-Technik bin ich noch schlechter als im 
programmieren :-)

Ich werd wohl die Datenblätter demnächst nur noch mit nem Textmarker in 
der Hand lesen - ich hab das echt nicht mehr auf dem Schirm gehabt.

von ... (Gast)


Lesenswert?

Martin Brehme schrieb:
> Tja, was lerne ich daraus: In E-Technik bin ich noch schlechter als im
> programmieren :-)

Jetzt aber nicht verzweifeln, zur Not gibt es ja noch so alte Männer wie 
mich und das Forum hier... ;)

von Martin B. (methusalem)


Lesenswert?

... schrieb:
> Martin Brehme schrieb:
>> Tja, was lerne ich daraus: In E-Technik bin ich noch schlechter als im
>> programmieren :-)
>
> Jetzt aber nicht verzweifeln, zur Not gibt es ja noch so alte Männer wie
> mich und das Forum hier... ;)

Ne, wenn ich verzweifeln würde, hätte ich den Smilie weggelassen. 
Allerdings hat mir das jetzt deutlich meine Grenzen in der E-Technik 
aufgezeigt. Ich bin aber froh, das ich nun endlich - nach langer Pause - 
wieder am µContrller sitze.

Die nächsten Fragen sammeln sich hier schon ... dann aber in nem neuen 
Thread.

von ... (Gast)


Lesenswert?

[Neugier an]
Darf man fragen, was das werden soll?
[Neugier aus]

von Martin B. (methusalem)


Lesenswert?

Das Anzeigen von Daten auf den 7 Segment Bausteinen war ein Einstieg in 
die AVR µController für mich. Das geht auch noch weiter ... nebenher 
acker ich die Tutorials hier durch.

Ziel ist das hier: Beitrag "Konzept zum Auswerten von Lichtschranken gesucht"

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.