74HC595 und PCF8574 für LED`s, 7-Segmente und Co (BASCOM)

Cassio

Aktives Mitglied
29. Okt. 2008
4.027
17
38
Region Hannover
Sprachen
  1. BascomAVR
Hallo zusammen!

Ich hatte hier seit einiger Zeit die bekannten Schieberegister 74HC595 und
die BCD-zu-7-Segment Decoder Chips CD4543 rumliegen.

Um diese nun endlich einmal zu kombinieren...... und auch zu programmieren..... hatte ich mir folgendes ausgedacht:
Als "Herzstück" sollte maximal ein ATMega8 zum Einsatz kommen.
Um auch permanent ändernde Werte ausgeben zu können, wird eine DCF77 Uhr verwendet.
Die Schieberegister (74HC595) sollen mit LED`s eine Binäruhr darstellen, oder verschiedene Lauflichter anzeigen. So kann man das Verhalten der IC`s und auch die verschiedenen Möglichkeiten in der Programmierung testen.

Die Decoder-IC`s treiben (bestimmungsgemäß) eine 7-Segment-Anzeige an und geben die übermittelten Werte als Zahl aus.
Allerdings werden die CD4543 nicht direkt mit dem AVR verbunden, sondern erhalten ihre Daten- und Latchbefehle von einem weiteren 74HC595.

Auf dieser Grundlage habe ich mir erst mal einen Schaltplan gezeichnet. ;)
Um den Testaufbau zu einfach wie möglich zu halten, wurde z.B. ein einzelner FET (BF256) zur Strombegrenzung der LED`s verwendet.
Um bei einer späteren richtigen Anwendung alle LED`s gleichmäßig hell leuchten zu lassen, kommt man um Einzelwiderstände nicht herum.
Für diesen Testaufbau ist es mir aber egal, dass die Helligkeit der LED`s stetig abnimmt, je mehr LED`s in Betrieb sind.

Hier nun der erste Schaltplan für die Binäruhr mit drei Stück 74HC595:
Plan_74595-Mega.gif

In der Realität sind das dann so aus:
74595_1.jpg


