Zwei Schieberegister in Reihe: Denkfehler?

OP #2276604
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
}
Angehängte Dateien:
OP #2276629
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.
Gast #2276643
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 ...
OP #2276854
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.
OP #2276929
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.
OP #2276951
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren