C 8x8 LED Matrix mit Max7219 ansteuern

bentiaci

Neues Mitglied
11. Dez. 2013
13
0
0
Sprachen
Hallo zusammen,
ich hoffe ich bin hier richtig...dies ist mein erstes teilnahme in diesem forum.
ich möchte anhand mehrere 8x8 Led Matrix Module ein Led Dispaly realisieren!
für meine Display benutze ich ein ATmega32 und die Module werden durch Max7219 angesteuert und das ganze mit C geschrieben.
ich habe versucht die datasheet vom max7219 richtig zu studieren und ein klein versuch gestartet! leider geling mir nicht mein Module zum leutchten zu bringen!!
es wäre nett wenn jmd mein code liest und mir meinem Fehler zeigt.
Vielen dank im Voraus .

Max7219 datasheet:

http://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf


Code:
/*
 
#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

#define PIN_SCK                   PORTB5
#define PIN_MOSI                  PORTB7
#define PIN_SS                    PORTB2
 
#define ON                        1
#define OFF                       0
 
#define MAX7219_LOAD1             PORTB |= (1<<PIN_SS)
#define MAX7219_LOAD0             PORTB &= ~(1<<PIN_SS)
 
#define MAX7219_MODE_DECODE       0x09
#define MAX7219_MODE_INTENSITY    0x0A
#define MAX7219_MODE_SCAN_LIMIT   0x0B
#define MAX7219_MODE_POWER        0x0C
#define MAX7219_MODE_TEST         0x0F
#define MAX7219_MODE_NOOP         0x00

unsigned char i;
unsigned char j;

 static uint8_t disp1[36][8] PROGMEM ={
	{0B00111000, 0B01000100, 0B01001100, 0B01010100, 0B01100100, 0B01000100, 0B00111000, 0B00000000}, //0
	{0B00010000, 0B00110000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00111000, 0B00000000},//1
	{0B00111000, 0B01000100, 0B00000100, 0B00001000, 0B00010000, 0B00100000, 0B01111100, 0B00000000}, //2
	{0B01111100, 0B00001000, 0B00010000, 0B00001000, 0B00000100, 0B01000100, 0B00111000, 0B00000000}, //3
	{0B00001000, 0B00011000, 0B00101000, 0B01001000, 0B01111100, 0B00001000, 0B00001000, 0B00000000}, //4
	{0B01111100, 0B01000000, 0B01111000, 0B00000100, 0B00000100, 0B01000100, 0B00111000, 0B00000000}, //5
	{0B00011000, 0B00100000, 0B01000000, 0B01111000, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //6
	{0B01111100, 0B01000100, 0B00000100, 0B00001000, 0B00010000, 0B00010000, 0B00010000, 0B00000000}, //7
	{0B00111000, 0B01000100, 0B01000100, 0B00111000, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //8
	{0B00111000, 0B01000100, 0B01000100, 0B00111100, 0B00000100, 0B00001000, 0B00110000, 0B00000000}, //9
	{0B00010000, 0B00101000, 0B01000100, 0B01000100, 0B01111100, 0B01000100, 0B01000100, 0B00000000}, //A
	{0B01111000, 0B01000100, 0B01000100, 0B01111000, 0B01000100, 0B01000100, 0B01111000, 0B00000000}, //B
	{0B00111000, 0B01000100, 0B01000000, 0B01000000, 0B01000000, 0B01000100, 0B00111000, 0B00000000}, //C
	{0B01110000, 0B01001000, 0B01000100, 0B01000100, 0B01000100, 0B01001000, 0B01110000, 0B00000000}, //D
	{0B01111100, 0B01000000, 0B01000000, 0B01111000, 0B01000000, 0B01000000, 0B01000000, 0B00000000}, //F
	{0B00111000, 0B01000100, 0B01000000, 0B01011100, 0B01000100, 0B01000100, 0B00111100, 0B00000000}, //G
	{0B01000100, 0B01000100, 0B01000100, 0B01111100, 0B01000100, 0B01000100, 0B01000100, 0B00000000}, //H
	{0B00111000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00111000, 0B00000000}, //I
	{0B00011100, 0B00001000, 0B00001000, 0B00001000, 0B00001000, 0B01001000, 0B00110000, 0B00000000}, //J
	{0B01000100, 0B01001000, 0B01010000, 0B01100000, 0B01010000, 0B01001000, 0B01000100, 0B00000000}, //K
	{0B01000000, 0B01000000, 0B01000000, 0B01000000, 0B01000000, 0B01000000, 0B01111100, 0B00000000}, //L
	{0B01000100, 0B01101100, 0B01010100, 0B01010100, 0B01000100, 0B01000100, 0B01000100, 0B00000000}, //M
	{0B01000100, 0B01000100, 0B01100100, 0B01010100, 0B01001100, 0B01000100, 0B01000100, 0B00000000}, //N
	{0B00111000, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //O
	{0B01111000, 0B01000100, 0B01000100, 0B01111000, 0B01000000, 0B01000000, 0B01000000, 0B00000000}, //P
	{0B00111000, 0B01000100, 0B01000100, 0B01000100, 0B01010100, 0B01001000, 0B00110100, 0B00000000}, //Q
	{0B00111000, 0B01000100, 0B01000100, 0B01111000, 0B01010000, 0B01001000, 0B01000100, 0B00000000}, //R
	{0B00111000, 0B01000100, 0B01000000, 0B00111000, 0B00000100, 0B01000100, 0B00111000, 0B00000000}, //S
	{0B01111100, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00000000}, //T
	{0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //U
	{0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B00101000, 0B00010000, 0B00000000}, //V
	{0B01000100, 0B01000100, 0B01000100, 0B01010100, 0B01010100, 0B01010100, 0B00101000, 0B00000000}, //W
	{0B01000100, 0B01000100, 0B00101000, 0B00010000, 0B00101000, 0B01000100, 0B01000100, 0B00000000}, //X
	{0B01000100, 0B01000100, 0B01000100, 0B00101000, 0B00010000, 0B00010000, 0B00010000, 0B00000000}, //Y
	{0B01111100, 0B00000100, 0B00001000, 0B00010000, 0B00100000, 0B01000000, 0B01111100, 0B00000000}, //Z*/
};