Nun kommen noch die BCD-zu-7-Segment Decoder zum Einsatz.
Damit ich später die DCF-Zeit auch wirklich ablesen kann, habe ich mich für vier 7-Seg.-Einheiten entschieden.
Jedes 7-Segment wird von einem CD4543 angesteurt und alle IC`s bekommen ihre "Daten" von einem 74HC595.
Der Schaltplan dazu sieht so aus:
Plan_74595-4543.gif


Und nun auch wieder ein Bild vom echten Aufbau:
4543_1.jpg

Am gemeinsamen Anodenschluss zweier 7-Segmente wird wieder nur ein FET (BF256) verwendet, um den Strom zu begrenzen.
Natürlich müsste man auch hier bei einer richtigen Anwendung wieder einzelne Widerstände einbauen!


Insgesamt sieht der vollständige Testaufbau nun so aus:
74595-4543_2.jpg


Wie auf den Bildern zu erkennen ist funktioniert auch meine Software, die euch natürlich nicht vorenthalten möchte. ;)
Ach so.....
Das Programm ist extra nicht optimiert, damit jeder Interessierte die einzelnen Schritte auch nachvollziehen kann!



CodeBox BascomAVR
'Test für eine Binäruhr mit Schieberegister 74HC595
'und BCD-Decoder CD4543 für 7-Segmente

$regfile = "m8def.dat"
$crystal = 1000000

$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 10                                               ' default use 10 for the SW stack
$framesize = 40                                             ' default use 40 for the frame space

$baud = 4800

Ddrb = &B1100_0011                                          '1 ist Ausgang 0 ist Eingang
Portb = &B0011_1100                                         'auf Hi oder Low setzen
'PB.0 = Ein/Aus 4543-Anzeigen

Ddrc = &B00_0000                                            '1 ist Ausgang 0 ist Eingang
Portc = &B11_1111                                           'auf Hi oder Low setzen

Ddrd = &B1111_1110                                          '1 ist Ausgang 0 ist Eingang
Portd = &B0000_0001                                         'auf Hi oder Low setzen
'PD.0 = RxD
'PD.1 = TxD

'PD.4 = Data
'PD.3 = Latch
'PD.2 = Clock

'PD.7 = Data-4543
'PD.6 = Latch-4543
'PD.5 = Clock-4543

'------------------------------------------------------------------------------
' Timereinstellungen
'------------------------------------------------------------------------------
'Config Timer1 = Timer , Prescale = 64                       'Timer1 für Keyboard
'On Timer1 Eingaben
'Enable Timer1


Daten Alias Portd.4
Latch Alias Portd.3
Takt Alias Portd.2

Daten2 Alias Portd.7
Latch2 Alias Portd.6
Takt2 Alias Portd.5

Set Latch
Set Latch2

'------------------------------------------------------------------------------
' DCF77-Uhr Config (Pollin, invertierter Ausgang)
'------------------------------------------------------------------------------
Config Dcf77 = Pinc.0 , Timer = 1 , Timer1sec = 1 , Debug = 1 , Update = 0 , Check = 1 , Inverted = 1 , Gosub = Sectic
Config Date = Dmy , Separator = .

Enable Interrupts

Time$ = "19:48:00"
Date$ = "01.01.07"



Dim Puls As Bit , Sync As Bit
Dim I As Byte , I2 As Byte , I3 As Byte
Dim Z1 As Byte , Flag1 As Bit , 4543flag As Bit
Dim S1 As String * 1 , Zeit As String * 8
Dim L As Long

'------------------------------------------------------------------------------
' Shiftregister 595
'------------------------------------------------------------------------------
'74HC595-()---<|---R---+5V
'Der 74HC595-Ausgang ist Low, wenn eine 0 gesendet wird!
'Damit alle LEDs (mit +5V versorgt) dunkel sind, müssen alle Bits High sein!
'Daher werden zu Beginn &HFFFFFFFF gesendet!

Print "Start, alle LEDs aus!"

L = &HFFFFFFFF                                              'Alle Bits High setzen
Shiftout Daten , Takt , L , 0 , 32                          '32bit rausschieben
Reset Latch                                                 'Latch auf Low = neue Bits übernehmen
Set Latch

'------------------------------------------------------------------------------
' Anzeigentest
'------------------------------------------------------------------------------
4543flag = 0

Do

Zeit = Time$
Gosub 4543


' -------------------------------------
'DCF-Syncbit zurück setzen
If Dcf_sec > 1 Then Reset Dcf_status.7


'DCF-Sync anzeigen
If Dcf_sec < 2 Then
   If Dcf_status.7 = 1 Then
   Sync = 1
   Else
   Sync = 0
   End If
Else
End If
' -------------------------------------


If Pinc.5 = 0 Then
   Gosub Balken1
Elseif Pinc.4 = 0 Then
   Gosub Balken3
Else
   Gosub Bin_uhr
End If


Loop

'------------------------------------------------------------------------------
Sectic:
Toggle Puls
4543flag = 0
Return



' -------------------------------------
Balken1:
'Bitsweise Steuerung des Byte mit MSB

Shiftout Daten , Takt , L , 0 , 32                          '32 bit rausschieben
   Reset Latch
   Set Latch
Waitms 1

I = &H00                                                    'LEDs der Reihe nach einschalten
For Z1 = 1 To 24
Shiftout Daten , Takt , I , 0 , 1
   Reset Latch
   Set Latch
Waitms 100
Next Z1

I = &HFF                                                    'LEDs der Reihe nach wieder ausschalten
For Z1 = 1 To 24
Shiftout Daten , Takt , I , 0 , 1
   Reset Latch
   Set Latch
Waitms 100
Next Z1

Gosub Balken2

Return


' -------------------------------------
Balken2:
'Bitweise Steuerung des Byte mit LSB

Shiftout Daten , Takt , L , 0 , 32                          '32 bit rausschieben
   Reset Latch
   Set Latch
Waitms 1

I = 252                                                     'Immer 2 LEDs der Reihe nach einschalten
For Z1 = 1 To 12
Shiftout Daten , Takt , I , 2 , 2                           '2 bit rausschieben
   Reset Latch
   Set Latch
Waitms 100
Next Z1

I = 3                                                       'Immer 2 LEDs der Reihe nach wieder ausschalten
For Z1 = 1 To 12
Shiftout Daten , Takt , I , 2 , 2                           '2 bit rausschieben
   Reset Latch
   Set Latch
Waitms 100
Next Z1


Return


' -------------------------------------
Balken3:
'Lauflicht mit einer LED

Shiftout Daten , Takt , L , 0 , 32                          '32 bit rausschieben
   Reset Latch
   Set Latch
Waitms 1

I = 0
Print I
Shiftout Daten , Takt , I , 2 , 1                           '1 bit rausschieben
   Reset Latch
   Set Latch

I = 1
For Z1 = 1 To 24
Shiftout Daten , Takt , I , 2 , 1                           '1 bit rausschieben
   Reset Latch
   Set Latch
Waitms 100
Next Z1

L = &HFFFFFFFF

Return



' -------------------------------------
Bin_uhr:
' Darstellen einer binären Uhr mit LEDs
' Da alle LEDs mit +5V verbunden sind, müssen
' die Ausgänge "invertiert" werden (255 - X)!

If Puls = 1 Then
   If Sync = 1 Then
      I = 127 - _hour
   Else
      I = 255 - _hour
   End If

   Shiftout Daten , Takt , I , 0 , 8

   I = 255 - _min
   Shiftout Daten , Takt , I , 0 , 8

   I = 255 - _sec
   Shiftout Daten , Takt , I , 0 , 8

   Reset Latch
   Set Latch

Else
   I = _hour
   I = Not I
   Shiftout Daten , Takt , I , 0 , 8

   I = _min
   I = Not I
   Shiftout Daten , Takt , I , 0 , 8

   I = _sec
   I = Not I
   Shiftout Daten , Takt , I , 0 , 8

   Reset Latch
   Set Latch

End If

Return


' -------------------------------------
4543:
'Der Befehl "mid()" funktioniert NICHT mit der Variable "Time$".
'Daher wird der String "Time$" in die Stringvariable "Zeit" kopiert!!!

If 4543flag = 0 Then

   If Pinc.3 = 1 Then

      '------MIN-Einer------
      S1 = Mid(zeit , 5 , 1)
      I3 = Val(s1)
      I2 = I3 + 16
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2

      '------MIN-Zehner------
      S1 = Mid(zeit , 4 , 1)
      I3 = Val(s1)
      I2 = I3 + 32
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2




      '------STD-Einer------
      S1 = Mid(zeit , 2 , 1)
      I3 = Val(s1)
      I2 = I3 + 64
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2

      '------STD-Zehner------
      S1 = Mid(zeit , 1 , 1)
      I3 = Val(s1)
      I2 = I3 + 128
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2

      4543flag = 1

   Else

      '------SEC-Einer------
      S1 = Mid(zeit , 8 , 1)
      I3 = Val(s1)
      I2 = I3 + 16
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2

      '------SEC-Zehner------
      S1 = Mid(zeit , 7 , 1)
      I3 = Val(s1)
      I2 = I3 + 32
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2




      '------MIN-Einer------
      S1 = Mid(zeit , 5 , 1)
      I3 = Val(s1)
      I2 = I3 + 64
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2

      '------MIN-Zehner------
      S1 = Mid(zeit , 4 , 1)
      I3 = Val(s1)
      I2 = I3 + 128
      Shiftout Daten2 , Takt2 , I2 , 0 , 8
         Reset Latch2
         Set Latch2
      Shiftout Daten2 , Takt2 , I3 , 0 , 8
         Reset Latch2
         Set Latch2

      4543flag = 1

   End If


Else
End If

Return


End                                                         'end program



So, dass soll es erst einmal gewesen sein. :)
Warum ich gerade die CD4543 IC`s so interessant und praktisch finde, werde ich demnächst mal berichten.

