www.mikrocontroller.net

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


Autor: Paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <io.h>


#define DOUT    0
#define SCK     1
#define STB     2               // load output register
#define SPIPORT PORTB
#define SPIDIR  DDRB


void spi_out( unsigned char val )
{
  unsigned char i;

  SPIDIR |= 1<<DOUT^1<<SCK^1<<STB;      // outputs

  for( i = 8; i; i-- ){
    SPIPORT &= ~(1<<DOUT);      // DOUT = 0
    if( val & 0x80 )
      SPIPORT |= 1<<DOUT;       // DOUT = 1
    val <<= 1;
    SPIPORT &= ~(1<<SCK);       // SCK = 0
    SPIPORT |= 1<<SCK;          // SCK: 0->1
  }
  SPIPORT &= ~(1<<STB);
  SPIPORT |= 1<<STB;            // STB: 0->1
}


Peter

Autor: Paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
#include <avr/io.h>      // ein und ausgaenge
#include <avr/delay.h>      // definiert _delay_ms() ab avr-libc
Version 1.2.0 
#define F_CPU 1000000UL     // 1 MHz

// Initialisierung
void init(void)
{
  DDRA = 0xff;    // PortA als Ausgang deklarieren
  PORTA = 0x00;    // PortsA auf LOW schalten
}

void SPI_MasterInit(void)
{
  // set MOSI and SCK output, all others input
  DDRB |= (1<<PB5)|(1<<PB7);    
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(uint8_t data)
{
  SPDR = data;  //start transmission
  while(!(SPSR & (1<<SPIF))); //wait for transmission complete
}


//---------------------- main -------------------------
int main(void)
{  
  init();
  SPI_MasterInit();    
  while (1)
  {   
    SPI_MasterTransmit(0b11110000);
    PORTA = 0xff;  // storage 1
    _delay_ms(1000);
    PORTA = 0x00; // storage 0
    SPI_MasterTransmit(0b00001111);
    PORTA = 0xff;   // storage 1
    _delay_ms(1000);
    PORTA = 0x00;  // storage 0
  }
}

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
while(!(SPSR & (1<<SPIF))); //wait for transmission complete
aufhört?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.