Forum: Compiler & IDEs SPI schieberegister


von spong3bob (Gast)


Lesenswert?

Hallo!
Ich versucher gerade mein erstes gcc programm zu schreiben und hab 
anscheinend irgendwo einen fehler drin.
in meiner schaltung habe ich einen ATMega16 und eine Schieberegister.

http://img844.imageshack.us/i/schaltung12.png/

Das ist meine schaltung (den rest einfach mal wegdenken...)

und jetzt wollt ich mal ein programm schreiben, das einfach nur jedes 2. 
LED im schieberegister leuchten lasst. (nur mal zu testzwecken)
1
#include <avr/io.h>
2
#define RCK PB4
3
#define SIN PB5
4
#define SCK PB7
5
6
int main(void)
7
{
8
  DDRB = (1 << RCK) | (1 << SIN) | (1 << SCK);
9
  PORTB = (1<<RCK) | (1 << PB6);
10
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL);
11
  SPSR |= (1 << SPI2X);
12
13
  char data = 0b01010101;
14
  while(1)
15
  {
16
    SPDR = data;
17
18
    while (!(SPSR & (1 << SPIF)));
19
20
    SPDR;
21
    PORTB &= ~(1<<RCK);
22
    PORTB |= (1<<RCK);
23
  }  
24
}

aber mit dem programm leuchten immer alle 8 LEDs

von Dieter M. (Gast)


Lesenswert?

spong3bob schrieb:
> while (!(SPSR & (1 << SPIF)));

In der While-Schleife passiert doch gar nichts, oder sehe ich das 
falsch?

von Sesk K. (zeborok)


Lesenswert?

Was für Schieberegister verwendest du? Die z.B. HC595? Bedenke, dass die 
noch Latches vor ihren Ausgängen haben und du noch nen Freigabetakt hast 
neben dem Schiebetakt.
Über RCK schiebst du? Mache mal nen kleinen Delay von vllt. µs 50 
dazwischen.
Wieso das "SPDR;" vor dem RCK-Strobe?

von spong3bob (Gast)


Lesenswert?

Den code hab ich von dort abgeschaut:
http://www.rn-wissen.de/index.php/Portexpander_am_AVR

ich verwende ein HCT595.

while (!(SPSR & (1 << SPIF)));
wartet wenn ichs richtig verstanden hab darauf, dass die bits gesendet 
wurden. ( was den delay eigentlich auch unnötig macht? )

von spong3bob (Gast)


Lesenswert?

(sry für doppelpost kann als gast nicht editieren)
mit dem wait dazwischen ändert sich nix...
1
PORTB &= ~(1<<RCK);
2
_delay_ms(50);
3
PORTB |= (1<<RCK);

von Armin (Gast)


Lesenswert?

Se Sk. schrieb:
> Wieso das "SPDR;" vor dem RCK-Strobe?

jo, mach das mal raus! die sollte eigentlich nichts tun, vielleicht 
wurde sie sogar wegoptimiert.

außerdem glaube ich, das RCK muss eine positive Flanke zum speichern 
bekommen. Also die beiden Zeilen vom Strobe bei Gelegenheit vertauschen. 
Dürfte aber bei dem kleinen Programm nichts machen

wie CPOL eingestellt ist, ist bei mir egal, kannst also auch auf default 
lassen für die reine Ausgabe.

Das delay ist nicht nötig.



Was mich wundert, ist dass du sagst, dass ALLE LEDs immer leuchten. 
Könnte es nicht sein, dass das Programm einfach funktioniert und du die 
LEDs zufälligerweise genau so falsch angeschlossen hast, dass alle immer 
an sind? Versuch doch mal andere Kombinationen für data...?

von spong3bob (Gast)


Lesenswert?

Hab das programm neu geschrieben:
1
unsigned char sternschnuppe_data=0b00000001;
2
3
void init_sternschnuppe(void)
4
{
5
  DDRB |= (1<<RCK) | (1<<SIN) | (1<<SCK);
6
  PORTB |= (1<<RCK);
7
  SPCR = (1 << SPE) | (1<<MSTR);
8
  SPSR |= (1<<SPI2X);
9
}
10
11
void write_sternschnuppe(void)
12
{
13
  SPDR = sternschnuppe_data;
14
    while (!(SPSR & (1 << SPIF)));
15
  PORTB |= (1<<RCK);
16
  PORTB &= ~(1<<RCK);
17
}

und im main dann nit und write noch vor der mainloop aufgerufen. (dann 
sollte sich das doch auch nicht ändern?)

und noch immer leuchten alle LEDs.

von jakob m. (spong3bob)


