wieder mal MAX7219 (Problem mit Programm oder Schaltung?)

OP #1557952
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
}
Gast #1558011
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
......
OP #1558729
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
}
Gast #1558812
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);
Gast #1560049
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."
Gast #1560108
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... ;)
OP #1560318
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren