Forum: Mikrocontroller und Digitale Elektronik Schieben bis der Arzt kommt (74HC595)


von Paul (Gast)


Lesenswert?

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?

von Jan (Gast)


Lesenswert?

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.

von Paul (Gast)


Lesenswert?

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?

von Jan (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Paul (Gast)


Lesenswert?

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