Lesenswert?

wie sollte ich die leds falsch anschließen? ich hab + auf +12V
(-) über einen widerstand auf den register-ausgängen.

Beim schieberegister hab ich SCL mim reset vom µC zusammengehängt (und 
der is die ganze zeit auf high), und den rest halt so wie auf dem plan 
(1. post)

von Stefan E. (sternst)


Lesenswert?

jakob m. schrieb:
> wie sollte ich die leds falsch anschließen? ich hab + auf +12V
> (-) über einen widerstand auf den register-ausgängen.

Jap, genau dann leuchten sie immer. Mit den Ausgängen kannst du dann 
höchsten die Helligkeit leicht variieren.

von jakob m. (spong3bob)


Lesenswert?

oh... kannst du mir auch verraten, wie ich sie einzeln zum leuchten 
bringe?

von Stefan E. (sternst)


Lesenswert?

Indem du sie an die 5V anschließt (natürlich mit entsprechend 
angepassten Vorwiderständen), nicht an die 12V.

von jakob m. (spong3bob)


Lesenswert?

so. habs jetzt an 5V angeschlossen mit einem 100ohm widerstand. jetzt 
blinkts nurnoch am anfang einmal kurz auf, wenn ich einsteck. aber 
irgendwas dürft mit dem programm wieder nicht passen :-/ hab probiert 
das write_sternschnuppe nur vor der main-loop aufzurufen und auch in der 
main-loop (kein unterschied).

von Andreas B. (Gast)


Lesenswert?

Armin schrieb:
> Se Sk. schrieb:
>> Wieso das "SPDR;" vor dem RCK-Strobe?
>
> jo, mach das mal raus! die sollte eigentlich nichts tun, vielleicht
> wurde sie sogar wegoptimiert.

SPDR sollte als Register eine volatile Variable sein und kann daher 
nicht wegoptimiert werden. Durch diese Zeile wird SPDR lesen und der 
gelesene Wert ignoriert.

von Karl H. (kbuchegg)


Lesenswert?

Du musst auch noch SS als Ausgang konfigurieren.

von Stefan E. (sternst)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Du musst auch noch SS als Ausgang konfigurieren.

Ist es. Trägt in seinem Programm den Namen "RCK".

von jakob m. (spong3bob)


Lesenswert?

warum funktioniert das eigentlich mit den 12V nicht? sollte doch auch 
funktionieren, wenn ich einen passenden widerstand einbau?

Edit: kann es sein, dass es zu problemen kommt, wenn die kabel (vom µC 
zum schieberegister) etwas länger sind? (ca. 1,5m)

von Stefan B. (steckersammler)


Lesenswert?

jakob m. schrieb:
> warum funktioniert das eigentlich mit den 12V nicht? sollte doch auch
> funktionieren, wenn ich einen passenden widerstand einbau?
Eigentlich ganz logisch:
- SR-Ausgang ist LOW => 12V-0V = 12V über LED+Vorwiderstand => leuchtet
- SR-Ausgang ist HIGH => 12V-5V = 7V über LED+Vorwiderstand => leuchtet 
auch

Dadurch leuchtet die LED in beiden Zuständen, die Unterschiede in der 
Helligkeit dürften so gering sein, dass du sie nicht bemerkst. Wurde 
auch weiter oben schon geschrieben...

Wenn du die LEDs an 5V anschließt, hast du:
- SR-Ausgang LOW => 5V-0V = 5V über LED+Vorwiderstand => LED leuchtet
- SR-Ausgang HIGH => 5V-5V = 0V über LED+Vorwiderstand => LED leuchtet 
nicht

Tada... ;)

MfG Stefan

von Karl H. (kbuchegg)


Lesenswert?

Stefan Ernst schrieb:
> Karl Heinz Buchegger schrieb:
>> Du musst auch noch SS als Ausgang konfigurieren.
>
> Ist es. Trägt in seinem Programm den Namen "RCK".

Ah ja.
Im Original ganz oben sieht man es.
Mein Fehler

von Karl H. (kbuchegg)


Lesenswert?

jakob m. schrieb:
> warum funktioniert das eigentlich mit den 12V nicht? sollte doch auch
> funktionieren, wenn ich einen passenden widerstand einbau?
>
> Edit: kann es sein, dass es zu problemen kommt, wenn die kabel (vom µC
> zum schieberegister) etwas länger sind? (ca. 1,5m)

Möglich, aber nicht sehr wahrscheinlich.

