Ich verstehe es nicht. Seit einiger Zeit versuche ich ein Schieberegister (74HC595) anzusteuern. Klappt aber alles nicht so wie soll. An dem Dingen hängt ein 7-Segment Display. hier mein Test-Code _delay_ms(50); PORTA = 0b00000101; //SI high & SCK high _delay_ms(50); PORTA = 0b00000001; //SI low & SCK low _delay_ms(50); PORTA = 0b00000101; _delay_ms(50); PORTA = 0b00000001; _delay_ms(50); PORTA = 0b00000101; _delay_ms(50); PORTA = 0b00000001; _delay_ms(50); PORTA = 0b00000101; _delay_ms(50); PORTA = 0b00000001; _delay_ms(50); PORTA = 0b00000100; _delay_ms(50); PORTA = 0b00000000; _delay_ms(50); PORTA = 0b00000100; _delay_ms(50); PORTA = 0b00000000; _delay_ms(50); PORTA = 0b00000100; _delay_ms(50); PORTA = 0b00000000; _delay_ms(50); PORTA = 0b00000100; _delay_ms(50); PORTA = 0b00000000; _delay_ms(50); PORTA = 0b00000010; //RCK _delay_ms(50); PORTA = 0b00000000; _delay_ms(1000); PINA0 ist mit SI vom 74HC595 verbunden, PINA1 mit RCK (storage) und PINA2 mit SCK. Eigentlich will ich die ersten 4 Pins auf High ziehen, den Rest auf 0. Als Ausgabe erhalte ich aber 00011110 (QA...QH) ??? Wenn ich alles richtig verstanden habe, dann funktioniert das Dingen eigentlich so: Das Signal von SI wird bei einem Highpegel von SCK übernommen. Bei RCK = 1 wird das ganze dann ausgegeben. Richtig? Die erste Zahl, die ich reinschiebe entspricht dem QA, oder?
Schau dir im Datenblatt mal die "Timing Chart" an. Dort siehst du, dass das an SI anliegende Signal bei einem Wechsel an SCK von low nach high übernommen wird. Du musst also erst SI setzen und anschließend sck setzen: (1) SI=1 (2) SCK=1 (3) SI=0,SCK=0 Wenn du nur ein bit hineinschiebst, bzw. SCK einmal auf high ziehst, landet SI in QA. Setzt du SCK ein zweites Mal auf high, wird QA nach QB verschoben und wieder SI in QA. Auch das kannst du sehr schön in dieser Timing Chart nachvollziehen. 50ms sind für einen HC595 ("up to 55Mhz") aber deutlich übertrieben. 1µs reicht da vollkommen. PS: Für die effektive Benutzung eines Schieberegisters solltest du aber die (sofern vorhanden) SPI-Funktion deines µC nutzen.
Okey, werde es heute abend nochmal versuchen um das ganze besser verstehen zu können. Die 50ms habe ich erstmal nur zum testen eingebaut. Mein µC ist zur Zeit noch ein mega16 mit SPI. Später soll das dann mal auf einen tiny mit USI portiert werden. Deshalb bastel ich ja auch an den Schieberegistern ;) Hast du da zufällig mal einen Link wo das mit dem SPI beschrieben ist?
Im Datenblatt des µC steht das eigentlich recht verständlich drin. Du setzt den µC in den Master-Mode, stellst den prescaler ein (SPI Control Register) und kopierst anschließend einfach das zu sendende Byte ins SPI Data Register, das Senden erledigt sich dann von selbst.
Du solltest Dir vielleicht angewöhnen, Programme lesbarer zu schreiben. D.h. statt irgendwelche kryptische Hexwerte mit #defines arbeiten um dann im Code aussagekräftige Namen verwenden zu können. Auch ist es empfehlenswert, sich mal mit Schiebeoperationen und Schleifen zu beschäftigen, damit es nicht immer solche Spaghetticodeungetüme werden müssen. Das könnte dann z.B. so aussehen:
1 | #include <io.h> |
2 | |
3 | |
4 | #define DOUT 0
|
5 | #define SCK 1
|
6 | #define STB 2 // load output register
|
7 | #define SPIPORT PORTB
|
8 | #define SPIDIR DDRB
|
9 | |
10 | |
11 | void spi_out( unsigned char val ) |
12 | {
|
13 | unsigned char i; |
14 | |
15 | SPIDIR |= 1<<DOUT^1<<SCK^1<<STB; // outputs |
16 | |
17 | for( i = 8; i; i-- ){ |
18 | SPIPORT &= ~(1<<DOUT); // DOUT = 0 |
19 | if( val & 0x80 ) |
20 | SPIPORT |= 1<<DOUT; // DOUT = 1 |
21 | val <<= 1; |
22 | SPIPORT &= ~(1<<SCK); // SCK = 0 |
23 | SPIPORT |= 1<<SCK; // SCK: 0->1 |
24 | }
|
25 | SPIPORT &= ~(1<<STB); |
26 | SPIPORT |= 1<<STB; // STB: 0->1 |
27 | }
|
Peter
So, besten Dank für eure Hilfe! Ich habe gerade mit dem angepassten Beispiel von Peter alles hinbekommen! Danke!!! Mein Code war nicht sauber, weil er einfach nur fürs Testen benutzt werden sollte. Ansonsten bemühe ich mich schon das alles etwas übersichtlicher zu gestalten :) Jetzt aber zu meinem neuem Problem g (das hört wohl vorerst nicht auf - schlimm, wenn man feststellt was man alles noch nicht kann) Ich habe ganze geschichte jetzt über SPI getestet. Text
1 | #include <avr/io.h> // ein und ausgaenge |
2 | #include <avr/delay.h> // definiert _delay_ms() ab avr-libc |
3 | Version 1.2.0 |
4 | #define F_CPU 1000000UL // 1 MHz
|
5 | |
6 | // Initialisierung
|
7 | void init(void) |
8 | {
|
9 | DDRA = 0xff; // PortA als Ausgang deklarieren |
10 | PORTA = 0x00; // PortsA auf LOW schalten |
11 | }
|
12 | |
13 | void SPI_MasterInit(void) |
14 | {
|
15 | // set MOSI and SCK output, all others input
|
16 | DDRB |= (1<<PB5)|(1<<PB7); |
17 | SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); |
18 | }
|
19 | |
20 | void SPI_MasterTransmit(uint8_t data) |
21 | {
|
22 | SPDR = data; //start transmission |
23 | while(!(SPSR & (1<<SPIF))); //wait for transmission complete |
24 | }
|
25 | |
26 | |
27 | //---------------------- main -------------------------
|
28 | int main(void) |
29 | {
|
30 | init(); |
31 | SPI_MasterInit(); |
32 | while (1) |
33 | {
|
34 | SPI_MasterTransmit(0b11110000); |
35 | PORTA = 0xff; // storage 1 |
36 | _delay_ms(1000); |
37 | PORTA = 0x00; // storage 0 |
38 | SPI_MasterTransmit(0b00001111); |
39 | PORTA = 0xff; // storage 1 |
40 | _delay_ms(1000); |
41 | PORTA = 0x00; // storage 0 |
42 | }
|
43 | }
|
Ich habe mal mit einem Oszilloskop geguckt. Irgendwie scheint er einmal die Daten zu senden und dann aufzuhören. Kann das sein, dass der an dieser Stelle Text
1 | while(!(SPSR & (1<<SPIF))); //wait for transmission complete |
aufhört?
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.