Hallo, Leute! Nach vielen mehr oder weniger erfolgreichen Projekten mit Mikrocontrollern wollte ich mich mit der SPI-Schnittstelle beschäftigen. Der Atmega32 arbeitet als Master, der Atmega8 als Slave. Verbindungen siehe Schaltplan. Der Atmega32 wird mit dem internen 8Mhz Oszillator getaktet, der Atmega8 laut Buch hingegen mit dem internen 1Mhz Oszillator. Den Code sowie den Schaltplan habe ich aus dem Buch "Hardware und C-Programmierung in der Praxis". Dort wurde zwar der Atmega16 + 8 verwendet, was aber nach einer Änderung im Makefile keinen Unterschied machen sollte. Am Atmega32 (Master) ist ein Lcd angeschlossen, welches tadellos funktioniert, wobei der RW-Pin auf GND gezogen werden musste (im Buch steht, dass man ihn nicht zu beschalten hat?!). Der Atmega32 sendet dem Atmega8 nun die Zahl "1". Der Atmega8 prüft, ob diese Zahl "1" entspricht und sendet daraufhin "100" zurück. Der Atmega32 soll dann diese "100" ausgeben. Soweit so gut, aber der Atmega32 schreibt auf das Lcd mehr oder weniger zufällige Zahlen wie: sehr häufig 255 031 087 251 239 243 usw... Leider habe ich momentan kein Oszi zur Verfügung, um die Kommunikation zu überprüfen, aber wenn ich eine Led an Miso, Mosi oder Sck hänge, dann blitzt sie kurz auf (jenachdem ob ich sie nach VCC oder GND beschalte). Es findet also eine Kommunikation statt. Komischerweise blitzt die Led (wenn sie an Miso angeschlossen ist) manchmal hell auf, manchmal nur ganz schwach... Während dem Programmieren hänge ich natürlich den anderen AVR vom Programmer ab. Während des Betriebs ist der Programmer (bis auf VCC + GND) auch nicht angeschlossen. Die VCC kommen aus meinem USB-Programmer. Das ganze habe ich auf einem Steckbrett aufgebaut. Hat jemand eine Idee, warum sich diese Schaltung so verhält und wie man eine stabile Kommunikation zwischen den µCs herstellen kann? Danke im Voraus Gruß DjElko! :-D
Mir ist aufgefallen: extrem selten (jedes gefühlte 578. mal kommt 100 am Atmega32 an und die Led am Atmega8 leuchtet auf... Ich denke, es hat etwas mit den Zeiten zu tun (z.B. dass der Atmega8 nicht hinterherkommt)... Hat jemand eine Idee? Ich werde jetzt mal den Atmega32 mit 1Mhz takten...
Hm... auch mit 1Mhz gehts nicht besser... Einziger Unterschied: Die Lcd-Darstellung benötigt mehr Zeit...
Hi >Der Atmega32 sendet dem Atmega8 nun die Zahl "1". >Der Atmega8 prüft, ob diese Zahl "1" entspricht und sendet daraufhin >"100" zurück. >Der Atmega32 soll dann diese "100" ausgeben. >char SPI_MasterReceive(void) >{ > while(!(SPSR & (1<<SPIF))); // warte bis Empfang komplett > return SPDR; // empfangenes Byte >zurueckgeben >} Das funktioniert so nicht. Damit der Master etwas empfangen kann muss er ein Dummy-Byte senden. Der Slave erzeugt keinen Takt auf dem, den bekommt er vom Master und dazu muß der Master etwas senden. MfG Spess
Ah, klar. Danke! Der Slave hat ja kein Taktsignal, worauf er zurückgreifen kann... Da muss man ersteinmal drauf kommen... Wie realisiert man das denn in der Programmierung, dass der Master "weiß", wann der Slave sendet?
Hi >Wie realisiert man das denn in der Programmierung, dass der Master >"weiß", wann der Slave sendet? Ein Slave sendet nicht, er wird 'gefragt'. Im einfachsten Fall sendet der Master zyklisch etwas an den Slave und wertet die Antwort aus. Du könntest natürlich auch eine zusätzliche Leitung benutzen mit der der Slave sein Mitteilungsbedürfnis signalisiert. Persönlich bevorzuge ich zu Kommunikation zwischen Controllern U(S)ART. MfG Spess
>Persönlich bevorzuge ich zu Kommunikation zwischen Controllern U(S)ART.
Ich auch. An SPI schliesse ich nur dumme Slaves an die in der
Lage dazu sind sofort etwas zu antworten. Bei einem uC SPI Slave
weiss man nie wann der antworten kann. Also muss man entweder lang
genug warten oder weitere Leitungen für ein Handshake einsetzen.
Allerdings könnte der Slave zum Master werden wenn er die SS
Leitung vom Master beackert. Naja, viel Spass dabei.
Spess53 schrieb: > Du könntest natürlich auch eine zusätzliche Leitung benutzen mit der der > Slave sein Mitteilungsbedürfnis signalisiert. Als dreckige Lösung habe ich dafür auch mal !SS verwendet, im Master über de Pullup High geschaltet und den Pin als Eingang. Möchte der Slave Daten loswerden, zuppelt er das mal kurz auf Masse, und schon kann der Master seine Dummyload rüberschicken um das Ergebnis abzuholen.
Hi >Als dreckige Lösung habe ich dafür auch mal !SS verwendet, im Master >über de Pullup High geschaltet und den Pin als Eingang. Damit wechselt der Master aber erst in den Slavemode und muß erst mal wieder in den Mastermode geschaltet werden, MfG Spess
>Möchte der Slave >Daten loswerden, zuppelt er das mal kurz auf Masse, und schon kann der >Master seine Dummyload rüberschicken um das Ergebnis abzuholen. In dem Fall muss der Slave den Takt erzeugen. Der Ex-Master kann gar kein Dummy Byte mehr schicken wenn er zum Slave geworden ist.
Der Master wird nirgends zum Slave. Nur hat die Slave-Leitung den angenehmen Effekt, dass sie Active-Low ist. Somit kann der Master über einen High-Pegel den Slaves signalisieren, dass sie gerade nicht aktiv sind. Soweit der normale Betrieb. Nun kann ich aber statt einem High-Ausgangspin das Nicht-Aktiv-High auch über den (internen) Pullup erzeugen, und damit dem Slave die Möglichkeit geben es runterzuziehen. Der Master bemerkt diesen Pegelwechsel, im einfachsten Fall hat er einen Interrupt drauf, der ein passendes Flag setzt. Nun weiß er (weiterhin in seiner Funktion als Master) dass der Slave Daten für ihn hat, und kann sie bei Gelegenheit abholen. Wo der Master nun zum Slave geworden sein sollt müsst ihr mir noch erläutern. Das ist nichts anderes als der Interrupt-Ausgang, den viele fertige SPI-Chips sowieso haben, ohne dass ich einen weiteren Pin dafür brauche.
Danke für die vielen Antworten! Ich glaube, ich werde zur Kommunikation zwischen mehreren µCs doch I²C nehmen... Mein Vorhaben ist es, mehrere Module mit einer gleichen Schnittstelle (z.B SPI oder I²C) zu bauen, um dann auf dem Steckbrett modular mit diesen Bausteinen arbeiten zu können. Bei 4-8 7-Segment-Anzeigen, einem Display (zum Debuggen) und einem Tastenfeld werden die Pins und auch der Platz auf dem Steckbrett sowie dem Atmega32 zu wenig... Außerdem hat die Verwendung mehrerer Mikrocontroller (zumindest bei Versuchsaufbauten und zum Lernen der Programmierug) den Vorteil, dass der Hauptmikrocontroller "gemütlich" das Hauptprogramm abarbeiten kann und sich die anderen Mikrocontroller um die Kommunikation mit der Außenwelt kümmern. UART wollte ich nicht nehmen, weil ich das ja schon vom PC sowie dem Haupt-µC "belegt" ist. Ich mache mal ein Paar Versuche mit I²C; vielleicht funktioniert das ja besser. ;-D Gruß, DjElko!
Hm... Mit I²C komme ich auch nicht wirklich weiter... Ich möchte vom Atmega32 (Master) was zum Atmega8(Slave) senden und umgekehrt... Kennt jemand einen Link oder so für eine funktionierende Master + Slave Library für I²C? Ich bin langsam ratlos... Hab es jetzt schon mit einigen Codes versucht, unter anderem mit dem hier: Beitrag "AVR TWI Master und Slave Funtionen in C" Leider kommt bei mir beim Compilieren der TWI_Master_main.c in Programmers Notepad + WinAVR folgende Fehlermeldung:
1 | Linking: TWI_Master_main.elf |
2 | avr-gcc -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=TWI_Master_main.o -std=gnu99 -MD -MP -MF .dep/TWI_Master_main.elf.d TWI_Master_main.o --output TWI_Master_main.elf -Wl,-Map=TWI_Master_main.map,--cref -lm |
3 | TWI_Master_main.o: In function `main': |
4 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:51: undefined reference to `Delayloop32' |
5 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:55: undefined reference to `RS232_Init' |
6 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:60: undefined reference to `TWIM_Init' |
7 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:75: undefined reference to `TWIM_Start' |
8 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:77: undefined reference to `TWIM_Stop' |
9 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:84: undefined reference to `TWIM_ReadAck' |
10 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:87: undefined reference to `TWIM_ReadNack' |
11 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:89: undefined reference to `TWIM_Stop' |
12 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:90: undefined reference to `Delayloop32' |
13 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:97: undefined reference to `TWIM_Start' |
14 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:99: undefined reference to `TWIM_Stop' |
15 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:106: undefined reference to `TWIM_Write' |
16 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:109: undefined reference to `TWIM_Stop' |
17 | D:\Erstellungen - Master-Ordner\Hobby\Elektro\uC\avr_gcc_neu\i2c_topic\TWI_Master/TWI_Master_main.c:110: undefined reference to `Delayloop32' |
18 | make.exe: *** [TWI_Master_main.elf] Error 1 |
19 | |
20 | > Process Exit Code: 2 |
21 | > Time Taken: 00:01 |
Hat jemand einen Tipp oder eine Lösung? Das Problem wurde zwar auch in dem oben genannten Thread beschrieben, doch eine wirkliche Lösung hat da keiner gefunden... Gruß, DjElko!
>Hat jemand einen Tipp oder eine Lösung?
Du hast TWI_Master.c und Delay.c nicht zum Projekt hinzugefügt.
Einfach in das Verzeichnis kopieren reicht nicht.
Heureka! :-D Es funktioniert! :-D Vielen Dank für die Unterstützung! :-D Ein paar Änderungen mussten noch im Makefile des Slaves vorgenommen werden. Gruß, DjElko!
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.