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);
}
________________________________________
@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?
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