void spiSendByte (uint8_t databyte)
{
    // Daten Kopieren in die SPI-Datenregister
    SPDR = databyte;
    // Warten bis die Übertragung abgeschlossen ist
    while (!(SPSR & (1 << SPIF)));
}
 
void MAX7219_writeData(uint8_t data_register, uint8_t data)
{
    MAX7219_LOAD0;
        // Senden an das Register, in dem die Daten gespeichert werden
        spiSendByte(data_register);
        // Senden  die zu speichernden Daten
        spiSendByte(data);
    MAX7219_LOAD1;
}


//initialisieren 1 chip
void max7219_init1()
{
	MAX7219_LOAD0;
	  MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
	  MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
	  MAX7219_writeData(MAX7219_MODE_INTENSITY, 0x0f);
	  MAX7219_writeData(MAX7219_MODE_POWER, ON); 
	  MAX7219_writeData(MAX7219_MODE_TEST, 0x00); 
	  
	MAX7219_LOAD1;
	
} 

int main(void)
{
    // SCK MOSI CS/LOAD/SS
    DDRB |= (1 << PIN_SCK) | (1 << PIN_MOSI) | (1 << PIN_SS);
 
    // SPI aktivieren, Master-Modus
    SPCR |= (1 << SPE) | (1 << MSTR)| (1<<SPR1);
    
	// Alle 3 Module initialisieren
	 max7219_init1();
	
	  while(1){
	     for(j=0;j<36;j++)
		 {
		 for(i=1;i<9;i++)
		 MAX7219_writeData(i,disp1[j][i-1]);
		 _delay_ms(500);
		 }
	  }
		return 0;
}
 
Hallo und willkommen im Forum.

Du verwendet Hardware SPI, MOSI und SCK sind hier wichtig, die Signale liegen bei dem ATmega32 auf PB5 und PB7. Hast du das so angeschlossen? Bei deinen defines sind andere Pins definiert. Dann würde ich nochmal den verwendeten SPI Mode über prüfen, ob dieser zum Display controller passt.

Ich bin jetzt leider nicht mehr an meinem Rechner und kann leider im Moment nicht so einfach im Datenblatt nach schauen.

Noch ein Hinweis. Du benötigt für das Array viel SRAM, am besten Legat du dieses in das FLASH Memory (progmem) .

Dirk :ciao:
 
Code geändert!

