Forum: Mikrocontroller und Digitale Elektronik atmega32 & 74HC595 Schieberegister


von Hanoii (Gast)


Lesenswert?

Hallo zusammen,

versuche schon den ganzen Tag erfolglos mein 74HC595 vernünftig 
anzusteuern. Habe einfach mal drauf los getestet und probiert aber denke 
mal dass ich einfach Denkfehler oder Wissenslücken habe. Vielleicht kann 
ja mal einer drüber schauen und Tipps geben

spi.h
1
#ifndef SPIF
2
#define SPIF 7
3
#endif
4
5
unsigned char spi(unsigned char data)
6
{
7
SPDR=data;
8
while ((SPSR & (1<<SPIF))==0);
9
return SPDR;
10
}

main.c
1
#ifndef F_CPU
2
#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
3
#define F_CPU 16000000UL     /* Quarz mit 3.6864 Mhz  */
4
#endif
5
6
7
#include <avr\io.h>
8
#include <util\delay.h>
9
#include "spi.h"
10
11
12
#define DD_MOSI     PINB5
13
14
#define DD_SCK     PINB7
15
16
#define DDR_SPI    PORTB
17
18
void SPI_MasterInit(void)
19
20
{
21
22
// Set MOSI and SCK output, all others input
23
24
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
25
26
// Enable SPI, Master, set clock rate fck/16
27
28
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
29
30
}
31
32
33
34
int main(void) {
35
36
SPI_MasterInit();
37
38
39
  while (1)
40
      {
41
        PORTB |= (1<<PB4);
42
      // Place your code here
43
          spi(0xff);
44
   _delay_ms(2000);
45
   spi(0);
46
   _delay_ms(2000);
47
      PORTB &= ~(1<<PB4);
48
      
49
      };
50
51
52
}

Benutze einen atmega32 und ja ich weiss alles etwas wirsch aber wäre 
trotzdem über Hilfe dankbar.

Gruß Snaper

von Karl H. (kbuchegg)


Lesenswert?

Hanoii schrieb:

> DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
>
> // Enable SPI, Master, set clock rate fck/16
>
> SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);

Aus dem Gedächtnis:
Du musst auch SS auf Ausgang setzen, sonst ist dein SPI kein Master.
Aber schau zur Sicherheit noch mal ins Datenblatt.

von Hanoii (Gast)


Lesenswert?

Okay,

das habe ich zwar nicht bedacht aber dennoch ist leider noch keine 
Besserung in Sicht.

von Matthias K. (matthiask)


Lesenswert?

Schaltung? Was klappt eigentlich genau nicht?

von Purzel H. (hacky)


Lesenswert?

Zum Einen kann man die Signale hinreichend langsam setzten, sodass man's 
auch nachmessen kann, zum Anderen gibt es auch oszilloskope.

von Joachim B. (jojo84)


Lesenswert?

Das wäre auch meine Frage gewesen, was eigentlich nicht geht...

Ich hatte an meiner Schieberegisterkaskade über zwei Tage rumgedoktort, 
bis ich feststellen mußten, daß ich einen Lötfehler drin hatte... -_O

Edit: schaue er auch bitte hier (falls noch nicht geschehen):
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister

von Hanoii (Gast)


Lesenswert?

Also es sieht wie folgt aus. Wenn ich einen 74HC595 dran habe dann 
funktioniert es jedoch nicht mehr wenn ich 2 kaskadierte dran habe...

Bevor wieder die Frage kommt was icht genau funktioniert möchte ich 
diese natürlich vorher klären. ;) Und zwar kommt mehr oder weniger an 
den Ports nur "Mist" an. Wenn ich z.b. serpa[0] = 0xff; serpa[1] = 0xff; 
schreibe dann sollten ja alle Ports durchschalten aber es sind nur 
vereinzelt LEDs an bzw werden nur einzelne Ports durchgeschaltet. 
Atmega32 @16Mhz wird genutzt. Für Hilfe wäre ich sehr dankbar.