Grüße,
Cassio


Ach so...
Kommentare und Fragen hierzu sind jederzeit Willkommen. ;)
 
Zuletzt bearbeitet:
Hallo zusammen!

Nun mal ein paar Zeilen zum Decoder-IC CD4543.

Erst einmal das Pin-Layout:
cd4543-Pins.gif

Die Pins a, b, c, d, e, f und g sind für die Pins einer 7-Segment-Anzeige ausgelegt. Es müssen also nur die "Buchstaben" mit einander verbunden werden.

Über die Pins A, B, C und D wird dann die Zahl im BCD (bzw. binär) Code zugeführt.

Pin "LD" funktioniert als Latch.
Sobald LD High ist, werden die Daten am Eingang kopiert, dekodiert und ausgegeben.

Hier mal die Tabelle dazu:
cd4543-table.gif


Dank der "eingebauten" Tabelle zur Ansteuerung der 7-Segmente, kann eine Datentabelle (und zugehörige Routinen) im Mega8 entfallen! Es müssen die Zahlen einfach nur binär an die Pins A, B, C und D angelegt werden.


Unheimlich praktisch sind noch zwei weitere Pins.
Durch den Pin "PH" kann man festlegen, ob die angeschlossenen 7-Segmente eine gemeinsame Anode, oder Kathode haben.
Dadurch sind sie universell verwendbar! :)


Duch den Pin "BI" kann die gesammte 7-Segment-Anzeige ein- und ausgeschaltet werden.
Eigentlich ist dieser Pin für LC-Displays gedacht, aber auch bei LED`s kann man ihn gebrauchen.
Wenn man z.B. ein PWM-Signal an BI anlegt ist es möglich, die LED-Anzeige zu dimmen. ;)


So, das war es erst mal zum Decoder IC......

Gruß,
Cassio
 
Hallo!

Weiter geht es nun mit I2C:

In Punkto "Bitschieberei" bin ich durch die BASCOM-Hilfe auch bei I2C (TWI) gelandet.

Unter dem Begriff I/O-Portexpander wurde in der BASCOM-Hilfe der Baustein PCF8574A erwähnt.
Da es für mich Neuland war und ich dies gern einmal ausprobieren wollte, hatte ich mir vor einiger Zeit einfach mal ein paar IC`s besorgt.....

Hier mal der Schaltplan zu meinem Testaufbau:
Plan-I2C-PCF8574A_1.gif

Da die Ein-/Ausgänge des PCF8574A nicht gerade belastbar sind und ich einfach zu faul war alles mit Transistoren aufzubauen, ;) habe ich die Ausgänge mit dem ULN2803 verstärkt.

Da der PCF8574A sowohl Eingang als auch Ausgang sein kann (und dies sogar noch "gleichzeitig"), habe ich die acht Pins zur Hälfte aufgeteilt.
P0 bis P3 sind Eingänge,
P4 bis P7 sind Ausgänge.

Ob der PCF8574A jedoch die Pins als Eingänge, oder als Ausgänge verwenden soll, hängt lediglich von der Programmierung ab.
Dies wird beim Senden der I2C-Adresse einfach mit übermittelt. :)