Hallo Dirk,
Vielen Dank für deine Hilfe! ich habe deine Hinweise in meinem Code geändert...
ist das richtig ich dass ich <avr/pgmspace.h> einbinden soll für PROGMEM?
ich habe mein AVR board gerade nicht dabei zum nachprüfen ob alles funktioniert, werde ich aber morgen testen.
nochmal Vielen Dank Dirk:)
 
Hallo Dirk,
bist du bitte nett wenn du Zeit hast und schaust in Max7219 Datasheet nach wie ich dieser Baustein initialisiere wenn ich meherer kaskadiere?
ich verstehe das nähmlich nicht richtig....hier ist mein vorschlag:
Code:
/*
 

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>


 

#define PIN_SCK                   PORTB5
#define PIN_MOSI                  PORTB7
#define PIN_SS                    PORTB2
 
#define ON                        1
#define OFF                       0
 
#define MAX7219_LOAD1             PORTB |= (1<<PIN_SS)
#define MAX7219_LOAD0             PORTB &= ~(1<<PIN_SS)
 
#define MAX7219_MODE_DECODE       0x09
#define MAX7219_MODE_INTENSITY    0x0A
#define MAX7219_MODE_SCAN_LIMIT   0x0B
#define MAX7219_MODE_POWER        0x0C
#define MAX7219_MODE_TEST         0x0F
#define MAX7219_MODE_NOOP         0x00

unsigned char i;
unsigned char j;

 static uint8_t disp1[36][8] PROGMEM ={
	{0B00111000, 0B01000100, 0B01001100, 0B01010100, 0B01100100, 0B01000100, 0B00111000, 0B00000000}, //0
	{0B00010000, 0B00110000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00111000, 0B00000000},//1
	{0B00111000, 0B01000100, 0B00000100, 0B00001000, 0B00010000, 0B00100000, 0B01111100, 0B00000000}, //2
	{0B01111100, 0B00001000, 0B00010000, 0B00001000, 0B00000100, 0B01000100, 0B00111000, 0B00000000}, //3
	{0B00001000, 0B00011000, 0B00101000, 0B01001000, 0B01111100, 0B00001000, 0B00001000, 0B00000000}, //4
	{0B01111100, 0B01000000, 0B01111000, 0B00000100, 0B00000100, 0B01000100, 0B00111000, 0B00000000}, //5
	{0B00011000, 0B00100000, 0B01000000, 0B01111000, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //6
	{0B01111100, 0B01000100, 0B00000100, 0B00001000, 0B00010000, 0B00010000, 0B00010000, 0B00000000}, //7
	{0B00111000, 0B01000100, 0B01000100, 0B00111000, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //8
	{0B00111000, 0B01000100, 0B01000100, 0B00111100, 0B00000100, 0B00001000, 0B00110000, 0B00000000}, //9
	{0B00010000, 0B00101000, 0B01000100, 0B01000100, 0B01111100, 0B01000100, 0B01000100, 0B00000000}, //A
	{0B01111000, 0B01000100, 0B01000100, 0B01111000, 0B01000100, 0B01000100, 0B01111000, 0B00000000}, //B
	{0B00111000, 0B01000100, 0B01000000, 0B01000000, 0B01000000, 0B01000100, 0B00111000, 0B00000000}, //C
	{0B01110000, 0B01001000, 0B01000100, 0B01000100, 0B01000100, 0B01001000, 0B01110000, 0B00000000}, //D
	{0B01111100, 0B01000000, 0B01000000, 0B01111000, 0B01000000, 0B01000000, 0B01000000, 0B00000000}, //F
	{0B00111000, 0B01000100, 0B01000000, 0B01011100, 0B01000100, 0B01000100, 0B00111100, 0B00000000}, //G
	{0B01000100, 0B01000100, 0B01000100, 0B01111100, 0B01000100, 0B01000100, 0B01000100, 0B00000000}, //H
	{0B00111000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00111000, 0B00000000}, //I
	{0B00011100, 0B00001000, 0B00001000, 0B00001000, 0B00001000, 0B01001000, 0B00110000, 0B00000000}, //J
	{0B01000100, 0B01001000, 0B01010000, 0B01100000, 0B01010000, 0B01001000, 0B01000100, 0B00000000}, //K
	{0B01000000, 0B01000000, 0B01000000, 0B01000000, 0B01000000, 0B01000000, 0B01111100, 0B00000000}, //L
	{0B01000100, 0B01101100, 0B01010100, 0B01010100, 0B01000100, 0B01000100, 0B01000100, 0B00000000}, //M
	{0B01000100, 0B01000100, 0B01100100, 0B01010100, 0B01001100, 0B01000100, 0B01000100, 0B00000000}, //N
	{0B00111000, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //O
	{0B01111000, 0B01000100, 0B01000100, 0B01111000, 0B01000000, 0B01000000, 0B01000000, 0B00000000}, //P
	{0B00111000, 0B01000100, 0B01000100, 0B01000100, 0B01010100, 0B01001000, 0B00110100, 0B00000000}, //Q
	{0B00111000, 0B01000100, 0B01000100, 0B01111000, 0B01010000, 0B01001000, 0B01000100, 0B00000000}, //R
	{0B00111000, 0B01000100, 0B01000000, 0B00111000, 0B00000100, 0B01000100, 0B00111000, 0B00000000}, //S
	{0B01111100, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00010000, 0B00000000}, //T
	{0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B00111000, 0B00000000}, //U
	{0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B01000100, 0B00101000, 0B00010000, 0B00000000}, //V
	{0B01000100, 0B01000100, 0B01000100, 0B01010100, 0B01010100, 0B01010100, 0B00101000, 0B00000000}, //W
	{0B01000100, 0B01000100, 0B00101000, 0B00010000, 0B00101000, 0B01000100, 0B01000100, 0B00000000}, //X
	{0B01000100, 0B01000100, 0B01000100, 0B00101000, 0B00010000, 0B00010000, 0B00010000, 0B00000000}, //Y
	{0B01111100, 0B00000100, 0B00001000, 0B00010000, 0B00100000, 0B01000000, 0B01111100, 0B00000000}, //Z*/
};


