Forum: Mikrocontroller und Digitale Elektronik Zwei Schieberegister in Reihe: Denkfehler?


von Joachim .. (joachim_01)


Angehängte Dateien:

Lesenswert?

/*
Hallo,
ich schicke Daten an zwei hintereinander geschaltete 74HC595 8-Bit 
Schieberegister an deren Ausgänge LEDs hängen. Nix besonderes 
eigentlich. Die Schaltung funktioniert, der Code ebenfalls - allerdings 
immer nur ein Mal.

1. Schieben
rein: 0x0001
raus: 0x0001
ok

2. Schieben
rein: 0x0002
raus: 0x0200
Versatz, nicht ok

3. Schieben
rein: 0x0004
raus: 0x0004
jetzt stimmt das Muster wieder,
allerdings ist der Vorgang nicht reproduzierbar, denn:


Zweiter Versuch:
1. Schieben
rein: 0x0001
raus: 0x0001
ok

2. Schieben
rein: 0x0000
raus: 0x0000
scheinbar ok

3. Schieben
rein: 0x0004
raus: 0x0000
wieder kaputt


Es kommt mir so vor als ob die beiden parallelen Eingänge 'clock storage 
register' der beiden Schieberegister, welches die Daten auf die 
Ausgabelatches schalten, Mucken machen. Ich hatte vorher schon 
Schwierigkeiten, "sofort" nach der Schiebefunktion die Daten in die 
Ausgaberegister zu schalten, der PIC war für diesen Schreibvorgang zu 
schnell. Nun ja.

Wenn ich die drei auskommentierten Zeilen wieder in den Code nehme, dann 
funktioniert es. Allerdings habe ich dann immer ein kurzes Zucken auf 
den LEDs. Stattdessen muße es aber doch möglich sein, beide '595 
gleichzeitig zu schalten, oder? Ich könnte zwar mit einer weiteren 
Port-Leitung alle Register im '595 löschen aber das ist ja nicht der 
Sinn der Sache.

Compiler: Hitech + PIC 18F4550

Anbei der Code, bitte mal über die Funktion void showInt595 (unsigned 
uPattern) drüber kucken, ob da vielleicht was fehlt.




Besten Dank für die Mithilfe

*/



1
#include <htc.h>
2
3
__CONFIG(1, FCMDIS & IESODIS & HS);
4
__CONFIG(2, BORDIS & BORV45 & PWRTEN & WDTDIS & WDTPS1);
5
__CONFIG(3, CCP2RB3 & LPT1DIS & 0xFDFF);
6
__CONFIG(4, DEBUGDIS & XINSTDIS & LVPDIS & STVRDIS);
7
__CONFIG(5, 0xFFFF);
8
__CONFIG(6, 0xFFFF);
9
__CONFIG(7, 0xFFFF);
10
11
#define storage_reg       PORTCbits.RC2
12
13
14
//prototypes
15
void wait (unsigned int);
16
void showInt595(unsigned);
17
18
19
void main (void)
20
{
21
22
unsigned int uValue;
23
 
24
/***************************************************************
25
* 20.07.2011
26
* spi 74HC595 shift register test
27
*
28
* Lines for PIC 18F4550:
29
* clk: RB1, Pin34
30
* Ser out, (in for '595): RC7, Pin14
31
* /G (output enable): RC6 (mußt be low)
32
* storage register: RC2, Pin12
33
* RD2: /SCLR clear latch (testing...)
34
**************************************************************/
35
// port directions: 1=input, 0=output
36
37
  PORTB  = 0b00000000;  //clear output data latch
38
  TRISB  = 0b00000000;  //set to output
39
 
40
  PORTC  = 0b00000000;  //clear output data latch
41
  TRISC  = 0b00000000;  //set to output
42
43
  PORTD  = 0b00000000;  //clear output data latch
44
  TRISD  = 0b00000000;  //set to output
45
  
46
//while (1) {
47
PORTCbits.RC0=1; // Einschalt-LED
48
wait (300);
49
PORTCbits.RC0=0; // Einschalt-LED
50
//wait (300);
51
//}
52
53
  OpenSPI  (SPI_FOSC_64, MODE_10, SMPMID);
54
55
  showInt595(0x0001); 
56
  wait (300);
57
58
  showInt595(0x0002); 
59
  wait (300);
60
61
  showInt595(0x0004); 
62
  wait (300);
63
64
  while (1);
65
 } // Ende main