Ein Blick ins Datenblatt gibt hierüber Aufschluss....
Erst einmal werfen wir einen Blick auf die I2C-Adresse des Bausteins:
PCF8574A-Adresse.jpg
Da die Bits 4, 5 und 6 eine 1 haben, ergibt dies die Grundadresse des IC`s = 70hex bzw. 112dezimal bzw. 111_0000binär.

Mit den Anschlüssen A0, A1 und A2 (siehe Schaltplan) kann man die Adresse "manipulieren". Dies ist dafür gedacht, sollte man mehr als nur einen PCF8574A am I2C-BUS betreiben.
Hat man aber nur einen Baustein davon, legt man die Anschlüsse A0 bis A2 auf GND und erhält die "Grundadresse" 70hex.


Werfen wir nun mal einen zweiten Blick ins Datenblatt, was die Ein- und Ausgänge betrifft.
PCF8574A-RW.jpg

Hier wird drauf hingewiesen, dass Bit 1 der Adresse als "R/W" (Read/Write bzw. Ein/Ausgang) Signal arbeitet.
Hat das Bit 1 eine 0, dann sind die Ports des PCF8574A Ausgänge!

Wird also nun die Adresse &H70 über den I2C-BUS gesendet, wird der PCF8574A nicht nur angesprochen sondern er weiß auch, dass seine Pins Ausgänge sein sollen.

Senden wir aber die Adresse &H71 wird wieder der PCF8574A angesprochen.
Diesmal bekommt er aber das Signal, dass die Pins Eingänge sein sollen.

Das war auch schon alles, was man dabei beachten muss. :)


Ach so.....
Wie im Schaltplan zu sehen ist, habe ich nicht nur den I2C-BUS mit dem ATMega8 verbunden, sondern auch den Pin /INT vom PCF8574A mit INT0 vom AVR.
Dies kommt daher, dass der PCF8574A ein Low-Signal an /INT herausgibt, sobald sich der Zustand eines Pins verändert hat.
Bringt man nun dieses Signal beim AVR zu einem externen Interrupt (z.B. INT0), kann man das Programm veranlassen, sich die neuen Daten ausgeben zu lassen.
Das ist in sofern praktisch, weil der AVR so nicht ständig den PCF8574A abfragen muss, um jede Pin-Änderung auch mitzubekommen.
Wenn man den PCF8574A aber nur als Ausgang verwenden möchte, kann man sich die /INT-Leitung natürlich sparen.


Um dies alles mal zu testen habe ich ein kleines Programm geschrieben, das wieder absichtlich nicht optimiert ist, um es besser verfolgen zu können.


CodeBox BascomAVR
'I2C Test mit ATMega8 als Master

$regfile = "m8def.dat"
$crystal = 1000000

$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 10                                               ' default use 10 for the SW stack
$framesize = 40                                             ' default use 40 for the frame space

$baud = 4800

Ddrb = &B1100_0011                                          '1 ist Ausgang 0 ist Eingang
Portb = &B0011_1100                                         'auf Hi oder Low setzen

Ddrc = &B11_0000                                            '1 ist Ausgang 0 ist Eingang
Portc = &B00_1111                                           'auf Hi oder Low setzen
'PC.5 = SCL
'PC.4 = SDA

Ddrd = &B0000_0010                                          '1 ist Ausgang 0 ist Eingang
Portd = &B1111_1101                                         'auf Hi oder Low setzen
'PD.0 = RxD
'PD.1 = TxD
'PD.2 = INT0

'PD.5 = Taster 1
'PD.6 = Taster 2
'PD.7 = Taster 3

'------------------------------------------------------------------------------
' INT0, Signal vom PCF8574A
'------------------------------------------------------------------------------
Config Int0 = Falling

On Int0 Goi2c

Enable Int0

'------------------------------------------------------------------------------
' I2C Einstellungen
'------------------------------------------------------------------------------
$lib "i2c_twi.lbx"                                          ' we do not use software emulated I2C but the TWI


Config Scl = Portc.5                                        ' we need to provide the SCL pin name
Config Sda = Portc.4                                        ' we need to provide the SDA pin name

I2cinit                                                     ' we need to set the pins in the proper state


Enable Interrupts

'------------------------------------------------------------------------------
' Variablen
'------------------------------------------------------------------------------
Dim Ib As Byte , Ob As Byte


'------------------------------------------------------------------------------
' Erster Start
'------------------------------------------------------------------------------
Ob = 0
Gosub Senden
Waitms 250

'------------------------------------------------------------------------------
' Hauptschleife
'------------------------------------------------------------------------------
Do

If Pind.7 = 0 Then
   Ob = 16
   Gosub Senden
Elseif Pind.6 = 0 Then
      Gosub Empfangen
      Ob = 16 * Ib
      Gosub Senden
Elseif Pind.5 = 0 Then
   Ob = 128
   Gosub Senden
Else
End If


Loop

'------------------------------------------------------------------------------
Senden:
I2cstart
I2cwbyte &H70                                               'PCF8574A Adresse (Output)
I2cwbyte Ob                                                 ' write command
I2cstop

Bitwait Pind.7 , Set
Bitwait Pind.6 , Set
Bitwait Pind.5 , Set

Return

'------------------------------------------------------------------------------
Empfangen:
I2cstart
I2cwbyte &H71                                               'PCF8574A Adresse (Input)
I2crbyte Ib , Nack
I2cstop

Return


'------------------------------------------------------------------------------
Goi2c:

I2cstart
I2cwbyte &H71                                               'PCF8574A Adresse (Input)
I2crbyte Ib , Nack
I2cstop

Ob = 16 * Ib

I2cstart
I2cwbyte &H70                                               'PCF8574A Adresse (Output)
I2cwbyte Ob                                                 ' write command
I2cstop

Return

End                                                         'end program




Und nun noch ein paar Bilder vom "fliegenden" Testaufbau ;)

Hier ist P0 = 1 und dies wird durch die linke LED angezeigt:
a_DSCF0608.jpg


Nun ist P3 = 1 und die entsprechende LED signalisiert das:
a_DSCF0611.jpg


Ich hoffe, es war alles soweit verständlich.
Im Zweifel einfach fragen. ;)


So, nun muss ich mich nur noch entscheiden, welche "Bitschieberei" ich für mein Projekt verwende. :)

Grüße,
Cassio
 
Hallo !

Einen etwas größeren I2C-Baustein, mit 32 Ausgängen, habe ich ebenfalls noch ausprobiert.
Es handelt sich diesmal um den "verwandten" PCF8577C !

Wie eben schon erwähnt, besitzt der IC vier volle Bytes als Ausgänge.
Da es sich eigentlich um einen LCD direkt/duplex Treiber handelt, hat der IC sogar zwei getrennte Bänke für die Daten..... darauf möchte ich aber jetzt nicht eingehen.

Werfen wir erst mal einen Blick auf das Pinout:
PCF8577C-Pinout.jpg

Abgesehen von den 32 Ausgängen und dem fehlenden /INT, ist das Pinout mit dem PCF8574A fast identisch.
Aus dem Grunde gehe ich nun auch nicht mehr auf die einzelnen Anschlüsse ein.

Viel interessanter ist der Aufbau des IC`s.
Werfen wir hierfür mal wieder einen Blick ins Datenblatt und sehen uns die I2C-Adresse nebst benötigtes BUS-Protokoll.
PCF8577C-Adresse.jpg