void spiSendByte (uint8_t databyte)
{
    // Daten Kopieren in die SPI-Datenregister
    SPDR = databyte;
    // Warten bis die Übertragung abgeschlossen ist
    while (!(SPSR & (1 << SPIF)));
}
 
void MAX7219_writeData(uint8_t data_register, uint8_t data)
{
    MAX7219_LOAD0;
        // Senden an das Register, in dem die Daten gespeichert werden
        spiSendByte(data_register);
        // Senden  die zu speichernden Daten
        spiSendByte(data);
    MAX7219_LOAD1;
}


//initialisieren 1 chip
void max7219_init1()
{
	MAX7219_LOAD0;
	  MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
	  MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
	  MAX7219_writeData(MAX7219_MODE_INTENSITY, 0x0f);
	  MAX7219_writeData(MAX7219_MODE_POWER, ON); 
	  //MAX7219_writeData(MAX7219_MODE_TEST, 0x00); 
	  
	MAX7219_LOAD1;
	
} 


/*
//initialisieren 2 chip
void max7219_init2()
{
	MAX7219_LOAD0;
	MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);	 
	MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);	 
	MAX7219_writeData(MAX7219_MODE_INTENSITY, 0x0f);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_writeData(MAX7219_MODE_POWER, ON);
    MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	//MAX7219_writeData(MAX7219_MODE_TEST, 0x00); 
	//MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_LOAD1;
	
}

//initialisieren 3 chip
void max7219_init3()
{
	MAX7219_LOAD0;
	MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);	
	MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_writeData(MAX7219_MODE_INTENSITY, 0x0f);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_writeData(MAX7219_MODE_POWER, ON);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	//MAX7219_writeData(MAX7219_MODE_TEST, 0x00);
	//MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	//MAX7219_writeData(MAX7219_MODE_NOOP, 0x00);
	MAX7219_LOAD1;
	
}
*/


 
int main(void)
{
    // SCK MOSI CS/LOAD/SS
    DDRB |= (1 << PIN_SCK) | (1 << PIN_MOSI) | (1 << PIN_SS);
 
    // SPI aktivieren, Master-Modus
    SPCR |= (1 << SPE) | (1 << MSTR)| (1<<SPR1);
    
	// Alle 3 Module initialisieren
	 max7219_init1();
	// max7219_init2();
	// max7219_init3();
	  while(1){
	     for(j=0;j<36;j++)
		 {
		 for(i=1;i<9;i++)
		 MAX7219_writeData(i,disp1[j][i-1]);
		 _delay_ms(500);
		 }
		 
		
		
	
	  }
		
	 
	 return 0;
}
 
Hallo bentiaci,

ich kann mir das am Wochenende anschauen, heute klappt es nicht mehr. Vielleicht kann aber auch ein anderes Forenmitglied vorab helfen.