Zeig doch mal dein komplettes jetziges Programm.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Du gestattest, dass ich deinen Schaltplan hier ins Forum poste?
Aber die hüpfenden Bälle da bei Imageshack machen mich wahnsinng.
Und ausserdem seh ich nicht ein, warum der Schaltplan vom Programm 
getrennt werden soll. Programm hier - Schaltplan hier.

von jakob m. (spong3bob)


Lesenswert?

so mal das aktueller programm:
1
#define RCK PB4
2
#define SIN PB5
3
#define SCK PB7
4
5
extern unsigned char sternschnuppe_data;
6
7
extern void init_sternschnuppe(void);
8
extern void write_sternschnuppe(void);
1
unsigned char sternschnuppe_data=0b11110000;
2
3
void init_sternschnuppe(void)
4
{
5
  DDRB |= (1<<RCK) | (1<<SIN) | (1<<SCK);
6
  PORTB |= (1<<RCK);
7
  SPCR = (1 << SPE) | (1<<MSTR);
8
  SPSR |= (1<<SPI2X);
9
}
10
11
void write_sternschnuppe(void)
12
{
13
  SPDR = sternschnuppe_data;
14
    while (!(SPSR & (1 << SPIF)));
15
  //SPDR;
16
  PORTB |= (1<<RCK);
17
  PORTB &= ~(1<<RCK);
18
}
1
int main(void)
2
{
3
4
  init_sternschnuppe();
5
  //write_sternschnuppe();
6
  while(1)
7
  {
8
    write_sternschnuppe();
9
  }  
10
}

hab schon alle kombinationen probiert (nur am anfang write, nur in der 
schleife write, beides, mit spdr; ohne spdr;)

jetzt hab ich gerade die richtigen leds zum leuchten gebracht, wie ich 
den ISP stecker im laufenden betrieb angesteckt hab. wie ich dann den 
strom wieder aus/eingesteckt hab wars wieder weg...

Ok. mir is gerade das massekabel von buchsenstecker abgerissen. vll hats 
ja deshalb probleme gegeben ...

von Stefan E. (sternst)


Lesenswert?

Bitte auch mal die echte aktuelle Schaltung zeigen. Die im ersten Post 
kann ja schon mal nicht gestimmt haben. Dort sind 4 LED gegen Masse 
angeschlossen. Und die haben mich zuerst vom Antworten abgehalten, denn 
dass die oberen immer leuchten würden, habe ich gleich gesehen, konnte 
mir aber nicht erklären, warum auch die unteren 4 leuchten sollten. Wer 
weiß, was da noch so alles anders ist.

von jakob m. (spong3bob)


Lesenswert?

Hab leider keinen aktuelleren schaltplan. aber die LEDs sind jetzt mit 
(+) am 7805 angehängt und mit (-) über einen 100ohm widerstand an den 
ausgängen vom schieberegister.