Die Grundadresse für den PCF8577C ist demnach = 74hex bzw. 01110100 binär..... solange die Pins für A0, A1 und A2 auf GND liegen.

Wenn man sich nun das BUS-Protokoll einmal genau ansieht, müssen jetzt drei Bytes nacheinander gesendet werden.
I2C-Adresse + Conrol Register + Datenbyte

Was es mit dem Control-Register auf sich hat, verrät wieder das Datenblatt:
PCF8577C-Control-Register.jpg

Wie zu erkennen ist, sorgt das Byte des Control-Registers für die Steuerung der nachfolgenden Daten.
Da die Daten immer ein Byte betragen, werden diese in einzelne Sektoren abgelegt.
Im Control-Register-Byte kann man vorher angeben, wo die Daten nun abgelegt werden sollen.
Im einzelnen bedeuten die Bits:
00000010
_______|_Sektorbit 1
______|__Sektorbit 2
_____|___Sektorbit 4
____|____A0
___|_____A1
__|______A2
_|_______Bank A (0) oder Bank B (1) (Sektoren Bank A, ID = 0, 2, 4, 6) (Sektoren Bank B, ID = 1, 3, 5, 7)
|________Direct (0) oder Duplex (1) Mode

Da das PCF8577C zwei Bänke mit je 4 x 8 Bit zur Datenaufnahme besitzt, muss mit Bit 6 die Bank ausgewählt werden.
Passend zur Bank (A oder B) müssen nun noch die Sektoren angegeben werden, um dort die Daten ablegen zu können.
Lt. Datenblatt gehören Sektor 0, 2, 4 und 6 zu Bank A.

Wollen wir also in Sektor 0 die ersten Daten ablegen, muss das Byte des Control-Register so aussehen:
&B00000001 bzw. 01hex
Wollen wir danach ein Byte in Sektor 6 ablegen, muss folgendes gesendet werden:
&B00000110 bzw. 06hex
Da das Prinzip für alle Sektoren und beide Bänke identisch ist, muss ich wohl nun nicht jeden einzelnen Sektor hier erwähnen. ;)


Auf diesen Grundlagen habe ich dann einen kleinen Testaufbau gemacht.
Damit es aber kein Mammuttestaufbau wird und nicht 32 LED`s sowie zugehörige Treiber einsetzen muss, habe ich mich für eine "Sparversion" entschieden.
Hier der Schaltplan:
Plan-I2C-PCF8577C.gif

Wie man sehen kann, hat jeder Sektor nur zwei LED`s bekommen..... immer eine LED für das niedrigste Bit und Eine für das höchste Bit.
Somit sind es nur acht LED`s und ein Treiber-IC, das ULN2803.
Trotzdem kann man nun mit diesem kleinen Aufbau die richtige Programmierung überprüfen. :)


Das Programm gibt es nun natürlich auch noch.....
Wie bereits gewohnt, ist es nicht optimiert und sollte soweit verständlich sein.


CodeBox BascomAVR
'I2C Test mit ATMega8 als Master
'PCF8577C (32 Seg. IC) als Slave

$regfile = "m8def.dat"
$crystal = 1000000

$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 10                                               ' default use 10 for the SW stack
$framesize = 40                                             ' default use 40 for the frame space

$baud = 4800

Ddrb = &B1100_0011                                          '1 ist Ausgang 0 ist Eingang
Portb = &B0011_1100                                         'auf Hi oder Low setzen

Ddrc = &B11_0000                                            '1 ist Ausgang 0 ist Eingang
Portc = &B00_1111                                           'auf Hi oder Low setzen
'PC.5 = SCL
'PC.4 = SDA

Ddrd = &B0000_0010                                          '1 ist Ausgang 0 ist Eingang
Portd = &B1111_1101                                         'auf Hi oder Low setzen
'PD.0 = RxD
'PD.1 = TxD
'PD.2 = INT0

'PD.5 = Taster 1
'PD.6 = Taster 2
'PD.7 = Taster 3

'------------------------------------------------------------------------------
' I2C Einstellungen
'------------------------------------------------------------------------------
$lib "i2c_twi.lbx"                                          ' we do not use software emulated I2C but the TWI


Config Scl = Portc.5                                        ' we need to provide the SCL pin name
Config Sda = Portc.4                                        ' we need to provide the SDA pin name

I2cinit                                                     ' we need to set the pins in the proper state


Enable Interrupts

'------------------------------------------------------------------------------
' Variablen
'------------------------------------------------------------------------------
Dim I As Byte                                               'Indexzähler
Dim Segmente As Byte
Dim Sektor As Byte

'I2C-Adresse des PCF8577C = &B0111_0100 = &H74
Const Pcf = &H74                                            'PCF8577C  I2C-Adresse

'------------------------------------------------------------------------------
' Erster Start
'------------------------------------------------------------------------------
Gosub I2c_cls                                               'Alle LED`s aus


