Hi, ist bin ein totaler Anfänger im Bereich Microprozessoren. Ich will mit einem Atmega8 und einem Max7221 eine LED-Lichtleichte realisieren. Von der Hardware ist alles Fertig. Die Verdrahtung: Atmega8 MAX7221 PIN17 PB3(MOSI) -> PIN1 DIN PIN19 PB5 (CLK) -> PIN13 CLK PIN16 PB2 (SS) -> PIN12 LOAD(CS) Strom und der Rest ist alles Klar. So nun habe ich verschiedene Varianten hier gefunden wie man Daten senden kann aber irgendwie kommt nichts an an dem MAX7221 der Atmel sendet nix. Wenn ich den Atmel mit PonyProg beschreibe kann ich mit meinem Messgerät Spannungsschankungen feststellen am MOSI aber der Atmel selbt sendet nichts. Das ist mein derzeitiger Code: _______________________________________________________ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> int main() { DDRB = (1<<PB3)|(1<<PB5); // MOSI,SCK als Output, MISO als Input SPCR = (1<<SPE)|(1<<MSTR); // SPI enable, Master Mode for(;;) { SPDR = Fxff; // 10101010 while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet } }; _______________________________________________________ Ich hoffe ihr könnt mir helfen. Hab echt keinen plan was ich genau machen soll.
Hi, Du musst bei der SPI-Schnittstelle den SS-Pin per Hand bedienen. Also: * vor der Übertragung SS auf Low * Daten in SPDR schreiben * warten, bis SPI fertig ist * SS wieder auf High Damit überträgst Du EIN Byte an den 7221. Kann sein, dass der 7221 mehrere Bytes hintereinander braucht (->Datenblatt), dann muss das SS während der ganzen Zeit auf High bleiben. Was soll bitte diese Zeile: SPDR = Fxff; // 10101010 Hast Du Fxff irgendwo definiert - und wie? Oder hast Du Dich verschrieben und meinst 0xFF? Warum übersetzt dann gcc korrekt? Wenn Du 0xff ausgibst, dann ändert sich (natürlich) nichts am MOSI-Pin, der bleibt dann die ganze Zeit High. Bei anderen Werten wird Messgerät wohl eine konstante Gleichspg anzeigen. Gruß, Stefan
Danke. das ist mein code zurzeit es scheint sogar was zu passieren =) Aber die Anzeige zeigt noch nicht das an was ich will. ________________________________________________________ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> void spi_senden(unsigned); int main() { DDRB = (1<<PB3)|(1<<PB5)|(1<<PB2); // MOSI,SCK als Output PORTB =(1<<PB2); //SS auf High SPCR = (1<<SPE)|(1<<MSTR); // SPI enable, Master Mode spi_senden(0x0F00); // Displaytest ausschalten , Tabelle 9 / 2 spi_senden(0x0B07); // Anzahl Digits (Segmetbausteine ) Tabelle 7 spi_senden(0x0C01); // Display auf Normal Operation , Tabelle 3 spi_senden(0x0900); // Decode-Mode (BCD-CODE für die mitleren 4) Tabelle 4 for(;;) { spi_senden(0x0100); } }; void spi_senden(unsigned daten) { PORTB =(1<<PB2); SPDR = daten; while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet PORTB =(0<<PB2); }
> Aber die Anzeige zeigt noch nicht das an was ich will. Hmm - daraus ergeben sich gleich 2 Fragen: * was willst Du? * was zeigt sie tatsächlich an? -> Fehler- und Unfallmeldungen immer möglichst präzise ... Nachdem ich mal im Datenblatt geschaut habe: der 7221 erwartet 16 Bit SPI-Daten. D.h. Du musst: * vor der Übertragung SS auf Low * Daten(high) in SPDR schreiben * warten, bis SPI fertig ist * Daten(low) in SPDR schreiben * warten, bis SPI fertig ist * SS wieder auf High Entweder Du übergibst Deinem spi_senden also 2 8-Bit-Werte (High und Low), was einfacher zu programmieren ist, einen 16-Bit-Wert und trennst diesen in spi_senden in High- und Low auf. Etwas ganz anderes: > PORTB =(1<<PB2); Im Moment ist es wohl (noch) nicht Dein Problem, aber es kann später zu einem werden: Diese Zeile setzt den GESAMTEN Port B, und zwar auf 0000 0100 binär. Sobald Du die anderen Pins auch benutzst, hast Du ein Problem. Deshalb: * zu Setzen eines Portpins verODERn: PORTB |= (1<<PB2); * zum Löschen eines Portpins verUNDen: PORTB &= ~(1<<PB2); Beispiel 1: Portpin setzen angenommen, PORTB ist 1111 0000 binär. 1 << PB2 entspricht 0000 0100 binär (nämlich 1 um 2 Binärstellen links geschoben). PORTB |= (1<<PB2) entspricht: 1111 0000 (Annahme von oben) ODER 0000 0100 (1 << PB2) = 1111 0100 (neuer Portzustand) Beispiel 2: Portpin löschen angenommen, PORTB ist 1111 0100 binär. (1 << PB2) entspricht 0000 0100 binär (nämlich 1 um 2 Binärstellen links geschoben). ~(1 << PB2) entspricht diesem Wert negiert, also 1111 1011 binär. PORTB &= ~(1<<PB2) entspricht: 1111 0100 (Annahme von oben) UND 1111 1011 ~(1 << PB2) = 1111 0000 (neuer Portzustand) Gruß, Stefan
vielen Dank für deine Hilfe! >der 7221 erwartet 16 Bit SPI-Daten. D.h. Du musst: >* vor der Übertragung SS auf Low >* Daten(high) in SPDR schreiben >* warten, bis SPI fertig ist >* Daten(low) in SPDR schreiben >* warten, bis SPI fertig ist >* SS wieder auf High >Entweder Du übergibst Deinem spi_senden also 2 8-Bit-Werte (High und Low), was einfacher zu programmieren ist, einen 16-Bit-Wert und trennst >diesen in spi_senden in High- und Low auf. ________________________________________ Mein Code: void spi_senden(unsigned daten) { PORTB &= ~(1<<PB2); SPDR = daten; while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet PORTB |=(1<<PB2); } ________________________________________ ich weiss noch nicht genau was du meinst, dass der einmal high daten braucht und dann low.?!? meinst du das so? ________________________________________ Mein Code: void spi_senden(unsigned daten, unsigned daten1) { PORTB &= ~(1<<PB2); SPDR = daten; while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet SPDR = daten1; while(!(SPSR & (0<<SPIF))); // warte bis Byte gesendet PORTB |=(1<<PB2); } ________________________________________
PORTB &= ~(1<<PB2); SPDR = daten; while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet SPDR = daten1; while(!(SPSR & (0<<SPIF))); // warte bis Byte gesendet PORTB |=(1<<PB2); Ja, so kannst Du das machen. Sollte eigendlich funktionieren? Gruß, Stefan
Hi, wo hast du das eigentlich gefunden im datenblatt mit dem einmal 8Bit high und dann 8Bit low senden??? irgendwie klappt da nix.
Hi, @Peter Der MAX7219 hat doch kein SPI oder? Irgendwie raf ich dein code auch net haste keine kurze version?
@Nook, der MAX7219 ist der Vorgänger des MAX7221. Die eigentliche Ausgaberoutine ist diese hier:
1 | void display_write( u16 dc ) |
2 | {
|
3 | u8 i; |
4 | |
5 | MAX7219_DDR |= 1<<MAX7219_DO; |
6 | MAX7219_DDR |= 1<<MAX7219_SCK; |
7 | MAX7219_DDR |= 1<<MAX7219_STB; |
8 | MAX7219_PORT &= ~(1<<MAX7219_STB); |
9 | |
10 | for( i = 12; i; i-- ){ |
11 | MAX7219_PORT &= ~(1<<MAX7219_SCK); |
12 | MAX7219_PORT |= 1<<MAX7219_DO; |
13 | if( (dc & 0x0800) == 0 ) |
14 | MAX7219_PORT &= ~(1<<MAX7219_DO); |
15 | dc <<= 1; |
16 | MAX7219_PORT |= 1<<MAX7219_SCK; |
17 | }
|
18 | |
19 | MAX7219_PORT |= 1<<MAX7219_STB; |
20 | }
|
Der Rest ist nur Initialisierung und 7-Segment Wandlung. Peter
@Stefan Kleinwort:
PORTB &= ~(1<<PB2);
SPDR = daten;
while(!(SPSR & (1<<SPIF))); // warte bis Byte gesendet
SPDR = daten1;
>> while(!(SPSR & (0<<SPIF))); // warte bis Byte gesendet
PORTB |=(1<<PB2);
Muss in der 2. Whileschleife nicht eine 1 anstatt der 0 stehen? Man
wartet auch hier bis das SPI_flag gesetzt ist oder nicht?
@Marian: ooops .. natürlich muss da eine 1 stehen, sorry. Keine Ahnung, wie da die 0 hinkam ... Viele Grüße, Stefan
Hallo an alle ICh bin ebenfalls daran beschäftigt einen Max 7221 mit 6 LED Segmentanzeigen zum laufen zu bringen Leider funktioniert es nicht. Es werden immer alle Leds der Segmentanzeigen eingeschaltet. Und ich weiß nicht warum :( Hier der Code: void spi_init (void) { DDRB |= ((1 << PB3) | (1 << PB5) | (1 << PB2)); //MOSI, SCK, SS Output, alle anderen Input SPCR |= ((1 << SPE) | (1 << MSTR)); } void spi_senden (uint8_t adress, uint8_t data) { PORTB &= ~(1 << PB2); //SS auf Low SPDR = adress; while (!(SPSR & (1 << SPIF))); //warten bis gesendet SPDR = data; while (!(SPSR & (1 << SPIF))); //warten bis gesendet PORTB |= (1 << PB2); //SS auf high } void segments_init(void) { spi_senden(0x0B, 0x05); //6 Digits 0-5 spi_senden(0x0F, 0x00); //Display Test ausschaltren spi_senden(0x0C, 0x01); //Normal Operation spi_senden(0x09, 0xFF); //BCD Code für alle Digits } void show_temp(void) { spi_senden(0x01, 0x01); spi_senden(0x02, 0x02); spi_senden(0x03, 0x03); spi_senden(0x04, 0x04); spi_senden(0x05, 0x05); spi_senden(0x06, 0x06); } int main (void) { spi_init(); i2c_init(); segments_init(); spi_senden(0x0A, 0x0C); //Helligkeit show_temp(); while(1) { } return 0; } Vielleicht kann mir wer helfen Danke im Voraus Gruß Robert
Hi Leute! Hab genau dasselbe Problem. Bei mir werden trotz richtiger Initialisierung auch immer alle LEDs angezeigt. Übertragung findet auch über SPI statt. Habt ihr schon ne Lösung? Grüße, Didi
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.