Folgenden Code nehme ich dazu:
serpa.h
1
/* SERiell nach PArallel (serpa) im SPI-Protokoll */
2
#ifndef _SERPA_H_
3
#define _SERPA_H_
4
5
/* 4 Bytes (32 Ports) */
6
#define SERPA_SIZE 2 
7
/* Das muss auf 1 sein, wenn man nur ein Schieberegister benutzt ... das wir dauch bei dem serp-- und so benutzt.*/
8
9
extern unsigned char serpa[];
10
extern void serpa_out (void);
11
extern void serpa_init (void);
12
13
#endif /* _SERPA_H_ */
14
15
//SERPA.h ende ------------------------

schiebe.c
1
#ifndef F_CPU
2
#define F_CPU 16000000UL
3
#endif
4
5
// SERiell nach PArallel (serpa) mit Hardware-Unterstuetzung 
6
#include <avr/io.h>
7
#include "serpa.h"
8
#include <util\delay.h>
9
10
unsigned char serpa[SERPA_SIZE];
11
unsigned char maske(unsigned char input);
12
13
// Array fuer die Daten 
14
15
void serpa_init (void)
16
{
17
18
   DDRB=0xff;
19
   PORTB |= (1<<PB4);
20
21
   // !!! SS muss OUT sein, damit SPI nicht in Slave-Mode wechselt !!! 
22
   // entfaellt, falls PORT_RCK = PORT_SS 
23
24
   // SPI als Master 
25
   // High-Bits zuerst 
26
   // SCK ist HIGH wenn inaktiv 
27
   SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL);
28
  
29
   // pullup an MISO vermeidet Floaten 
30
   PORTB |=(1<<PB6);
31
32
   // maximale Geschwindigkeit: F_CPU / 2 
33
   SPSR |= (1 << SPI2X);
34
}
35
36
void serpa_out (void)
37
{
38
   
39
   unsigned char anz = SERPA_SIZE;
40
   unsigned char* serp = serpa+SERPA_SIZE;
41
42
   do
43
   {
44
      unsigned char data = *--serp;
45
46
      // SPDR schreiben startet Uebertragung 
47
      SPDR = data;
48
49
      // warten auf Ende der Uebertragung für dieses Byte 
50
      while (!(SPSR & (1 << SPIF)));
51
52
      // clear SPIF durch Lesen von SPDR 
53
      SPDR;
54
   }
55
   while (--anz > 0);
56
  
57
58
   // Strobe an RCK bringt die Daten von den Schieberegistern in die Latches 
59
   PORTB &=~ (1<<PB4);
60
   PORTB |= (1<<PB4);
61
}
62
63
int main (void)
64
{
65
  serpa_init();
66
  while(1)
67
  {
68
    
69
70
  serpa[0] = 0xff;
71
  serpa[1] = 0xff;
72
  serpa_out();
73
  }
74
}
75
76
unsigned char maske(unsigned char input)
77
{
78
  return 0xFF ^ input;
79
}

von Hanoii (Gast)


Lesenswert?

So langsam schließe ich einen Softwarefehler aus also das Problem ist, 
dass die Nullen nahezu "verschluckt" werden. Wenn ich auf beide 0xff 
schreibe, dann gehen alle an aber sobald ich eine Null drin habe geht es 
den Bach runter und es kommen ziemlich "wilde" Zustände zum vorschein. 
Woran könnte dies liegen?

Ein Oszi habe ich leider nicht sodass ich mir das Signal nicht richtig 
angucken kann leider.

von Karl H. (kbuchegg)


Lesenswert?

Was passiert, wenn du hier

>    // maximale Geschwindigkeit: F_CPU / 2
>   SPSR |= (1 << SPI2X);

probehalber mal weniger Vollgas gibst?

von Hanoii (Gast)


Lesenswert?

Habe den Fehler beheben können und zwar war die Lösung des Rätsels 
folgende:

Die Vcc und GNDs der beiden einzelnen ICs weiter weg stecken und 
möglichst IC nahe jedem der beiden ICs ein Entstörkondensator spendiert. 
Ergo war wohl etwas zu viel "Noise" auf der Leitung und das macht sich 
bei denen wohl schnell bemerkbar. Habe ich aber nur durch Zufall herraus 
gefunden da ich die Schaltung nochmal neu gesteckt habe.

Naja aus Fehlern lernt man. :)

Aber vielen dank für eure Tipps.

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.