'------------------------------------------------------------------------------
' Hauptschleife
'------------------------------------------------------------------------------
'PD.7 = Taster
'PD.6 = Taster
'PD.5 = Taster

'Control Register:
'00000010
'       |_Sektorbit 1
'      |__Sektorbit 2
'     |___Sektorbit 4
'    |____A0
'   |_____A1
'  |______A2
' |_______Bank A (0) oder Bank B (1)
'         Sektoren Bank A, ID = 0, 2, 4, 6
'         Sektoren Bank B, ID = 1, 3, 5, 7
'|________Direct (0) oder Duplex (1) Mode

'Segmente = &B1000_0001 = &H81 = 129dez

'Datenfluss= I2C-Adresse +  Control-Register  +  Bank-Byte(Segmente)
'Beispiel =    01110100  +      00000110      +      10000001
'Bedeutet =      &H74    +  Bank A, Sektor 6  +  Erste & letzte LED ein

Do

If Pind.7 = 0 Then
Gosub I2c_cls
   For Sektor = 0 To 6 Step 2
      Segmente = &H81
      Gosub Senden
      Wait 1
         Segmente = &H00
         Gosub Senden
         Waitms 250
   Next Sektor

Elseif Pind.6 = 0 Then
Gosub I2c_cls
   For Sektor = 6 To 0 Step -2
      Segmente = &H81
      Gosub Senden
      Waitms 500
         Segmente = &H00
         Gosub Senden
         Waitms 100
   Next Sektor

Elseif Pind.5 = 0 Then
Gosub I2c_cls
   For I = 1 To 3
      Sektor = 0
      Segmente = &B0000_0001
         Gosub Senden
      Sektor = 6
      Segmente = &B1000_0000
         Gosub Senden
   Waitms 250
      Sektor = 0
      Segmente = &B1000_0000
         Gosub Senden
      Sektor = 6
      Segmente = &B0000_0001
         Gosub Senden
   Waitms 250
   Next I

Else
   Sektor = 0
   Segmente = 1
      Gosub Senden
   Sektor = 2
   Segmente = 0
      Gosub Senden
   Sektor = 4
   Segmente = 0
      Gosub Senden
   Sektor = 6
   Segmente = 128
   Gosub Senden
Waitms 250
   Sektor = 0
   Segmente = 0
      Gosub Senden
   Sektor = 2
   Segmente = 128
      Gosub Senden
   Sektor = 4
   Segmente = 1
      Gosub Senden
   Sektor = 6
   Segmente = 0
      Gosub Senden
Waitms 250
End If


Loop

'------------------------------------------------------------------------------
Senden:
I2cstart
I2cwbyte Pcf                                                'PCF8577C Adresse senden
I2cwbyte Sektor                                             'Sektor Control Register
I2cwbyte Segmente                                           'Bytes im Sektor
I2cstop

Return

'------------------------------------------------------------------------------
I2c_cls:
For Sektor = 0 To 6 Step 2
   Segmente = &H00
   Gosub Senden
Next Sektor

Return


End                                                         'end program



