Hallo an alle, aktuell bin ich dabei mit Schieberegsistern ein wenig herum zu spielen. Jedoch möchte es mir nicht so ganz gelingen. Ich habe folgendes Problem: In diesem Thread (Beitrag "LED-Matrix mit Atmega8 (16Mhz) Wieivele Schieberegiste in Reihe?") konnten die Probleme des Aufbaus einer 16*8-Bit-Matrix gelöst werden. Die LEDs sollen also über 16 Schieberegister angesprochen werden, welche alle hintereinander geschaltet sind. Die Schieberegister sollen wiederum von dem SPI des Atmega8 angesprochen werden. Jetzt habe ich mir mal probehalber auf einem Breadboard 2 Schieberegister, wie auf diesem Bild: http://www.mikrocontroller.net/attachment/169521/spi.png zusammengesteckt. Mir fehlt jedoch der passende C Code. Im AVR-Schieberegister-Tutorial ist alles nur in Assembler angegeben, womit ich nicht wirklich klar komme. Perfekt wäre es, wenn ich eine Funktion hätte, die alles nötige initialisiert und eine, der ich einen 8-Bit-Wert (z.B. 0b01100110) übergebe, welcher dann in das erste Register geschoben wird. Beim zweiten Aufruf würde dann der erste Wert in das zweite Register geschoben werden und der zweite Wert (z.B. 0b10011001) in das erste Register. So dass ich die Fuktion theoretisch für beliebig viele Register nutzen könnte. Ist das möglich? Bzw. weiß jemand wo ich dafür die nötigen Infos/Codeschnippsel herbekomme? Gruß
Thomas J. schrieb: > Mir fehlt jedoch der passende C Code. Im AVR-Schieberegister-Tutorial > ist alles nur in Assembler angegeben, womit ich nicht wirklich klar > komme. Naja, wenn du ein Hardware-SPI hast, dann greift der code doch nur auf die paar SPI-Register zu. Ob man das nun in Assembler oder C aufschreibt, ist kein großer Unterschied. > Perfekt wäre es, wenn ich eine Funktion hätte, die alles nötige > initialisiert Du musst das MSTR-Bit in SPCR setzen und ggf. die Taktrate. > und eine, der ich einen 8-Bit-Wert (z.B. 0b01100110) > übergebe, welcher dann in das erste Register geschoben wird. Das ist einfach nur ein Schreibvorgang auf SPDR. Braucht man dafür eine Funktion? Ach so, vorher musst du noch schauen, ob die vorhergehende Transaktion bereits beendet ist (SPIF-Bit muss wieder 1 sein). > Beim > zweiten Aufruf würde dann der erste Wert in das zweite Register > geschoben werden und der zweite Wert (z.B. 0b10011001) in das erste > Register. Ja, genau so funktionieren kaskadierte Schieberegister. Allerdings würde ich (anders als im von dir gezeigten Bild) den Ladeeingang der Schieberegister nicht fest auf Vcc verdrahten, sondern auf einen Portpin legen. Andernfalls "wackeln" alle angeschlossenen Ausgänge während der Aktualisierung mit (da werden die einzelnen Bytes ja durch die Register hindurch geschoben). Wenn man fertig ist und alle Register mit ihren Werten geladen sind, gibt man einfach einen kurzen Impuls an den Ladeeingang der '595. Erst durch diesen Impuls übernehmen die parallelen Ausgänge die Information aus dem seriellen Register.
@ Thomas J. (rrurr) >Mir fehlt jedoch der passende C Code. Im AVR-Schieberegister-Tutorial >ist alles nur in Assembler angegeben, womit ich nicht wirklich klar >komme. Das ist eine gute Einstiegsaufgabe. Entweder "per Hand" und Bitmanipulation oder direkt mit dem SPI Modul. Das ist nicht schwer zu benutzen. >So dass ich die Fuktion theoretisch für beliebig viele Register nutzen >könnte. Ist das möglich? Ja. > Bzw. weiß jemand wo ich dafür die nötigen > Infos/Codeschnippsel herbekomme? "Nur selber denken macht geistig fett". Gerade als Anfänger muss man eigentlich alles mal selber gemacht haben, um dabei was zu lernen.
Jörg Wunsch schrieb: > Allerdings würde ich (anders als im von dir gezeigten Bild) den > Ladeeingang der Schieberegister nicht fest auf Vcc verdrahten, > sondern auf einen Portpin legen. Andernfalls "wackeln" alle > angeschlossenen Ausgänge während der Aktualisierung mit (da werden > die einzelnen Bytes ja durch die Register hindurch geschoben). > Wenn man fertig ist und alle Register mit ihren Werten geladen sind, > gibt man einfach einen kurzen Impuls an den Ladeeingang der '595. > Erst durch diesen Impuls übernehmen die parallelen Ausgänge die > Information aus dem seriellen Register. Was meinst du mit "Ladeeingang"? Den Pin "SCL"? Da habe ich mich an das Tutorial gehalten (http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister#Ansteuerung_per_SPI-Modul), in dem es heißt: "Hier wird der Pin SCL nicht benutzt, da das praktisch keinen Sinn hat. Er muss also fest auf VCC gelegt werden." Was ich auch nicht ganz verstanden habe ist der folgende Abschnitt: "Der AVR-Pin SS wird sinnvollerweise als RCK benutzt, da er sowieso als Ausgang geschaltet werden muss, sonst gibt es böse Überaschungen (siehe Datenblatt „SS Pin Functionality“). Dieser sollte mit einem Widerstand von 10 kΩ nach Masse, während der Start- und Initialisierungsphase, auf L-Potential gehalten werden. ..." Heißt das, dass ich zwischen SS-Pin des AVR und dem RCK des Registers einen 10k-Wiederstand nach Masse legen soll?
@ Thomas J. (rrurr) >Was meinst du mit "Ladeeingang"? Den Pin "SCL"? Da habe ich mich an das >Tutorial gehalten Ist OK, das war eine Irrtum. >(http://www.mikrocontroller.net/articles/AVR-Tutori...), >in dem es heißt: "Hier wird der Pin SCL nicht benutzt, da das praktisch >keinen Sinn hat. Er muss also fest auf VCC gelegt werden." Passt. Das Pin löscht das Schieberegister, eine Funktion, die man praktisch nie braucht. Einfach 0x00 reinschieben tut's auch. >Heißt das, dass ich zwischen SS-Pin des AVR und dem RCK des Registers >einen 10k-Wiederstand nach Masse legen soll? Nicht ZWISCHEN, die Verbindung ist direkt. Aber zwischen dem Pin und VCC kommt zusätzlich ein Widerstand, Pull-Up genannt.
Also ich habe das mit dem 10k-Widerstand nun so gelöst: Pin SS: o------------------o Pin RCK auf | auf dem | dem AVR | Register [ ] [ ] 10k [ ] | | v VCC (5V) Im Anhang mal mein Programm-Code für ein Register. Der Code läuft auch soweit, allerdings nicht ganz stabil, das heißt, dass die LEDs mal angehen und nach ein paar Sek wieder aus. Jedoch nicht schlagartig, sondern Regel sich (wie bei PWM) runter... Hat jemand 'ne Anhnung woran das liegen könnte? Gruß
Thomas J. schrieb: > Hat jemand 'ne Anhnung woran das liegen könnte? Gewöhn dir an, dass du in main() immer eine Hauptschleife hast. Wenn es in der Hauptschleife nichts mehr zu tun gibt, dann ist die halt leer. Aber Hauptschleife willst du haben! Immer. Du willst nicht, dass main() jemals verlassen wird. in setAllOut möchtest du einen sauberen Puls erzeugen. D.h. Pin auf High setzen, Pin auf Low setzen. Dann hast du einen korrekten Puls. Pin nur auf High setzen ist kein Puls.
1 | void setAllOut(void) |
2 | {
|
3 | PORTB |= (1<<SS); |
4 | PORTB &= ~(1<<SS); |
5 | }
|
6 | |
7 | int main(void) |
8 | {
|
9 | init(); |
10 | transmit(0b11111111); |
11 | setAllOut(); |
12 | |
13 | while( 1 ) |
14 | {
|
15 | }
|
16 | |
17 | return(0); |
Die Methode "void setAllOut(void)" habe ich geändert, ergibt schon Sinn was du geschrieben hast. Danke für den Hinweis. Die Schleife habe ich ebenfalls eingebaut. Tortzdem löst das mein Problem leider nicht. Abgesehen, davon, dass die LEDs einfach ausgehen, habe ich noch den folgenden Effekt beobachtet (siehe Anhang).
Sieht mir nach einem Wackelkontakt oder zumindest einem schlechten Kontakt irgendwo aus.
Scheint in der Tat nur ein Wackelkontakt zu sein. Naja, für einen Prototypen nicht so tragisch. Die LED-Matrix wird dann fest verlötet sein. Damit wäre jetzt alle Probleme behoben und ich kann mit dem Löten beginnen. Ich danke euch für die Hilfestellungen und Tipps! Gruß
Falk Brunner schrieb: >>Was meinst du mit "Ladeeingang"? Den Pin "SCL"? Da habe ich mich an das >>Tutorial gehalten > > Ist OK, das war eine Irrtum. Danke für die Korrektur, Falk. Ich hatte dann gestern keine Zeit mehr, mir das nochmal genau anzusehen, und hatte aufgrund des "CL" auf "clock" getippt.
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.