Hallo zusammen, ich versuche momentan das Zusammenspiel zwischen einem 595 und dem ATMEGA328 zu verstehen und habe ein Testsetup aufgesetzt. 8 LEDs connected zu Q0-Q7 des 595ers, DS an PB0, SHCP and PB1 und STCP an PB2 des AVR. der 595 Code: **MAIN** // AVR #include <avr/io.h> #include <util/delay.h> // CUSTOM #include <systemDefinitions.h> #include <pinDefinitions.h> #include <HC595.h> int main(void) { while (1) { } return (0); } **HC595.h** #define HC595_PORT PORTB #define HC595_DDR DDRB #define HC595_DS_POS PB0 #define HC595_SH_CP_POS PB1 #define HC595_ST_CP_POS PB2 #define HC595DataHigh() (HC595_PORT |= (1 << HC595_DS_POS)) #define HC595DataLow() (HC595_PORT &= (~(1<<HC595_DS_POS))) void HC595Init() { // Make DS, SHCP and STCP output HC595_DDR |= ((1 << HC595_SH_CP_POS) | (1 << HC595_ST_CP_POS) | (1 << HC595_DS_POS)); } // Sends a clock pulse on SHCP Line void HC595Pulse() { // Pulse shift clock HC595_PORT |= (1 << HC595_SH_CP_POS); // HIGH HC595_PORT &= (~(1<<HC595_SH_CP_POS)); // LOW } // Sends a clock pulse on STCP Line void HC595Latch() { // Pulse the store clock HC595_PORT |= (1 << HC595_SH_CP_POS); // HIGH _delay_loop_1(1); HC595_PORT &= (~(1<<HC595_ST_CP_POS)); // LOW _delay_loop_1(1); } /* Main High level function to write a single byte to Output shift register 74HC595. Arguments: single byte to write to the 74HC595 IC Returns: NONE Description: The byte is serially transfered to 74HC595 and then latched. The byte is then available on output line Q0 to Q7 of the HC595 IC. */ void HC595Write(uint8_t data) { // Send each 8 bits serially // Order is MSB first for (uint8_t i = 0; i < 8; i++) { // Output the data on DS line according to the value of MSB if (data & 0b10000000) { // MSB is 1 so output HIGH HC595DataHigh(); } else { // MSB is 0 so output LOW HC595DataLow(); } HC595Pulse(); // Pulse the clock line data = data << 1; // Now bring the next bit at MSB Position } // Now all 8 bits have been transferred to shift register and move them to output latch at ones HC595Latch(); } Der Code den ich ausführe auf dem AVR ist: int main(void) { uint8_t led = 0b11111111; HC595Init(); HC595Write(led); return (0); } Meine Erwartung wäre, das jetzt alle 8 LEDs aufleuchten. Aber statt 11111111 erhalte ich 10101010 auf den LEDs. Wie kann das sein? Habe ich was vergessen?
Tja... Beim Aufbau Mist gebaut, was nicht beachtet zB. Abblockkondensator, Vorwiderstände...?
Sebastian S. schrieb: > Ich habe mich an diesem Beispiel orientiert. Und wo sind da die Abblockkondensatoren für den 74hc595 und den ATmega?
https://www.mikrocontroller.net/articles/Kondensator#Entkoppelkondensator (Abblock == Entkoppel)
:
Bearbeitet durch User
Ich hab den Cap mit eingefügt, hat aber leider auch nichts verändert.
Sebastian S. schrieb: > Ich hab den Cap mit eingefügt, hat aber leider auch nichts verändert. Und hast du dem Schieberegister versuchsweise mal etwas mehr Zeit zwischen dem Anlegen der Daten und der aktiver Clock-Flanke gegeben?
ich bin jetzt einen Schritt näher gekommen. Tatsächlich habe ich den Cap zunächst zuweit weg platziert. Jetzt direkt an das Schieberegister ran und es leuchtet schon mal nicht mehr zufällig. Jedoch ist alles um ein bit verschoben. Wenn ich 11110000 eingebe, dann kommt 11100000 raus. Es scheint also halb zu funktionieren. Wenn ich 01111000 nehme dann sehe ich 11110000. Woran kann das denn noch liegen? das muss doch jetzt meine Write Funktion sein, oder?
:
Bearbeitet durch User
Teo D. schrieb: > https://www.mikrocontroller.net/articles/Kondensator#Entkoppelkondensator > (Abblock == Entkoppel) Danke. Soweit hat das tatsächlich geklappt (ich bin neu mit der ganzen Thematik und lerne noch). Jedoch wie unten beschrieben, scheint alles ein Bit versetzt zu sein, da ich mit dem Input 01111000 auf den LEDs sehe: 11110000; Aber das Random Leuchten ist weg. Ist meine Write Funktion falsch?
Sebastian S. schrieb: > Ist meine Write Funktion falsch? Guck dir mit dem LA einfach mal deine Signale an und vergleiche sie mit dem im Datenblatt vom 74HC595 gezeigten Ablauf, insbesondere unter Berücksichtigung der Zeiten im Abschnitt 11. Dynamic characteristics
Es ist sogar noch etwas seltsamer. Wenn ich 00001111 reingebe, kommt 00011111 raus. Also irgendwie wird ein Bit mehr geschalten. Ein anderes komisches Phänomen habe ich, wenn ich den Code auf meinen AVR lade. Die Anzeige ist nur bei jedem 2. Mal richtig. Aus 11111111 wird einmal 11111111 und einmal 11111110, um dann wieder 11111111 auf den LEDs auszugeben.
Wolfgang schrieb: > Sebastian S. schrieb: >> Ist meine Write Funktion falsch? > > Guck dir mit dem LA einfach mal deine Signale an und vergleiche sie mit > dem im Datenblatt vom 74HC595 gezeigten Ablauf, insbesondere unter > Berücksichtigung der Zeiten im Abschnitt 11. Dynamic characteristics Jetzt hab ich natürlich das Problem als Anfänger, das ich keine LA habe... ich habe mir bisher armselig mit einer Serial Port Ausgabe beholfen :)
Sebastian S. schrieb: > Jetzt hab ich natürlich das Problem als Anfänger, das ich keine LA > habe... ich habe mir bisher armselig mit einer Serial Port Ausgabe > beholfen :) Dann investiere mal gut 6€ in dein Hobby. Die sind gut angelegt. z.B. ebay 201541710029
Wolfgang schrieb: > Sebastian S. schrieb: >> Jetzt hab ich natürlich das Problem als Anfänger, das ich keine LA >> habe... ich habe mir bisher armselig mit einer Serial Port Ausgabe >> beholfen :) > > Dann investiere mal gut 6€ in dein Hobby. Die sind gut angelegt. > z.B. ebay 201541710029 Oh.... das wusste ich nicht. Den letzten den ich gesehen habe, hat gleich 180 EUR gekostet, was ich mir aber auch schon überlegt habe. Hast Du eine Idee warum ich das byte so versetzt sehe? Tatsächlich waren die Caps der Grund für das Zufällige aufleuchten. Aber ich verstehe nicht, warum sich meine Eingabe um eins verschiebt.
Ich hab dir ein einfaches Rätsel gepostet:
1 | // Sends a clock pulse on STCP Line
|
2 | void HC595Latch() |
3 | {
|
4 | // Pulse the store clock
|
5 | HC595_PORT |= (1 << HC595_SH_CP_POS); // HIGH |
6 | //------------------------^^^^^^^^^^^^^^^^------------
|
7 | _delay_loop_1(1); |
8 | |
9 | HC595_PORT &= (~(1<<HC595_ST_CP_POS)); // LOW |
10 | _delay_loop_1(1); |
11 | }
|
Den Rest musst du selbst leisten ;-)
Noch ein einfaches Rätsel: Warum kann meinen C-Code besser lesen als deinen? Des Rätsels Lösung: Ich habe die "Wichtige Regeln - erst lesen, dann posten!" beachtet.
Namen sollten sich in wenigstens 2 Buchstaben unterscheiden. Delay braucht man nicht, der HC595 schafft 25MHz. Mit den Bitbefehlen kommt der Mega328 @20MHz nur auf max 5MHz. In *.h Files gehört kein Code. Man kann die Lesbarkeit mit Bitmacros nochmal deutlich erhöhen:
1 | #include <avr/io.h> |
2 | |
3 | struct bits { |
4 | uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; |
5 | } __attribute__((__packed__)); |
6 | |
7 | #define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
|
8 | |
9 | #define SPI_CLK SBIT( PORTB, 0 ) // clock
|
10 | #define SPI_CLK_oe SBIT( DDRB, 0 )
|
11 | #define SPI_MOSI SBIT( PORTB, 1 ) // data out
|
12 | #define SPI_MOSI_oe SBIT( DDRB, 1 )
|
13 | #define SPI_MISO_in SBIT( PINB, 2 ) // data in
|
14 | |
15 | uint8_t shift_io( uint8_t b ) // send / receive byte |
16 | {
|
17 | SPI_CLK_oe = 1; // set as output |
18 | SPI_MOSI_oe = 1; |
19 | |
20 | for( uint8_t i = 8; i; i-- ){ // 8 bits |
21 | SPI_MOSI = 0; |
22 | if( b & 0x80 ) // high bit first |
23 | SPI_MOSI = 1; |
24 | b <<= 1; |
25 | SPI_CLK = 1; |
26 | if( SPI_MISO_in ) |
27 | b++; |
28 | SPI_CLK = 0; |
29 | }
|
30 | return b; |
31 | }
|
Arduinoquäler schrieb: > Ich hab dir ein einfaches Rätsel gepostet: > >
1 | >
|
2 | > // Sends a clock pulse on STCP Line |
3 | > void HC595Latch() |
4 | > { |
5 | > // Pulse the store clock |
6 | > HC595_PORT |= (1 << HC595_SH_CP_POS); // HIGH |
7 | > //------------------------^^^^^^^^^^^^^^^^------------ |
8 | > _delay_loop_1(1); |
9 | >
|
10 | > HC595_PORT &= (~(1<<HC595_ST_CP_POS)); // LOW |
11 | > _delay_loop_1(1); |
12 | > } |
13 | >
|
14 | >
|
> > Den Rest musst du selbst leisten ;-) Hmmm... guter Punkt! :) In Vorfreude hab ich das gleich mal ausprobiert, aber interessanterweise keinerlei Auswirkung auf das Ergebnis?! der Output den ich auf den LEDs sehe, ist immer noch um 1 verschoben, nur das ich mir das nicht erklären kann, da der Code dies nicht wiederspiegelt meiner Meinung nach.
Ah... wieder einen Schritt weiter. ich habe die Funktion nochmals angepasst: void HC595Pulse() { // Pulse shift clock HC595_PORT |= (1 << HC595_SH_CP_POS); // HIGH HC595_PORT &= (~(1<<HC595_SH_CP_POS)); // LOW } PS: Ich werde die Variablen noch umbenennen. Jetzt funktionert alles wie geplant, bis auf ein Detail: Wenn ich den Code auf den ATMEGA lade, blitzen die ersten 3 LEDS (11100000) kurz auf bevor das richtige Ergebnis erscheint. Dabei habe ich hier ja noch keine Daten übertragen?
Sebastian S. schrieb: > Wenn ich den > Code auf den ATMEGA lade, blitzen die ersten 3 LEDS (11100000) kurz auf > bevor das richtige Ergebnis erscheint Nach dem Einschalten sind die Ausgänge des 595 erstmal grundsätzlich unbestimmt und zufällig. Dagegen gibt es verschiedene Massnahmen, z.B. kannst du mit /OE des 595 die Ausgänge abschalten, bis sie richtig programmiert sind. Dazu musst du dafür sorgen, dass /OE nach einem Reset nicht Lo ist, z.B. kannst du einen Port des Prozessors nehmen, der nach Reset hochohmig ist, und einen Pullup. Ob sich das lohnt, musst du wissen. Wegen der LEDs nicht unbedingt, aber wenn Motore oder Ventile angesteuert werden, muss auch der Initialisierungsvorgeng durchdacht werden, sowohl in Hardware als auch in Software. Zu beachten: der 595 hat einen schweren Designfehler: der Reseteingang heisst zwar Master Reset, schaltet aber keineswegs die Ausgänge auf 0, erst nach einem zusätzlichen Clock-Impuls. Es gibt daher keine sichere Methode, den 595 zu resetten, nur wie oben beschrieben die Ausgänge abzuschalten und später freizugeben. Georg
Georg schrieb: > Master Reset, schaltet aber keineswegs die Ausgänge auf 0, > erst nach einem zusätzlichen Clock-Impuls. > ... > Es gibt daher keine sichere > Methode Obiges ist keine sichere Methode? (hab den Reset nie gebraucht)
Sebastian S. schrieb: > int main(void) > { > while (1) { > } > > return (0); > } Irgendwie vermisse ich hier was... Nur weil unten dran der Quellcode der H-Datei steht, ruft sich da noch keine Funktion selbst auf. Davon abgesehen - kleines Rätsel: a) wie lange braucht der Controller für while(1) b) wann wird in dem Programm return(0) ausgeführt c) wieso int main(), wer holt sich den zurückgegebenen Wert ab (und wann)
Teo D. schrieb: > Obiges ist keine sichere Methode? Wenn der Clk vom Prozessor kommt (wie üblich), nein - Reset sollte ja wirksam sein, bevor der Prozessor anläuft. Also z.B. während die Versorgungspannung noch nicht auf Sollwert ist, und auch gerade dann wenn der Prozessor garnicht anläuft, um Schäden zu verhindern. Teo D. schrieb: > (hab den Reset nie gebraucht) Mit dem Designfehler ist er auch nicht zu gebrauchen. Georg
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.