66
67
68
//wait
69
void wait(unsigned int a) {
70
  unsigned int i,j;
71
    for (i = 0; i < a ; i++) {
72
       for (j = 1 ; j < 1000; j++); 
73
      }
74
}
75
76
77
78
/***************************************************************
79
* 20.07.2011
80
* 
81
*
82
* precondition:
83
* Lines for PIC 18F4550 mußt be properly initialised
84
* clk: RB1, Pin34, Pin11 at '595 
85
* Ser out: RC7, Pin14 at '595
86
* free selectable: output storage register: RC2 Pin17, Pin12 at '595
87
*
88
* /G (output enable): Pin13 on gnd
89
* /SCLR (clear shift register) Pin10 on Vcc
90
* /Qh (Pin9) output to the next 595's serial in, input Pin14 
91
*
92
* 
93
**************************************************************/
94
void showInt595 (unsigned uPattern) 
95
{
96
97
  unsigned uDummy1,uDummy2; // = unsigned int
98
  
99
100
  unsigned char ucPattern;
101
102
  //'595 No1
103
  //die 16bit in 2x 8bit zerlegen, unteres Byte:
104
  uDummy1 = uPattern;
105
  uDummy1= uDummy1 & 0x00FF;
106
  uDummy1 = (unsigned char) uDummy1;  //ist das eigentlich erlaubt bzw. notwendig???
107
  ucPattern = uDummy1;  
108
 
109
  WriteSPI(ucPattern);
110
  
111
  //wait (1);           // PIG zu schnell...?
112
  //storage_reg = 1;    // würde zwar funktionieren, erzeugt aber
113
  //storage_reg  = 0;   // ein kurzes störendes Blitzen auf den 
114
                        // korrespondierenden 8 bits
115
  
116
  //'595 No2  
117
  //die 16bit in 2x 8bit zerlegen, oberes Byte:
118
  uDummy2 = uPattern;
119
  uDummy2 >>= 8;
120
  uDummy2 = (unsigned char) uDummy2;
121
  ucPattern = uDummy2;  
122
123
  WriteSPI(ucPattern);
124
125
  wait (1);           // PIG zu schnell...?
126
   storage_reg = 1;   // alle 16 bits ins Ausgaberegister 
127
   storage_reg = 0;   // wieder freigeben
128
}

von (prx) A. K. (prx)


Lesenswert?

3,3V Ausgänge und 5V 74HC Eingänge passen nicht sehr gut zusammen. 74HCT 
oder die im Schaltplan aufgeführten 74LS wären passender.

Teste die 595er mal mit 3,3V. Oder den PIC mit jenen 5V, die er laut 
Datasheet offiziell benötigt.

Mal einen anderen SPI-Modus getestet?

von Joachim .. (joachim_01)


Lesenswert?

Die 3,3V hatte ich gleich zu Beginn auf 5V angehoben.
Hab alle vier Modi getestet, auch aufm Oszi. Die anderen Modi, (Idle auf 
high, Verschiebung um ein halbes Bit von data und clock) bringen nur 
Fehler.

Ich schiebe immer 16 bit. Denke ich. Als ob es aber 24 bit wären oder 
so...
Aber 24bit int gibt's ja nicht, oder? Zumal C18 default in einem 24-bit 
Speichermodell läuft...
Seltsam.

von Lutz (Gast)


Lesenswert?

Joachim ... schrieb:
> //while (1) {
> PORTCbits.RC0=1; // Einschalt-LED
.
.
.
>   while (1);
>  } // Ende main

