Hallo!
ich versuche mich gerade an einem Eingangs-Porterweiterung an einem
Mega32 mit 4 kaskadierten Schieberegistern 74HCT165. Die Schieberegister
werden vom Controller über Software-SPI angesteuert. Über den
Timerinterrupt werden die Schieberegister alle 10ms eingelesen.
Leider kriege ich im Controller aber falsche Ergebnisse. Zum Test habe
ich mal alle 32 Eingangspins auf Low gelegt und dann Pin für Pin die
Eingänge auf High gelegt und mir das im Controller ankommende Ergebnis
angeschaut (siehe beliegende Tabelle; ganz links das Eingangspin das
High ist, rechts daneben das vom Controller gelesene Ergebnis (mittels
RS232 an PC übergeben), und ganz rechts nochmal eine Übersichtstabelle
welches Pin als High erkannt wird).
Wie man sieht, werden einige Pins falsch eingelesen: z.B. bei Pin 1
werden Pin 1+16 auf High gesetzt...
weiteres Tests, die ich mit der selben Schaltung, aber nur mit einem
Register gemacht habe, ergaben keine Probleme. Die von mir entwickelte
Assembler-Software schaue ich mir schon zum x-ten Mal an, sehe aber dort
keine Probleme (Simulation im AVR-Studio schaut auch gut aus). Ich
vermute das Problem eher bei der Hardware / Schaltung.
Ich habe die Schieberegister einfach (wie im Datenblatt angegeben)
angeschlossen:
- Clock inhibit auf Low
- Clock auf Clockpin des Controllers (alle 4 Register parallel)
- Shift/Load auf entsprechendes Pin des Controllers (alle 4 Register
parallel)
- Serialinput des 1. Registers auf Low
- Serialinput des 2. Registers geht auf SerialOut-Pin des 1. Reg.
- Serialinput des 3. Registers geht auf SerialOut-Pin des 2. Reg.
- Serialinput des 4. Registers geht auf SerialOut-Pin des 3. Reg.
- Serialoutput des 4. Registers geht auf Input des Controllers
- GND+VCC angeschlossen, Abblockkondensatoren 100nF
Hat jemand von euch vielleicht eine Idee woran die komische Verschiebung
der eingelesenen Pins liegen könnte?
Vielen Dank für eure Mühe!
so, jetzt hab' ich ihn fertig.
schaut nicht sehr professionell aus, ist nur schnell zusammengezaubert.
Aber ich denke man sollte alles erkennen.
die Pins 3-6 + 11-14 sind die Eingänge die (für den Test) auf Low
liegen, nur jeweils ein wurde auf High gelegt...
Die skizzierte Schaltung ist eigentlich nur ein Teil der Hardware. Ich
versuche einen IO-Knoten zu entwickeln, der u.a. folgende Schnittstellen
haben wird:
- 32 digitale Eingänge
- 32-64 digitale Ausgänge
- TWI-Schnittstelle für Temperatursensoren
- 8 Analoge Eingänge
- Can-Bus-Anbindung
- RS232-Interface
- ...
das alles in der maximalen Ausbaustufe, wenn ich das überhaupt auf dem
Mega32 unterbringe (Software, Pins, Timing,...).
Ich baue Schaltung für Schaltung auf einem Steckbrett auf, entwickle die
Software dazu und teste das ganze. Das mit den digitalen Ausgängen
(74HCT595) klappt schon, bei den Eingängen hänge ich jetzt...
Zum Anfangen. Die 74HC595 sind die bessere Wahl. Dann das erste SER darf
nicht an GND sein, sond wird nichts, da muss ein Portpin her. Dann CLK
parallel, SH/LD parallel, INH parallel. Dann an SER die Darten anlegen,
32 mal clocken und Load.
Rene
Oh. Ein lesen, sorry. Dann das 74HC597. Den letzten Ausgang an den
PortPin. Sonst identisch. Man kann die Ausgaenge und die Eingaenge auch
in Serie haben.
rene
@rene:
danke für den Tipp! Ich habe mir eben mal das Datenblatt für den 597
angesehen. Mal abgesehen dass die Ansteuerung etwas anders ist, macht
der im Prinzip ja das selbe wie der 165. Denkst du das das mit dem 597
funktionieren würde?
Kann's leider nicht testen, habe keine da...
@Kai:
ich denke, ich verstehe nicht was du meinst. die Analogen Eingänge
können auch als digitale Eingänge verwendet werden. In Kombination mit
einem 74x597 sind allerdings nur digitale Signale zu verwenden. Um
mehrere analoge Signale zu erfassen würde ich einen Analog Multiplexer
verwenden. Ich habe mit denen allerdings auch noch nix gemacht...
rene wrote:
> Oh. Ein lesen, sorry. Dann das 74HC597.
Nö, bleib mal beim 74HC165, der ist genau richtig.
Der 74HC597 braucht noch nen zusätzlichen Takt für das Eingangslatch.
@Alex,
bei der Schaltung kann man eigentlich nichts falschmachen.
Der Fehler wird wohl in Deiner Software liegen.
Peter
also digitale Eingänge habe ich genug, nur leider analoge vom ADC nicht.
Deswegen suche ich da eine Möglichkeit.
Kann da jemand was empfehlen? Vielen Dank
dafür gibts die Analog-Multiplexer (4051/52/53).
Wieviele Eingänge brauchst du denn? 4051 macht 8 Eingänge auf einen
Ausgang.
Nimmst du davon 2 Stück, brauchst du 3 Steuereingänge vom MC zum
Multiplexer und 2 Analogeingänge am MC -> 16 Analogeingänge an 5
Portpins.
@Peter:
ich fürchte du hast recht. Ich dachte nur an irgendwelche
Ansteuerprobleme, die erst beim Kaskadieren auftreten, Störungen durch
das Steckbrett,...
Da aber die Fehler immer reproduzierbar sind, wird's wohl doch irgendwo
an der Software liegen.
ich poste mal meinen kompletten Code, vielleicht sieht jemand von euch
wo das Problem liegen könnte.
Schnell zum Aufbau:
- Erster Teil Initialisierung (Timer, Ports, RS232)
- Hauptschleife
- beim Timerinterrupt
- Schieberegister einlesen
- Bytes im Ram speichern
- anschliessend mit einer anderen Kopie im Ram vergleichen
- wenn Änderung entdeckt, Flag setzen
- neu gelesene Bytes im Ram ablegen
- wenn Flag gesetzt, wird aus Mainloop eine Sendeprozedur aufgerufen,
die die Bytes per RS232 an PC sendet
Danke für eure Hilfe!
Alex
Hmm, das Datenblatt sagt
"Either the CP or the CE should be HIGH before the LOW-to-HIGH
transition of PL to prevent shifting the data when PL is activated."
Du setzt aber CP auf LOW, bevor du den PL Pulse generierst.
MfG
Falk
Ausserdem generierst du nur 7 Schiebetakte pro Byte. Das reicht wenn nur
1 Schieberegister dranhängt, schlägt aber fehlt bei 4.
Weiterhin ist dein Programmierstil noch verbesserungsfähig. Z.B.
in temp, SER_PIN
andi temp, (1<<SER_DS) ;Maskiere den In-Pin
cpi temp, (1<<SER_DS) ;ist der Eingangspin auf High?
brne BitNotSet_SR ;nein, wie vermutet :-)
Die dritte Zeiel mit cpi kann entfallen, das andi setzt schon das Z-Flag
Ebenso ist deine Schleifenendeabfrage zu kompliziert, macht das Prgramm
nur länger und unleserlich
dec ByteZaehler
cpi ByteZaehler, 0 ;Alle Bytes ausgegeben (mit '0' vergleichen)
breq ExitLoop_SR ;ja, wir können die Funktion verlassen
;es sind noch nicht alle Bytes eingelesen
rjmp OuterLoop_ST
Sollte man sinnvollerweise so schreiben
dec ByteZaehler
brne OuterLoop_ST ;es sind noch nicht alle Bytes eingelesen
;ja, wir können die Funktion verlassen
MfG
Falk
Aller guten Dinge sind drei. Auch bei Kritik. ;-)
Du solltest den Timer am Anfang des Interrupts neu laden.
out tcnt0,TSW ;Timer0-Startwert setzen
Sollte gleich nach dem pushen der Register kommen. Denn wenn dein
Interrupt (Bits schieben, vergleichen etc.) länger als 1024 Takte
(Vorteiler) dauert, dann ist der Abstand der Timerinterrupts >10ms. Wenn
der Timer auch noch für ne Uhr oder ähnliches benutzt wird, kommt es
dann zu Abweichungen.
MfG
Falk
@Falk:
danke für deine guten Tipps! habe eben das Programm etwas umgestellt und
jetzt gehts! Das Problem lag eindeutig an den 7 Schiebetakten, nachdem
ich die Schleife etwas umgestellt hatte ging's!
Das mit dem ersten Tipp ("Either the CP or the CE should be HIGH before
the LOW-to-HIGH transition of PL to prevent shifting the data when PL is
activated") habe ich auch umgesetzt.
Du hast mit deiner Kritik betreffend meinem Programmierstil absolut
Recht: ist noch etwas holperig, ich habe erst vor einigen Wochen mit dem
Assembler-Programmieren begonnen. Da gibts noch Verbesserungspotential
Danke nochmal für die Hilfe!