HT16K33 und 7-Segment-Anzeigen

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • HT16K33 und 7-Segment-Anzeigen

      Hallo Leute,

      nach langer "Bastelpause" wollte ich mal einen I2C/LED Driver zum Ansteuern von einer 7-Segment Anzeige testen.

      Folgende Anzeige ist verbaut:
      HDSP-5501

      Laut Datenblatt ist dies ein Segment mit gemeinsamer Anode (+-Anschluss)

      Hier im Forum habe ich auch schon bereits einen Beitrag zum HT16K33 gefunden jedoch werde ich nicht so 100%ig schlau aus dem Programm und auch aus dem Datasheet.

      Hardwareaufbau ist wie folgt:
      Grundlage ist der Arduino Mega2560
      I2C mit 10k Pullups
      HT16K33 Breakoutboard von Adafruit
      und die oben genannte Segmentanzeige.

      Hier mein abgeänderter Code zum Ausgeben von Zeichen. Leider schaffe ich es nicht, das nur ein Segment leuchtet. Hoffe ihr könnt mir da weiterhelfen.

      BASCOM-Quellcode

      1. '###############################################################################
      2. 'Hardwareconfig #
      3. '###############################################################################
      4. '$sim
      5. $regfile = "m2560def.dat"
      6. $crystal = 16000000 '16MHz
      7. $hwstack = 100
      8. $swstack = 100
      9. $framesize = 400
      10. $baud = 19200
      11. 'Anschluss der 7-Segment Anzeige:
      12. 'Gemeinsame Anode (+)
      13. '7-Segment HT16K33
      14. 'Anode Row0/A2
      15. 'Kathode A COM0
      16. 'Kathode B COM1
      17. 'Kathode C COM2
      18. 'Kathode D COM3
      19. 'Kathode E COM4
      20. 'Kathode F COM5
      21. 'Kathode G COM6
      22. 'Kathode DP COM7
      23. 'I2C Config
      24. Config Sda = Portd.1
      25. Config Scl = Portd.0
      26. '$lib "i2c_twi.lbx"
      27. I2cinit
      28. Const 16k33 = &HE0 'Schreibadresse , alle Adresseingänge offen
      29. Const 16k33r = &HE1 'Leseadresse , alle Adresseingänge offen
      30. Const Display_on = &H81
      31. Const Digit = 16 'Anzahl 7 Segment Digits
      32. Const Digit1 = Digit + 1 ' Länge des Segment Strings + 1.Byte für dessen Startadresse
      33. Dim Temp As Byte
      34. Dim I As Byte
      35. Dim Segmente(digit) As Byte 'Segmente-Speicher
      36. 'Als erstes HT16K33 initialisieren
      37. Print "Init"
      38. Gosub Led_init 'Zu Beginn erst mal ein INIT ausführen!
      39. Wait 1
      40. Print "Init OK"
      41. Wait 1
      42. Print "Clear Display"
      43. Gosub Clear_disp
      44. Wait 1
      45. Print "Clear OK"
      46. Wait 1
      47. Do
      48. Temp = &H00
      49. Print "Loop " ; I
      50. I2csend 16k33 , Temp , I
      51. Wait 1
      52. Incr I
      53. Loop
      54. End
      55. ' #############################################################################
      56. Led_init:
      57. 'Register "System setup"
      58. Temp = &H21 'Oszillator einschalten
      59. I2csend 16k33 , Temp , 1
      60. Waitms 1
      61. 'Wird nicht benötigt, da gemeinsame Anode verbaut ist?!?
      62. 'Temp = &HA0 'Row15/int pin als LED ausgang definieren
      63. 'I2csend 16k33 , Temp , 1
      64. 'Waitms 1
      65. 'Temp = &HA1 'Row15/int pin als Interrupt ausgang definieren - LOW aktiv . Int wird nach jedem auslesen zurückgesetzt
      66. 'I2csend 16k33 , Temp , 1 'und wenn taster gedrückt bleibt gleich wieder ausgelöst, Tasten im HT16K33 intern entprellt, wiederholrate Int ca 50 Hz
      67. 'Waitms 1
      68. 'Register "Dimming set"
      69. Temp = &HEF 'Dimmimg auf 100% 16/16
      70. I2csend 16k33 , Temp , 1
      71. Waitms 1
      72. 'Register "Display setup"
      73. Temp = Display_on 'Display on - no Blink
      74. I2csend 16k33 , Temp , 1
      75. Waitms 1
      76. Return
      77. ' #############################################################################
      78. clear_disp:
      79. For I = 1 To Digit+1 'alle Segmente auf 0 setzen, Segment 1 ist die Displayspeicher startadresse
      80. Segmente(I) = &H00
      81. Next I
      82. I2csend 16k33 , Segmente(1) ,(digit1)
      83. Return
      Alles anzeigen
      Hardwareanbindung der Anzeige an den Controller steht oben im Code. Ich bin mir auch nicht sicher, ob dieser Anschluss so passt bei gemeinsamer Anode. Vielleicht kann da auch nochmal jemand drüber schauen.


      Danke und Gruß

      Stefan
    • Hi tschoeatsch,

      das clear_disp hab ich nun erst mal raus genommen. War von der Vorlage hier im Forum noch drin. Ich bin mir allerdings nicht so sicher ob der Hardwareanschluss vom Segment so richtig ist. Das geht leider nicht so ganz aus dem Datenblatt raus.

      Im Prinzip sollte es doch so funktionieren oder?

      1. HT16K33 initialisieren
      a: Oszillator aktivieren
      'Register "System setup"
      Temp = &H21 'Oszillator einschalten
      I2csend 16k33 , Temp , 1
      Waitms 1
      b: Blinken aus und Display an
      'Register "Display setup"
      Temp = &H81 'Display on - no Blink
      I2csend 16k33 , Temp , 1
      Waitms 1
      c: Helligkeit auf Max
      'Register "Dimming set"
      Temp = &HEF 'Dimmimg auf 100% 16/16
      I2csend 16k33 , Temp , 1
      Waitms 1

      2. Werte an HT16K33 übertragen.

      Hier bin ich mir nicht sicher. So wie ich es dem Datenblatt entnommen habe muss der Aufbau wie folgt sein:

      i2cstart, i2cslave write adresse, displayregister (&H00), 8 datenbytes (für die segmente), i2cstop

      Hier mein aktueller Code:

      BASCOM-Quellcode

      1. '###############################################################################
      2. 'Hardwareconfig #
      3. '###############################################################################
      4. '$sim
      5. $regfile = "m2560def.dat"
      6. $crystal = 16000000 '16MHz
      7. $hwstack = 100
      8. $swstack = 100
      9. $framesize = 400
      10. $baud = 19200
      11. 'Anschluss der 7-Segment Anzeige:
      12. 'Gemeinsame Anode (+)
      13. '7-Segment HT16K33
      14. 'Anode Row0/A2
      15. 'Kathode A COM0
      16. 'Kathode B COM1
      17. 'Kathode C COM2
      18. 'Kathode D COM3
      19. 'Kathode E COM4
      20. 'Kathode F COM5
      21. 'Kathode G COM6
      22. 'Kathode DP COM7
      23. 'I2C Config
      24. Config Sda = Portd.1
      25. Config Scl = Portd.0
      26. '$lib "i2c_twi.lbx"
      27. I2cinit
      28. Const 16k33 = &HE0 'Schreibadresse , alle Adresseingänge offen
      29. Const 16k33r = &HE1 'Leseadresse , alle Adresseingänge offen
      30. ' Länge des Segment Strings + 1.Byte für dessen Startadresse
      31. Dim Temp As Byte
      32. Dim I As Byte
      33. Dim T_byte(8) As Byte 'Segmente-Speicher
      34. 'Als erstes HT16K33 initialisieren
      35. Wait 1
      36. Print "Init" 'Register "Dimming set"
      37. Gosub Led_init 'Zu Beginn erst mal ein INIT ausführen!
      38. Wait 1
      39. Print "Init OK"
      40. Wait 1
      41. Do
      42. Print "Loop "
      43. I2csend 16k33 , T_byte(1) , 8
      44. Wait 1
      45. Loop
      46. End
      47. ' #############################################################################
      48. Led_init:
      49. 'Register "System setup"
      50. Temp = &H21 'Oszillator einschalten
      51. I2csend 16k33 , Temp , 1
      52. Waitms 1
      53. 'Register "Display setup"
      54. Temp = &H81 'Display on - no Blink
      55. I2csend 16k33 , Temp , 1
      56. Waitms 1
      57. 'Register "Dimming set"
      58. Temp = &HEF 'Dimmimg auf 100% 16/16
      59. I2csend 16k33 , Temp , 1
      60. Waitms 1
      61. Return
      62. ' #############################################################################
      Alles anzeigen
      Wie genau jetzt nun der Inhalt von "T_byte" aussehen muss, steht für mich aktuell noch in den Sternen ;) Hoffe hier kann dann jemand weiter helfen.

      Danke und Gruß

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von mC_fAkEr ()

    • Im Normalbetrieb adressierst du mit dem ersten byte (command) ein display , das dann mit dem 2. Byte angesteuert wird. Werden mehrere Daten-bytes gesendet, wird der display-Zähler automatisch incrementiert. Wenn du mit T_byte(1)=0 startest, dann werden die folgenden bytes als Muster für die Segmente nacheinander an die angeschlossenen displays verteilt. Im ersten Eintrag T_byte(1) steht immer 0 drin (Startadresse für das 1. Display) in den folgenden Einträgen die gewünschte Zahl, die angezeigt werden soll. T_byte(2) enthält also den anzuzeigenden Wert auf dem display Nummer 1.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von tschoeatsch ()

    • Also aktuell ist nur ein Display angeschlossen.

      Das bedeutet dann:
      T_byte(1) = &H00 (Bleibt auch immer 0)
      T_byte(2) = &H00 - &HFF (je nachdem was auf dem Display angezeigt werden soll)

      Also könnte ich ja so machen:
      I2csend 16k33 , T_byte(1) ,2

      und das zweite Byte dann inkrementieren, dann müsste das Display sich auch ändern?!?

      Werde mal testen
    • So folgendes getestet:
      Do
      T_byte(1) = &H00


      Print "Loop " ; T_byte(2)
      I2csend 16k33 , T_byte(1) , 2
      Waitms 500
      Incr T_byte(2)



      Loop

      Beim einschalten sind dann folgende Segmente an:a,b,d,e,
      und bei jedem Loop toggelt Segment a. Ich denke es gibt da noch Probleme beim Hardwareanschluss?


      EDIT:
      Kann es sein, das man nur 7-Segment Anzeigen mit gemeinsamer Kathode (-) nehmen kann?
    • Ich denke, das passt schon alles. Im Datenblatt sehe ich nix, dass die gesendeten Daten auf 7 Segmente umkodiert werden, wie es der max 7219 kann. Wenn du also einen '1' darstellen willst, dann musst du Segment A und B leuchten lassen. A ist an com0 also bit0=1, B ist an com1 also bit1=1. Wenn du mit deinem Programm das betrachtest, sind eben 255 Kombinationen der einzelnen Segmente möglich, deswegen toggelt auch Segment A doppelt so schnell wie Segment B...
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Wenn ich das Datenblatt ansehe, sind es gemeinsame Anoden
      HT16K33.PNG
      Und wenn ich im Datenblatt die Schaltungsvarianten ansehe, sind immer alle 8 com-Anschlüsse verwendet, die Anzahl der row-Anschlüsse richtet sich nach der Anzahl der displays.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Das man anders codieren muss. Um Segment A im display 1 leuchten zu lassen, muss man im controllbyte T_byte(1) das Segment auswählen und im Datenbyte T_byte(2) die displaynummer. Lass doch mal T_Byte(1) von 0 bis 15 durchlaufen und T_Byte(2)=0 sein.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Ich hab' das Db noch nicht durchschaut.

      Da steht
      ● There is a one-to-one correspondence between the RAM addresses and the Row outputs, andbetween the individual bits of a RAM word and the column outputs. The following shows themapping from the RAM to the LED pattern:

      Die bit-Nummern entsprechen den com-Nummern, so lese ich das. Also müsste es doch passen, dass T_byte(1) die Adresse für die Daten der com-Leitungen sind und die Adresse an den row-Leitungen anliegt.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von tschoeatsch ()

    • Also soeben hab ich es testen können. Also das erste Byte sind die Com-Nr. (also die Segmentauswahl des Displays a-g) und das zweite Byte sind die Row-Nr. (Bei &H00 ist das davor gewählte Segment aus und bei &H01 ist es ein)
      Aber wie kann ich jetzt vernünftig eine Zahl darstellen, ohne das man alle Segmente einzeln übertragen muss? (Also nicht "Auswahl Segment a und ein, Auswahl Segment b und ein usw...)

      Gruß

      EDIT:
      Also aktuell kann ich es so Ansteuern:

      'Segment a
      T_byte(1) = &H00
      T_byte(2) = &H01
      'Segment b
      T_byte(3) = &H00
      T_byte(4) = &H00
      'Segment c
      T_byte(5) = &H00
      T_byte(6) = &H00
      'Segment d
      T_byte(7) = &H00
      T_byte(8) = &H01
      'Segment e
      T_byte(9) = &H00
      T_byte(10) = &H01
      'Segment f
      T_byte(11) = &H00
      T_byte(12) = &H00
      'Segment g
      T_byte(13) = &H00
      T_byte(14) = &H00
      'Segment DP
      T_byte(15) = &H00
      T_byte(16) = &H01

      I2csend 16k33 , T_byte(1) , 16

      Print "loop"
      Wait 1

      Wobei jeweils das zweite Byte zum Ein/Ausschalten ist. Hier in diesem Beispiel sind Segmente a,d,e und DP an. Der Rest ist aus

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von mC_fAkEr ()

    • Hm, ich glaub' jetzt, es geht net gscheit mit gemeinsamer Anode. Mit dem T_Byte(1) wählt man ein byte von den 16 bytes aus dem ram aus und die folgenden Daten setzen die bits. Soweit, so gut. Jetzt entspricht aber doch leider die rows den bits, Row0 ist bit0, Row7 ist bit7 der geradzahlig nummerierten bytes des rams, Row8 ist bit0 und row15 ist bit7 der ungeradzahlig nummerierten bytes. Wenn man jetzt gemeinsame Anode hat, heißt das, man muss in verschiedenen bytes das eine bit setzen. Dann kann man ein display ansteuern. Beim 2. display muss man wieder jetzt bit1 von verschiedenen bytes setzen, das blöde ist aber, dass man das byte komplett schreiben muss. Also muss man wissen, welches bit schon gesetzt war, um das nicht aus Versehen wieder zu löschen.
      Eine Lösung wäre ein Bildspeicher im Programm, der komplett übertragen wird. Damit werden Zeilen und Spalten getauscht. Dann sollte es gehen.
      Bildspeicher(16) as byte
      Bildspeicher(0, 2, 4...E).0 setzt Row0
      Bildspeicher(0, 2, 4...E).1 setzt Row1
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Probier mal das

      BASCOM-Quellcode

      1. '###############################################################################
      2. 'Hardwareconfig #
      3. '###############################################################################
      4. '$sim
      5. $regfile = "m2560def.dat"
      6. $crystal = 16000000 '16MHz
      7. $hwstack = 100
      8. $swstack = 100
      9. $framesize = 400
      10. $baud = 19200
      11. 'Anschluss der 7-Segment Anzeige:
      12. 'Gemeinsame Anode (+)
      13. '7-Segment HT16K33
      14. 'Anode Row0/A2
      15. 'Kathode A COM0
      16. 'Kathode B COM1
      17. 'Kathode C COM2
      18. 'Kathode D COM3
      19. 'Kathode E COM4
      20. 'Kathode F COM5
      21. 'Kathode G COM6
      22. 'Kathode DP COM7
      23. 'I2C Config
      24. Config Sda = Portd.1
      25. Config Scl = Portd.0
      26. '$lib "i2c_twi.lbx"
      27. I2cinit
      28. Const 16k33 = &HE0 'Schreibadresse , alle Adresseingänge offen
      29. Const 16k33r = &HE1 'Leseadresse , alle Adresseingänge offen
      30. ' Länge des Segment Strings + 1.Byte für dessen Startadresse
      31. Dim Temp As Byte
      32. Dim I As Byte
      33. Dim T_byte(8) As Byte 'Segmente-Speicher
      34. Dim Bildspeicher(17) As Byte
      35. Dim Speicher_nummer As Byte
      36. Dim N As Byte
      37. 'Als erstes HT16K33 initialisieren
      38. Wait 1
      39. Print "Init" 'Register "Dimming set"
      40. Gosub Led_init 'Zu Beginn erst mal ein INIT ausführen!
      41. Wait 1
      42. Print "Init OK"
      43. Wait 1
      44. For N = 0 To 16 : Bildspeicher(n) = 0 : Next N 'Bildspeicher löschen
      45. Do
      46. For N = 0 To 7
      47. Speicher_nummer = 2 * N 'Bereich 0..14 geradzahlig
      48. Incr Speicher_nummer 'erste Speichernummer soll immer =0 sein
      49. Set Bildspeicher(speicher_nummer).0 'setze Row0
      50. I2csend 16k33 , Bildspeicher(1) , 17 'Bildspeicher senden
      51. Reset Bildspeicher(speicher_nummer).0 'setze Row0 zurück
      52. Wait 1
      53. Next N
      54. Loop
      55. End
      56. ' #############################################################################
      57. Led_init:
      58. 'Register "System setup"
      59. Temp = &H21 'Oszillator einschalten
      60. I2csend 16k33 , Temp , 1
      61. Waitms 1
      62. 'Register "Display setup"
      63. Temp = &H81 'Display on - no Blink
      64. I2csend 16k33 , Temp , 1
      65. Waitms 1
      66. 'Register "Dimming set"
      67. Temp = &HEF 'Dimmimg auf 100% 16/16
      68. I2csend 16k33 , Temp , 1
      69. Waitms 1
      70. Return
      71. ' #############################################################################
      Alles anzeigen
      Da sollten jetzt die einzelnen Segmente nacheinander durch schalten.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Meinen Fehler kannst du beheben? Beim Bildspeicher löschen geht der Index natürlich bei 1 los. Wird jetzt nicht auffällig sein, es wird so halt T_byte(8) auf 0 gesetzt und dafür Bildspeicher(17) nicht angesprochen.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • So ungefähr wirds was,der nachteil an den Gem Anoden ist das man immer den gesammten Speicher (oder in dem fall hier evtl nur die hälfte) beschreiben muss um auch nur ein Bit zu ändern. Daher nur die schon vorgeschlage Variante mit Speicher.
      Hatte das spielmal mit nem max 7219 veranstaltet, war nicht einfach, lief dann aber irgendwann. Das keline 8x8 display war echt gut um zu sehen welche bits sich wirklich geändert hatten, einfacher als das jedesmal aus den 7 segmentern zu knobeln.
      7 segment Common Anode Displays an MAX7219

      Tobias
    • So hab mich jetzt mal durch eBay geklickt... Jedoch ist es fast unmöglich, eine 7-Segment Anzeige Größe 0,56'' mit 3 Digits (3Bit) und mit gemeinsamer Kathode zu finden. D.h. ich werde doch versuchen eine Lösung über den Bildspeicher zu erarbeiten, oder drei einzelne Display bestellen und den erhöhten Verdrahtungsaufwand in Kauf nehmen. Was meint ihr?

      Gruß Stefan