Ich hoffe, dass auch diesmal das Prinzip zum Ansteuern des IC`s verständlich rüber gekommen ist.

Grüße,
Cassio
 
Hi Cassio,

recht interessanter Beitrag. Den werd ich mal demnächst mit in das
FAQ-Verzeichnis aufnehmen.

Du legst ja im Moment ziemlich los ;) Willst du mich mit den Beiträgen
übertreffen ? :D Im Moment ist es zeitmäßig bei mir leider etwas eng. :eek:
Aber das wird auch wieder ;)

Gruß
Dino
 
Hallo Dino!

Ich habe inzwischen auch schon drüber nachgedacht, ob ich den ersten Beitrag nicht etwas editiere und alles in den FAQ-Bereich verschiebe.
Schließlich sind aus den ersten Erfahrungen und Ideen nun schon mehr eine Art "Anleitung" geworden.

Außerdem wird es für mich etwas entspannter, wenn ich alles in den FAQ-Bereich verschiebe. So habe ich mehr Zeit zum überlegen und kann das Projekt noch ein wenig schleifen lassen. ;)


Zur Zeit waren dies aber auch erst mal alle Tests, die ich schon längst mal durchführen wollte.
Tja und während der Testphase kam mir die Idee, gleich alles hier mit einzustellen. So haben eben alle etwas davon. :)

Gruß,
Cassio


EDIT:
Schon passiert...... ;)
Habe das Thema nun in den FAQ-Bereich verschoben.
Kannst es ja mal in der FAQ-Übersicht verlinken.....
 
Hallo!

Ich wollte ja noch die Bilder vom Testaufbau des PCF8577C hochgeladen haben.....
Da der andere Thread aber schon die maximale Anzahl an Anhängen erreicht hat, gibt es die nun separat. ;)

Die Bauteile sind auf den Bildern natürlich wieder beschriftet und daher bedarf es wohl keiner weiteren Erklärung.

Wie immer, ist es ein "fliegender" Testaufbau und daher nicht besonders hübsch gemacht. ;)

Hier das erste Bild, wenn das Programm den "ersten" Teil (vor dem Waitms) von "Else" in der Hauptschleife erreicht hat:
a_DSCF0632.jpg

...und das zweite Foto, wenn das Programm dann die nächsten Daten übermittelt hat:
a_DSCF0631.jpg


Damit hätte ich das nun auch vollständig! :)

Gruß,
Cassio
 
Hallo zusammen!

Nach I2C und der Reihenfolge der Bauteile passt mein letztes IC hier zwar gar nicht hin, aber ich möchte es euch doch nicht vorenthalten.

Nach dem Aufräumen der oben durchgeführten Tests, habe ich beim Einsortieren der IC`s noch ein Weiteres gefunden. ;)

Scheinbar hatte ich mir auch mal das 74HC165 besorgt! :rolleyes:
Das gute Stück ist ein Input-Schieberegister für 8 Bit.

Die Funktion ist ähnlich dem 74HC595, nun das die 8 Pins als Eingänge arbeiten und nicht als Ausgänge.
Kann also auch unter dem Thema Porterweiterung "verbucht" werden.

Um das IC zu testen, habe ich einen kleinen Testaufbau mit einem ATMega8, dem 74HC165 und als Anzeige ein 74HC595 realisiert.
So sieht der Schaltplan dafür aus:
Plan-74165+74595.gif

Damit ich also sehen kann welche Eingänge ich am 74HC165 aktiviere, werden die Daten zu einem 74HC595 heraus geschoben, der mir dies per LED anzeigt.

Schauen wir uns aber erst mal das Pinout des 74HC165 an:
74165-pinout.jpg

Dort sind u.a. die acht Eingänge (A - H) zu sehen, ein Shift/Load-(Latch)-Pin, die Clock-Leitung, Serial-Input und QH als Ouput.