ich glaub ich hab jetzt nurnoch irgendwo eine schlechte verbindung 
(schlecht gelötet) weil wenn ich die kleine platine nimm (auf der das 
schieberegister und die leds draufgelötet sind und biss hin und her 
beweg leuchten manchmal die 4 LEDs auf

Edit: ok vll isses doch was anderes. Wenn ich direkt von oben auf die 
leds schau seh ich, dass sie leicht flackern ( nur die 4, die ich auf 1 
hab)

Wenn ich jetzt den ISP stecker einsteck (zum eval board) dann leuchten 
die 4 LEDs solange, bis die betriebs-LED vom evalboard leuchtet. dann 
isses wieder vorbei. allerdings solange sie leuchten leuchten sie 
richtig stark.

von jakob m. (spong3bob)


Lesenswert?

grad was neues probiert, und das funktionier auch nicht:
1
void init_sternschnuppe(void)
2
{
3
  DDRB |= (1<<RCK) | (1<<SIN) | (1<<SCK);
4
  //PORTB |= (1<<RCK);
5
  //SPCR = (1 << SPE) | (1<<MSTR);
6
  //SPSR |= (1<<SPI2X);
7
}
8
9
void write_sternschnuppe(void)
10
{
11
  //SPDR = sternschnuppe_data;
12
  PORTB |= (1<<SIN);
13
  PORTB |= (1<<SCK);
14
  PORTB &= ~(1<<SCK);
15
  PORTB |= ~(1<<SIN);
16
  PORTB |= (1<<SCK);
17
  PORTB &= ~(1<<SCK);
18
  PORTB |= (1<<SCK);
19
  PORTB &= ~(1<<SCK);
20
  PORTB |= (1<<SCK);
21
  PORTB &= ~(1<<SCK);
22
  PORTB |= (1<<SCK);
23
  PORTB &= ~(1<<SCK);
24
  PORTB |= (1<<SCK);
25
  PORTB &= ~(1<<SCK);
26
  PORTB |= (1<<SCK);
27
  PORTB &= ~(1<<SCK);
28
  PORTB |= (1<<SCK);
29
  PORTB &= ~(1<<SCK);
30
    //while (!(SPSR & (1 << SPIF)));
31
  //SPDR;
32
  PORTB |= (1<<RCK);
33
  PORTB &= ~(1<<RCK);
34
}

von Karl H. (kbuchegg)


Lesenswert?

Schreib dir jeweils eine Funktion die ein 0-Bit ausgibt bzw ein 1 Bit 
ausgibt, mach ein _delay_ms( 1000 ) zwischen die einzelnen Schritte (so 
dass der Transfer extrem langsam abläuft) und dann geh mit einem 
Messgerät (oder zuätzlichen LED) auf die Steuerbeinchen des 595 und sieh 
nach, was dort ankommt.
1
void OutOne()
2
{
3
  PORTB |= (1<<SIN);
4
5
  _delay_ms( 1000 );
6
7
  PORTB |= (1<<SCK);
8
9
  _delay_ms( 1000 );
10
11
  PORTB &= ~(1<<SCK);  
12
13
  _delay_ms( 1000 );
14
}
15
16
void OutZero()
17
{
18
  PORTB &= ~(1<<SIN);
19
20
  _delay_ms( 1000 );
21
22
  PORTB |= (1<<SCK);
23
24
  _delay_ms( 1000 );
25
26
  PORTB &= ~(1<<SCK);  
27
28
  _delay_ms( 1000 );
29
}
30
31
void write_sternschnuppe(void)
32
{
33
  OutOne();
34
  OutZero();
35
  OutOne();
36
  OutZero();
37
  OutOne();
38
  OutZero();
39
  OutOne();
40
  OutZero();
41
42
  PORTB |= (1<<RCK);
43
  _delay_ms( 1000 );
44
  PORTB &= ~(1<<RCK);
45
  _delay_ms( 1000 );
46
}

von jakob m. (spong3bob)


Lesenswert?

seltsame sache. wenn ich mit den fingern in die nähe vom board komm 
fangts zum blinken an (die 4 leds, die blinken sollen). wenn ich wieder 
weggeh isses wieder aus..

von Karl H. (kbuchegg)


Lesenswert?

Bring erst mal deine Hardware in Ordnung.
Das hat doch keinen Sinn, wenn man sich nicht darauf verlassen kann, 
dass alle Verbdinungen auch tatsächlich in Ordnung sind.

Ausserdem darf bei DEM Programm keine der Ausgangsled blinken.

von jakob m. (spong3bob)


Lesenswert?

1
int main(void)
2
{
3
  
4
  //init_sternschnuppe();
5
  //write_sternschnuppe();
6
  DDRB |= (1<<PB4);
7
  DDRB |= (1<<PB5);
8
  DDRB |= (1<<PB7);
9
  PORTB &= ~(1<<PB5);
10
    _delay_ms(2000);
11
    PORTB |= (1<<PB7);
12
    PORTB &= ~(1<<PB7);
13
    PORTB |= (1<<PB7);
14
    PORTB &= ~(1<<PB7);
15
    PORTB |= (1<<PB7);
16
    PORTB &= ~(1<<PB7);
17
    PORTB |= (1<<PB7);
18
    PORTB &= ~(1<<PB7);
19
    PORTB |= (1<<PB7);
20
    PORTB &= ~(1<<PB7);
21
    PORTB |= (1<<PB7);
22
    PORTB &= ~(1<<PB7);
23
    PORTB |= (1<<PB7);
24
    PORTB &= ~(1<<PB7);
25
    PORTB |= (1<<PB7);
26
    PORTB &= ~(1<<PB7);
27
    
28
    
29
    
30
    PORTB |= (1<<PB4);
31
    _delay_ms(2000);
32
    PORTB &= ~(1<<PB4);
33
    _delay_ms(2000);
34
  while(1)
35
  {
36
    
37
    //write_sternschnuppe();
38
  }  
39
}

das lasst jetzt alle LEDs leuchten
allerdings hab ich da angst, dass ich meinen 7805 kill... der wird schon 
ziemlich heiß, wenn die auch nur kurz alle leuchten.. (was hoffentlich 
nicht das problem sein sollt, weil sowieso immer nur 1-2 davon leuchten 
sollen (wird ein lauflicht)

von Karl H. (kbuchegg)


Lesenswert?

jakob m. schrieb:

> allerdings hab ich da angst, dass ich meinen 7805 kill... der wird schon
> ziemlich heiß,

wenn du den mit 12V fütterst, wundert mich das nicht besonders.

von jakob m. (spong3bob)


Lesenswert?

naja.. hab ja eigentlich auch nur vorgehabt den µC und den IR sensor 
damit zu betreiben...

von jakob m. (spong3bob)


Lesenswert?

kaum funktioniert mal was kommt auch schonwieder das nächste problem.
nach dem letzten überspielen hat ponyprog den µC nicht mehr erkannt...
d.h. wenn ich auf lesen gehe sagt er, dass nix an com3 angeschlossen ist 
(ist es aber) und die LEDs fangen auch zum blinken an (was sie vorher 
auch schon gemacht haben) eigentlich dürfte ich an den fuses nichts 
geändert haben, weil ich immer vor dem überschreiben ein load gemacht 
hab.

von jakob m. (spong3bob)


Lesenswert?

So.. Hab neuen µC gekauft und alles neu gelötet.
1
#define RCK PB4
2
#define SIN PB5
3
#define SCK PB7
4
5
6
int main(void)
7
{
8
  DDRB = (1<<PB4)|(1<<PB5)|(1<<PB7);
9
    
10
  PORTB |= (1<<SIN);
11
  _delay_ms(10);
12
  
13
  PORTB |= (1<<SCK);
14
  _delay_ms(10);
15
  PORTB &= ~(1<<SCK);
16
  _delay_ms(10);
17
  
18
  PORTB |= (1<<SCK);
19
  _delay_ms(10);
20
  PORTB &= ~(1<<SCK);
21
  _delay_ms(10);
22
  
23
  PORTB |= (1<<SCK);
24
  _delay_ms(10);
25
  PORTB &= ~(1<<SCK);
26
  _delay_ms(10);
27
  
28
  PORTB |= (1<<SCK);
29
  _delay_ms(10);
30
  PORTB &= ~(1<<SCK);
31
  _delay_ms(10);
32
  
33
  PORTB &= ~(1<<SIN);
34
  _delay_ms(10);
35
  
36
  PORTB |= (1<<SCK);
37
  _delay_ms(10);
38
  PORTB &= ~(1<<SCK);
39
  _delay_ms(10);
40
  
41
  PORTB |= (1<<SCK);
42
  _delay_ms(10);
43
  PORTB &= ~(1<<SCK);
44
  _delay_ms(10);
45
  
46
  PORTB |= (1<<SCK);
47
  _delay_ms(10);
48
  PORTB &= ~(1<<SCK);
49
  _delay_ms(10);
50
  
51
  PORTB |= (1<<SCK);
52
  _delay_ms(10);
53
  PORTB &= ~(1<<SCK);
54
  _delay_ms(10);
55
  
56
  PORTB |= (1<<RCK);
57
  _delay_ms(10);
58
  PORTB &= ~(1<<RCK);
59
  _delay_ms(10);
60
  
61
  
62
  while(1)
63
  {}
64
65
  return 0;
66
}

das is ein programm zum testen. allerdings leuchten da auch alle 8 LEDs 
und nicht nur die 4, die ich will..
hab auch schon durchgetestet. die anschlüsse stimmen alle und er setzt 
sie auch auf high, wenn ichs ihm sag..

von jakob m. (spong3bob)


Lesenswert?

Ok. habs jetzt soweit, dass das funktioniert:
1
void OutOne()
2
{
3
  PORTB |= (1<<SIN);
4
5
  _delay_ms( 1000 );
6
7
  PORTB |= (1<<SCK);
8
9
  _delay_ms( 1000 );
10
11
  PORTB &= ~(1<<SCK);  
12
13
  _delay_ms( 1000 );
14
}
15
16
void OutZero()
17
{
18
  PORTB &= ~(1<<SIN);
19
20
  _delay_ms( 1000 );
21
22
  PORTB |= (1<<SCK);
23
24
  _delay_ms( 1000 );
25
26
  PORTB &= ~(1<<SCK);  
27
28
  _delay_ms( 1000 );
29
}
30
31
void write_sternschnuppe(void)
32
{
33
  OutOne();
34
  OutZero();
35
  OutOne();
36
  OutZero();
37
  OutOne();
38
  OutZero();
39
  OutOne();
40
  OutZero();
41
42
  PORTB |= (1<<RCK);
43
  _delay_ms( 1000 );
44
  PORTB &= ~(1<<RCK);
45
  _delay_ms( 1000 );
46
}

aber mit spi hab ichs immer noch nicht zum laufen gebracht..

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
Noch kein Account? Hier anmelden.