Dirk :ciao:
 
Ich habe mir gerade deinen Soucecode angeschaut...

Jeder LED-Controller besitzt ein 16bit Schieberegister. Sind die Controller nacheinander kaskadiert und haben sie alle das selbe CS\ bzw. LOAD Signal, dann werden immer 64 Bit durchgeschoben.

CS\ auf low (LOAD)
2 Byte für den letzten kaskadierten Controller schieben
2 Byte für den vorletzten Controller schieben
2 Byte für den zweiten
2 Byte für den ersten Controller
CS\ auf high (LOAD)

Die Werte für die Initialisierung habe ich mir nicht angesehen. Vielleicht hilft dir das ja schon mal weiter.

Dirk :ciao:
 
Ich habe mir gerade deinen Soucecode angeschaut...

Jeder LED-Controller besitzt ein 16bit Schieberegister. Sind die Controller nacheinander kaskadiert und haben sie alle das selbe CS\ bzw. LOAD Signal, dann werden immer 64 Bit durchgeschoben.

CS\ auf low (LOAD)
2 Byte für den letzten kaskadierten Controller schieben
2 Byte für den vorletzten Controller schieben
2 Byte für den zweiten
2 Byte für den ersten Controller
CS\ auf high (LOAD)

Die Werte für die Initialisierung habe ich mir nicht angesehen. Vielleicht hilft dir das ja schon mal weiter.

Dirk :ciao:

Hallo Dirk,
ich bin dir sehr dankbar für deine Hilfe!
also ich habe es auch so verstanden wie du es gerade beschrieben hast nun ich frage mich ob ich das richtig programmiert habe in C ich studiere nähmlich elektrotechnik aber ich hatte leider nur wenige seminare was C und microkontroller angeht und muss ein Projekt fertig machen.
abgesehen davon ob die initialisierungswerte für die module stimmen oder nicht habe ich dann die allgemeine initialitierung richtig programmiert? No op Register ist gedacht für Kaskadierung!! habe ich das jedes mal richtig programmiert?ich muss nähmlich 16 Module kaskadieren bzw ein Led Display mit 16 8x8 led Matrix also 2 zeilen je 8 zeichen!!
danke im Voraus
Gruß bentiaci
 
Nur ganz kurz, da ich gleich nicht mehr online bin.

Aktuell verwendest du diese Routine ...


Code:
void max7219_init1()
{
MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_INTENSITY, 0x0f);
MAX7219_writeData(MAX7219_MODE_POWER, ON); 
//MAX7219_writeData(MAX7219_MODE_TEST, 0x00); 
MAX7219_LOAD1;
}



Du überträgst hier zwar 4 mal 2 Byte, allerdings bekommt ja nicht jeder einzelne Controller alles mit. Du musst es bei 4 Controllern so übertragen ...

Code:
void max7219_init1()
{
MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den letzten Controller
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den ersten Controller
MAX7219_LOAD1;

MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_LOAD1;

// usw. ...

}
 
ich glaube ich habe das doch nicht richtig verstanden gehabt aber bei dir fehlt auch die no op register für die kaskadierten Controller!
ok vielen Dank für deine Hinweise...ich werde mich gleich damit weiter beschäftigen und wenn du irgendwann wieder lust und zeit online zu kommen können wir darüber weiter diskutieren.
ich wünsche Dir einen angenehmen Tag
Gruß bentiaci
 
Ok, du hast recht. Ich habe das Datenblatt nur überflogen, wegen Zeitmangel, sorry :rolleyes: ...


No-Op Register
The no-op register is used when cascading MAX7219s
or MAX7221s. Connect all devices’ LOAD/CS inputs
together and connect DOUT to DIN on adjacent
devices. DOUT is a CMOS logic-level output that easily
drives DIN of successively cascaded parts. (Refer to
the Serial Addressing Modes section for detailed information
on serial input/output timing.) For example, if
four MAX7219s are cascaded, then to write to the
fourth chip, sent the desired 16-bit word, followed by
three no-op codes (hex 0xXX0X, see Table 2). When
LOAD/CS goes high, data is latched in all devices. The
first three chips receive no-op commands, and the
fourth receives the intended data.


Ich schau mir das später nochmal genauer an.

Im Forum ist der Controller schon ein paarmal Thema gewesen, allerdings oft in Verbindung mit Bascom, was aber nun prinzipiel sicher kein Problem ist, wenn es um das Protokoll geht.