Zum Betrieb als Input-Porterweiterung benötigt man also nur die Pins:
Shift/Load (Latch) , Clock und QH (der serielle Ausgang des IC`s)
Wenn man mehrere Eingänge benötigt, kann man das IC auch kaskadieren.
Es wird dann lediglich der Ausgang (QH) des einen IC`s mit dem Eingang (Serial Input) des anderen IC`s verbunden. ;)


Das IC funktioniert nun auf folgende Weise....
Die Latch-Leitung ist permanent High!
Wird die Latch-Leitung einmal kurz auf Low geschaltet, werden die Zustände der Eingänge gespeichert, die genau zu dem Zeitpunkt am IC angelegen haben.

Dies kann man auch im Datenblatt recht gut erkennen:
74165-timing.jpg

Anschließend müssen die Daten (1 Byte je IC) nur noch in den Mega8 eingelesen werden.
Hierfür bietet BASCOM den Befehl "Shiftin" an.
Dadurch ist es sehr einfach möglich, das Byte in einer Variable zu speichern und weiter zu verarbeiten. :)

In meinem Testprogramm werden die Daten dann zur optischen Kontrolle gleich wieder an den 74HC595 rausgeschoben.
Wenn alles richtig ist leuchtet z.B. die LED-8, wenn am 74HC165 der Eingang H aktiv war.

Hier nun das Programm dazu:


CodeBox bascom

'Test für das Input- und Output-Schieberegister
'74HC165 und 74HC595

$regfile = "m8def.dat"
$crystal = 1000000

$hwstack = 32 ' default use 32 for the hardware stack
$swstack = 10 ' default use 10 for the SW stack
$framesize = 40 ' default use 40 for the frame space


Ddrb = &B1100_0011 '1 ist Ausgang 0 ist Eingang
Portb = &B0011_1100 'auf Hi oder Low setzen

Ddrc = &B00_0000 '1 ist Ausgang 0 ist Eingang
Portc = &B11_1111 'auf Hi oder Low setzen
'PC0 = DCF77-Signal

Ddrd = &B1110_1110 '1 ist Ausgang 0 ist Eingang
Portd = &B0001_0001 'auf Hi oder Low setzen
'PD.0 = RxD
'PD.1 = TxD

'PD.7 = Datao (Outputpin !)
'PD.6 = Latch
'PD.5 = Clock
'PD.4 = Datai (Inputpin !)

'------------------------------------------------------------------------------
' Alias
'------------------------------------------------------------------------------
Dateno Alias Portd.7
Latch Alias Portd.6
Takt Alias Portd.5
Dateni Alias Pind.4

'------------------------------------------------------------------------------
' DCF77-Uhr Config (Pollin, invertierter Ausgang)
'------------------------------------------------------------------------------
Config Dcf77 = Pinc.0 , Timer = 1 , Timer1sec = 1 , Debug = 1 , Update = 0 , Check = 1 , Inverted = 1 , Gosub = Sectic
Config Date = Dmy , Separator = .

Enable Interrupts

Time$ = "19:48:00"
Date$ = "01.01.07"


'------------------------------------------------------------------------------
' Deklaration der Variablen
'------------------------------------------------------------------------------
Dim Puls As Bit
Dim I As Byte
Dim Flag1 As Bit


'------------------------------------------------------------------------------
' Shiftregister 595
'------------------------------------------------------------------------------
'Der 74HC595-Ausgang ist Low, wenn eine 0 gesendet wird!
'Damit alle LEDs (mit +5V versorgt) dunkel sind, müssen alle Bits High sein!
'Daher wird zu Beginn &HFF gesendet!
'74HC595----<|---R---+5V

Set Latch 'Latch VORAB auf High

I = &HFF 'Alle Bits High setzen
Shiftout Dateno , Takt , I , 0 , 8 '8 Bit rausschieben
Reset Latch 'Latch auf Low = neue Bits
Set Latch 'Latch auf High
'------------------------------------------------------------------------------
' Anzeigentest
'------------------------------------------------------------------------------

Do

If Flag1 = 1 Then

If Puls = 1 Then
Reset Latch 'Latch auf Low = neue Bits
Set Latch 'Latch Low, Inputpins "geladen"
Shiftin Dateni , Takt , I , 0 , 8 '8 Bit in Variable I einlesen

Waitms 1

Shiftout Dateno , Takt , I , 0 , 8 '8 Bit rausschieben
Reset Latch 'Latch auf Low = neue Bits
Set Latch 'Latch auf High
Flag1 = 0
Else
I = 126 'invertieren der Bits, weil LED an +5V
Shiftout Dateno , Takt , I , 0 , 8 '8 Bit rausschieben
Reset Latch 'Latch auf Low = neue Bits
Set Latch 'Latch auf High
End If
Else
End If

Loop

'------------------------------------------------------------------------------
Sectic:
Toggle Puls 'Sekundenpuls
Flag1 = 1 'Schleifenflag
Return


End 'end program



Da das 74HC165 aber nicht über ein Interrupt-Signal verfügt, wie der I2C-Baustein PCF8574A, muss man sich um die permanente Abfrage des IC`s (und damit der Zustand der Eingänge) selbst kümmern.


Nun noch die Bilder vom Testaufbau....
Hier wurde der Eingang H aktiviert, welches auch durch die LED (Bit 7) bestätigt wird:
74165-Erfassung.jpg

Da die Erfassung der Eingänge nur einmal in der Sekunde vorgenommen wird, zeigen die LED`s 1 und 8 (Bit 0 und Bit 7) dies als "Pausenzeichen" an:
74165-Pause.jpg


Ich hoffe, das die Erklärungen nicht zu kurz gewesen sind und das Prinzip verstanden wurde. :)

Grüße,
Cassio
 
Hallo,

Scheinbar hatte mir auch mal das 74HC165 besorgt! :rolleyes:
Das gute Stück ist ein Input-Schieberegister für 8 Bit.

Die Funktion ist ähnlich dem 74HC595, nun das die 8 Pins als Eingänge arbeiten und nicht als Ausgänge.
Kann also auch unter dem Thema Porterweiterung "verbucht" werden.
als Tip: statt dem 74HC165 würde ich lieber da 74HC597 verwenden.
Aber egal ... es war da. Aber bei Neubeschaffung : 74HC597. das ist wirklich
das genaue Gegenteil zum 74HC595.

74 HC 595 => Seriell rein - Parallel raus
74 HC 597 => Parallel rein - Seriell raus

Gruß
Dino
 
74 HC 595 => Seriell rein - Parallel raus
74 HC 597 => Parallel rein - Seriell raus

Hallo Dino!

Danke, für den Hinweis! :)

Wie du aber schon richtig vermutet hast, die IC`s hatte ich eben noch hier. ;)
Bei einer "Neuanschaffung" werde ich aber auf I2C setzen.....
Wegen dem /INT-Signal als Input und weil sie universell sind.

Naja.... OK, dafür sind sie auch wesentlich teurer. :eek:
Aber irgendwas ist ja immer! ;)

Gruß,
Cassio
 
Naja.... OK, dafür sind sie auch wesentlich teurer. :eek:
Aber irgendwas ist ja immer! ;)
und langsamer ... Wenn man die 74HC595/597 mit SPI befeuert/abfragt dann
kann man ohne Probleme mit 4MHz Bit-Takt arbeiten. Das Tempo bekommst
du mit I2C nie hin :D

Gruß
Dino
 
Das Tempo bekommst du mit I2C nie hin :D

Hi Dino!

Nein, das stimmt natürlich.


Allerdings brauchst du die 4MHz beim 74HC165 bzw. 74HC597 aber auch......
Schließlich musst du das IC auch 1000mal öfter manuell abfragen als beim I2C.
Er kann sich ja nicht melden, wenn es etwas Neues gibt. :p

Gruß,
Cassio
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)