Machen die beiden whiles denn auch das, was sie sollen? Zumindest das 
Obere ist nach derzeitigem Stand überflüssig.

Joachim ... schrieb:
> unsigned uDummy1,uDummy2; // = unsigned int
>   unsigned char ucPattern;
>   //'595 No1
>   //die 16bit in 2x 8bit zerlegen, unteres Byte:
>   uDummy1 = uPattern;
>   uDummy1= uDummy1 & 0x00FF;
>   uDummy1 = (unsigned char) uDummy1;  //ist das eigentlich erlaubt bzw.
> notwendig???
Ich kenne die PICs ja nicht, aber ist SPI bei denen 16 bit? 
Normalerweise schiebt SPI ja immer 8 bit raus.
Du solltest das mal mit uint8_t in 8 bit Portionen zerlegen. VerUNDen 
mitt FF ist nicht nötig; geht auch mit 8 bit shiften.

>   //wait (1);           // PIG zu schnell...?
Ob das Schwein zu schnell ist, wer weiß ...

Joachim ... schrieb:
> Ich schiebe immer 16 bit. Denke ich. Als ob es aber 24 bit wären oder
> so...
> Aber 24bit int gibt's ja nicht, oder? Zumal C18 default in einem 24-bit
> Speichermodell läuft...
Na wenn Du es nicht weißt ...

von Interessiert-A (Gast)


Lesenswert?

Der RCK noch nen Pulldown nach GND und der CLK könnte noch  nen guten 
PullUp nach Vcc vetragen, 10k wäre gut.

von Joachim .. (joachim_01)


Lesenswert?

>Der RCK noch nen Pulldown nach GND und der CLK könnte noch  nen guten
>PullUp nach Vcc vetragen, 10k wäre gut.
Eigentlich nicht, die Leitungen liegen ja direkt am Port. Oder hat etwa 
der PIC kein Totem-Pole Ausgang? Das Dumme: im Datenblatt ist darüber 
nichts explizit erwähnt, lediglich n Bild "Generic IO Operation" hab 
ich.

Danke für eure Hilfe, aber das ist es alles nicht...

Ich bin nochmal mitm Speicher-Oszi ran (kann so was anzuschaffen nur 
jedem empfehlen!)... und siehe da: Der PIC schickt beim zweiten Aufruf 
der Funktion nur 8 anstatt 16 Taktbits weg. Als ob es ein SPI 
Hardware-Feature wäre... werd' wohl noch n bisschen lesen müssen.

von Joachim .. (joachim_01)


Lesenswert?

Problem erschlagen.

Für den Nächsten der drüberstolpert:

Offensichtlich ist im PIC ein Bit (Buffer leer o.ähnl.) das SSPBUF(?) 
nutzt und damit ein sofortiges Wiederbeschreiben ins Leere laufen läßt. 
Dadurch wird auch kein 8-bit Taktzyklus erzeugt was genaugenommen das 
eigentliche Problem war.
Zwei Aufrufe von WriteSPI(Value); müssen durch eine Verzögerung getrennt 
werden.

von Peter D. (peda)


Lesenswert?

Wär es nicht einfacher, statt Trial&Error, das Datenblatt zu lesen?

Und dann einfach das Bit testen, welches anzeigt, daß alle Daten 
herausgeschoben sind. Denn erst danach darfst Du die RCK-Flanke 
erzeugen.


Peter

von Joachim .. (joachim_01)


Lesenswert?

>Wär es nicht einfacher, statt Trial&Error, das Datenblatt zu lesen?
Oha... das sag' ich auch immer ;-)


>Und dann einfach das Bit testen, welches anzeigt, daß alle Daten
>herausgeschoben sind.
Das irritierende war ja, daß es am Anfang ohne diese Bit zu testen 
(wußte nicht das es das gibt) funktioniert hat... Auch im Example (Array 
mit EEPROM r/W) hab ich nichts gefunden.

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.