Ich denke mal Cassio hat hier schon ein Projekt damit gemacht.
 
Hallo Dirk ,
ok mach mal bitte in Ruhe deine Sachen und schreib mir wenn du mal zeit und lust hast denn ich alleine komme ich leider nicht weiter....ich hoffe dass sich irgendwann cassio meldet und sich hier seine Hilfe bittet!
Vielen Dank
Gruß bentiaci
 
Hmmm, es stimmt ja soweit. NoOp benötigt man nur, wenn man zum Beispiel nur (!) am letzten Controller etwas einstellen möchte, an den anderen aber nicht. Dann sendet man ...

  1. CS\ low
  2. Daten / Einstellung für den letzten Controller
  3. NoOp dreimal (für die ersten drei Controller)
  4. CS\ high


Probiere es einfach mal aus.

Ich schau dann später noch mal genauer.
Dirk :ciao:
 
Hallo,

eigentlich ist das aus dem Datenblatt doch recht gut ersichtlich ...

MAX7219-Block.png . MAX7219-Register.png

Wenn man bei dem Word (16Bit) die Bits 8-11 auf Null läßt, dann interessiert sich der MAX7219 nicht für die reingeschobenen Daten. Damit wird das als reine "Fülldaten" interpretiert um die interessanten Daten zum richtigen Chip durchschieben zu können.

Gruß
Dino
 
Wenn man bei dem Word (16Bit) die Bits 8-11 auf Null läßt, dann interessiert sich der MAX7219 nicht für die reingeschobenen Daten. Damit wird das als reine "Fülldaten" interpretiert um die interessanten Daten zum richtigen Chip durchschieben zu können.

Ja genau. Aber man muss aber nicht unbedingt mit NoOp Kommando arbeiten, wenn man bei jedem Controller Einstellungen vornehmen oder Anzeigedaten ändern möchte ?! ...

zum Beispiel:
Code:
void max7219_init1()
{
MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den letzten Controller
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den ersten Controller
MAX7219_LOAD1;

MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_LOAD1;

// usw. ...

}
 
Ja genau. Aber man muss aber nicht unbedingt mit NoOp Kommando arbeiten, wenn man bei jedem Controller Einstellungen vornehmen oder Anzeigedaten ändern möchte ?! ...

zum Beispiel:
Code:
void max7219_init1()
{
MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den letzten Controller
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den ersten Controller
MAX7219_LOAD1;

MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_LOAD1;

// usw. ...

}
heisst das wenn ich mein 2x8 led display (2 zeilen je 8 zeichen "8x8 led Matrix für jedes Zeichen") habe und möchte z.B "Hello world" ausgeben! verzichte ich auf no op Register und muss nur 16 mal die andere Register initialisieren wie oben geschrieben ist also:

void max7219_init1()
{
MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den letzten Controller
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
MAX7219_writeData(MAX7219_MODE_DECODE, 0x00);
.
.
.

MAX7219_writeData(MAX7219_MODE_DECODE, 0x00); // für den ersten Controller
MAX7219_LOAD1;

MAX7219_LOAD0;
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
.
.
.
.
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_writeData(MAX7219_MODE_SCAN_LIMIT, 0x07);
MAX7219_LOAD1;

// usw. ...

Danke im Voraus
Gruß bentiaci
 
Also so wie ich das verstehe, machst du ja die Initialisierung einmalig, das heißt du stellst bei jedem Displaycontroller folgendes ein ...

  • Decode Mode
  • Scan Limit
  • Intensity
  • Scan Limit

Du kannst dir sicherlich erst einmal einen Displaycontroller vornehmen und für die anderen sendest du NoOp Kommando. Ich denke aber das musst du nicht machen.

Du sendest hier zunächst den Decode Mode für alle Controller ..

CS\ low
DecodeMode (letzer Controller)
DecodeMode
DecodeMode
DecodeMode (erster Controller)
CS\ high

Danach 4 mal Scan limit usw.


Es sind also 4 Datenpakete zusenden. Keine NoOp.

Die Controller sind dann konfiguriert. Was du vielleicht später mal änderst ist Intensity oder ShutDown/NormalOperation.

---

Wenn du Segmentdaten änderst, betrifft das ja nicht unbedingt alle Segmente, bzw. Digits. Für die Controller, bei denen sich nichts ändert kannst du dass NoOp senden. Ich würde mir im Mikrocontroller erst mal ein Array erstellen, was alle Digits/Zeilen (oder je nachdem wir du es angeschlossen hast) beinhaltet. Und das Array erst einmal komplett übertragen.

Dirk :ciao:
 
Also so wie ich das verstehe, machst du ja die Initialisierung einmalig, das heißt du stellst bei jedem Displaycontroller folgendes ein ...

  • Decode Mode
  • Scan Limit
  • Intensity
  • Scan Limit

Du kannst dir sicherlich erst einmal einen Displaycontroller vornehmen und für die anderen sendest du NoOp Kommando. Ich denke aber das musst du nicht machen.

Du sendest hier zunächst den Decode Mode für alle Controller ..

CS\ low
DecodeMode (letzer Controller)
DecodeMode
DecodeMode
DecodeMode (erster Controller)
CS\ high

Danach 4 mal Scan limit usw.


Es sind also 4 Datenpakete zusenden. Keine NoOp.

Die Controller sind dann konfiguriert. Was du vielleicht später mal änderst ist Intensity oder ShutDown/NormalOperation.

---

Wenn du Segmentdaten änderst, betrifft das ja nicht unbedingt alle Segmente, bzw. Digits. Für die Controller, bei denen sich nichts ändert kannst du dass NoOp senden. Ich würde mir im Mikrocontroller erst mal ein Array erstellen, was alle Digits/Zeilen (oder je nachdem wir du es angeschlossen hast) beinhaltet. Und das Array erst einmal komplett übertragen.

Dirk :ciao:

Gut Danke Dirk das werde ich später testen und dann sag ich bescheid ob das funktioniert hat oder nicht..

ich habe gerade erstmal ein Modul zum laufen gebracht aber das modul erkennt nicht richtig mein zeichen das heisst wenn ich A oder 1 z.B aus geben möchte zeigt mein Matrix kommische zeichen oder punkte die man nicht lesen kann obwohl ich schon mal mit Arduino das geschaft habe!!
habe ich da was falsches in meinem font Array falsch gemacht?
kennt jmd vielleicht ein guten font generator für ein 8x8 led matrix?
Vielen Dank im voraus
Gruß bentiaci
 
Gut Danke Dirk das werde ich später testen und dann sag ich bescheid ob das funktioniert hat oder nicht..

ich habe gerade erstmal ein Modul zum laufen gebracht aber das modul erkennt nicht richtig mein zeichen das heisst wenn ich A oder 1 z.B aus geben möchte zeigt mein Matrix kommische zeichen oder punkte die man nicht lesen kann obwohl ich schon mal mit Arduino das geschaft habe!!
habe ich da was falsches in meinem font Array falsch gemacht?
kennt jmd vielleicht ein guten font generator für ein 8x8 led matrix?
Vielen Dank im voraus
Gruß bentiaci

Hallo Zusammen,
ich habe das problem gelöst in dem ich einfach PROGMEM gelöscht habe und mein Matrix zeigt korrekte Zeichen aber wie gesagt mein Zeichen Font ist jetzt in SRAM und somit verbraucht mein Speicher!....
hat jmd eine Idee warum mein Matrix nicht funktioniert hat bzw kommische Zeichen zeigt wenn ich das Zeichen Font in Flash mit Hilfe von PROGMEM speichere??
Vielen Dank im voraus
bentiaci
 
Hallo Zusammen,
ich habe das problem gelöst in dem ich einfach PROGMEM gelöscht habe und mein Matrix zeigt korrekte Zeichen aber wie gesagt mein Zeichen Font ist jetzt in SRAM und somit verbraucht mein Speicher!....
hat jmd eine Idee warum mein Matrix nicht funktioniert hat bzw kommische Zeichen zeigt wenn ich das Zeichen Font in Flash mit Hilfe von PROGMEM speichere??

Ich kann jetzt nur vermuten wo die Fehlerursache liegt, da dein Sourcecode nur in Teilen im Forum steht.

Verwendest du PROGMEM, dann legt der Compiler das Array im Segment des Flash Memorys ab. Ich vermute du greifst in der Ausgaberoutine immer noch normal auf das Array zu, welches aber nicht mehr im SRAM liegt.

Verwende anstelle
data = MeinArray[j];
folgendes
data = pgm_read_byte(&MeinArray[j]);

Du musst folgendes in dem C-File einbinden
#include <avr/pgmspace.h>

Dirk :ciao:
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)