7-Segmentanzeigen und Multiplexing

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Michael wrote:

      kommt drauf an
      Ja klar es kommt auch auf die Anzahl der Anzeigen an.
      Ich habe jetzt mal einen Testaufbau mit zwei Anzeigen und habe bei 100 Hz kein Geisterleuchten aber flimmern.
      Und wenn ich mit der Frequenz höher gehe flimmert es nicht mehr aber ich habe dieses Geisterleuchten

      Hier mal mein Testprogramm.

      BASCOM Source Code

      1. $regfile = "m8def.dat" ' specify the used micro
      2. $crystal = 8000000 ' used crystal frequency
      3. $hwstack = 64 ' default use 32 for the hardware stack
      4. $swstack = 32 ' default use 10 for the SW stack
      5. $framesize = 32 ' default use 40 for the frame space
      6. Config Portd.3 = Output 'Stelle 2
      7. Config Portd.4 = Output 'Stelle 1
      8. Config Portd.5 = Output 'Daten
      9. Config Portd.6 = Output 'SCK
      10. Config Portd.7 = Output 'RCK
      11. Stelle2 Alias Portd.3
      12. Stelle1 Alias Portd.4
      13. Daten Alias Portd.5
      14. Sck Alias Portd.6
      15. Rck Alias Portd.7
      16. Const Timer0_preload = 185
      17. Config Timer0 = Timer , Prescale = 1024 '110 Hz
      18. Timer0 = Timer0_preload
      19. Const Timer1_Preload = 34286
      20. Config Timer1 = Timer , Prescale = 256
      21. Timer1 = Timer1_preload
      22. On Timer0 Isr_timer0
      23. On Timer1 Isr_timer1
      24. Enable Timer0
      25. Enable Timer1
      26. Enable Interrupts
      27. Dim Zahl1 As Byte , Zahl2 As Byte , Daten_out As Byte , I As Byte , Stellex As Bit
      28. Do
      29. If Stellex = 0 Then
      30. Set Stelle1
      31. Reset Stelle2
      32. Daten_out = Lookup(zahl1 , Segmente)
      33. Else
      34. Set Stelle2
      35. Reset Stelle1
      36. Daten_out = Lookup(zahl2 , Segmente)
      37. End If
      38. Gosub Anzeige
      39. Loop
      40. End
      41. Anzeige:
      42. For I = 0 To 7
      43. Daten = Daten_out.i
      44. Sck = 1
      45. Sck = 0
      46. Next I
      47. Rck = 0
      48. Rck = 1
      49. Return
      50. Isr_timer0:
      51. Timer0 = Timer0_preload
      52. Toggle Stellex
      53. Return
      54. Isr_timer1:
      55. Timer1 = Timer1_preload
      56. Incr Zahl1
      57. If Zahl1 = 10 Then
      58. Incr Zahl2
      59. Zahl1 = 0
      60. End If
      61. If Zahl2 = 10 Then Zahl2 = 0
      62. Return
      63. ' A,B,C,D,E,F,G,DP
      64. Segmente:
      65. Data &B11111100 ' 0
      66. Data &B01100000 ' 1
      67. Data &B11011010 ' 2
      68. Data &B11110010 ' 3
      69. Data &B01100110 ' 4
      70. Data &B10110110 ' 5
      71. Data &B10111110 ' 6
      72. Data &B11100000 ' 7
      73. Data &B11111110 ' 8
      74. Data &B11110110 ' 9
      75. Data &B00000000 ' Blank
      76. 'Ende
      Display All
      Die Segmente werden über eine 74HC595 angesteuert.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • djmsc wrote:

      und habe bei 100 Hz kein Geisterleuchten aber flimmern.
      Schwebung mit der Netzfrequenz?
      Meine Handykamera flimmert auch, wenns zu nah an der Lampe ist.
      Vielleicht hakt dein Timer1 auch regelmäßig rein.
      Zahlen inkrementieren kannst du sicher besser im Hauptprogramm oder in nur einem Timer.

      djmsc wrote:

      aber ich habe dieses Geisterleuchten
      wenn die eine Stelle erst eingeschaltet wird, bevor die andere aus ist passiert das.
      Ebenso, wenn zuwenig Zeit ist für's Leuchten.

      Ich würde den Timer nur nutzen, um ein Flag zu setzen.
      Das Hauptprogramm wartet dann auf das Bit (bitwait) und setzt die entsprechende Stelle.
      Die Zeit bis zum nächsten bitwait leuchtet dann die entsprehende Stelle.
    • Michael wrote:

      Vielleicht hakt dein Timer1 auch regelmäßig rein.
      Also Timer1 läuft mit 1s (1 Hz) und darin zähle ich auch nur die Variablen hoch.
      In der Timer0 ISR wird auch nur ein Flag gesetzt und in der Hauptschleife abgefragt

      Michael wrote:

      Ebenso, wenn zuwenig Zeit ist für's Leuchten.
      Also muss ich in dem Ablauf noch etwas ändern.
      Ich werde mal etwas rum probieren :)
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • Ich würde behaupten, dass das Multiplexen gar nicht mit 100 Hz2 statt findet.
      Denn in der ISR zählst du nur mit 100 Hz die Zahl hoch.

      Das was dann an Rechenleistung übrig bleibt von der ISR, wird zur Umschaltung der Stellen und der Ausgabe verwendet.

      Du musst die multiplexte Ausgabe an die 100 Hz koppeln, nicht an das Hochzählen der Werte.

      Die Geisterbilder kommen wahrscheinlich daher, weil während der Ausgabe der Stellen ein Interrupt statt findet, der auch noch die Werte ändert.
    • djmsc wrote:

      In der Timer0 ISR wird auch nur ein Flag gesetzt und in der Hauptschleife abgefragt
      naja, du toggelst ein Flag und wertest es per Polling in der Hauptschleife aus.
      Das geht bei dem kleinen Programm sicher ohne großen Stress.

      djmsc wrote:

      Ablauf noch etwas ändern.
      Ich sehe, dass eine Ziffer erst umgeschaltet wird und dann erst die Daten bekommt.
      Die Daten schickst du mit einer For-Schleife raus, die sehr langsam ist. Hier wäre Shiftout eine schönere Variante
      In dieser Zeit hast du auch das Geisterbild auf der falschen Anzeige.
      Das Umschalten der Anzeigen würde zeitlich besser in der Nähe vom Rck Impuls aufgehoben.
      Versteh mich nicht falsch, For-next ist schon in Ordnung, nur sollten die Daten nicht genau in diesem Moment kommen, in dem du gar keine Zeit dafür hast. Die Aufschaltung der Daten erfolgt ja erst mit Rck.
    • Was sind denn das für Anzeigen, die die Daten seriell brauchen?
      Sind das keine 7-Sehment-Anzeigen?

      Oder steuerst du das 7-Segment Teil über einem Schieberegister an?

      Ich denke das Toggel-Flag ist das Problem.
      Klar musst du die Anzeigen hin und herschalten.
      Aber ein 2. Flag wäre gut, damit die Hauptschleife weis, wann den die Anzeige zu aktualisieren ist.

      Das Toggle-Flag für die Stelle in der ISR setzen und zusätzlich ein Refresh-Flag, damit die Hauptschleife weiß, wann eine Ausgabe erfolgen muss. Dann nach der Ausgabe das Refresh-Flag löschen.
    • Die gesamte Anzeige Routine sollte in die Isr. Den spätestens wenn die Main noch was anderes zu tun bekommt wirds flackern. Die Main kann die Ziffern bereitstellen aber die Umschaltung würde oft humpeln.
      Evt läßt sich ein HW Schieberegister nutzen (SPI,Uart..) dann braucht die Isr nicht so lange.
    • New

      So ich bin jetzt mal wieder dazu gekommen etwas weiter zu testen.

      Ich habe jetzt folgendes Programm mit der Ausgabe über den Timer-Interrupt.

      BASCOM Source Code

      1. $regfile = "m8def.dat" ' specify the used micro
      2. $crystal = 8000000 ' used crystal frequency
      3. $hwstack = 64 ' default use 32 for the hardware stack
      4. $swstack = 32 ' default use 10 for the SW stack
      5. $framesize = 32 ' default use 40 for the frame space
      6. Config Portd.2 = Output 'LED
      7. Config Portd.3 = Output 'Stelle 2
      8. Config Portd.4 = Output 'Stelle 1
      9. Config Portd.5 = Output 'Daten
      10. Config Portd.6 = Output 'SCK
      11. Config Portd.7 = Output 'RCK
      12. Led Alias Portd.2 'Nur zu Testzwecken
      13. Stelle2 Alias Portd.3
      14. Stelle1 Alias Portd.4
      15. Daten Alias Portd.5
      16. Sck Alias Portd.6
      17. Rck Alias Portd.7
      18. Const Timer0_preload = 6
      19. Config Timer0 = Timer , Prescale = 64 '500 Hz
      20. Timer0 = Timer0_preload
      21. Const Timer1_preload = 34286
      22. Config Timer1 = Timer , Prescale = 256
      23. Timer1 = Timer1_preload
      24. On Timer0 Isr_timer0
      25. On Timer1 Isr_timer1
      26. Config Adc = Single , Prescaler = Auto , Reference = Avcc
      27. Enable Timer0
      28. Enable Timer1
      29. Enable Interrupts
      30. Dim Zahl1 As Byte , Zahl2 As Byte , Daten_out As Byte , Stellex As Bit
      31. Dim Ausgabe As Word , Zufall As Word
      32. Dim __rseed As Word
      33. 'Hier ist nur eine kleine Spielerei zu Testzwecken in der Hauptschleife
      34. Do
      35. Incr Ausgabe
      36. If Ausgabe = Zufall Then
      37. Toggle Led
      38. Ausgabe = 0
      39. End If
      40. Loop
      41. End
      42. 'Anzeige
      43. Isr_timer0:
      44. Timer0 = Timer0_preload
      45. Toggle Stellex
      46. If Stellex = 0 Then
      47. Set Stelle2
      48. Daten_out = Lookup(zahl1 , Segmente)
      49. Waitus 500 'für die Helligkeit der Anzeigen
      50. Reset Stelle2
      51. Else
      52. Set Stelle1
      53. Daten_out = Lookup(zahl2 , Segmente)
      54. Waitus 500 'für die Helligkeit der Anzeigen
      55. Reset Stelle1
      56. End If
      57. Shiftout Daten , Sck , Daten_out , 1
      58. Rck = 0
      59. Rck = 1
      60. Return
      61. 'Sekunden-Timer
      62. Isr_timer1:
      63. Timer1 = Timer1_preload
      64. Incr Zahl1
      65. If Zahl1 = 10 Then
      66. __rseed = Getadc(0)
      67. Incr Zahl2
      68. Zahl1 = 0
      69. Zufall = Rnd(65535)
      70. End If
      71. If Zahl2 = 6 Then
      72. Zahl2 = 0
      73. End If
      74. Return
      75. ' DP,G,F,E,D,C,B,A
      76. Segmente:
      77. Data &B00111111 ' 0
      78. Data &B00000110 ' 1
      79. Data &B01011011 ' 2
      80. Data &B01001111 ' 3
      81. Data &B01100110 ' 4
      82. Data &B01101101 ' 5
      83. Data &B01111101 ' 6
      84. Data &B00000111 ' 7
      85. Data &B01111111 ' 8
      86. Data &B01101111 ' 9
      87. Data &B00000000 ' Blank
      88. 'Ende
      Display All
      So funktioniert es erstmal auch ohne flimmern und Geisterbilder und die Anzeigen haben auch eine gute Helligkeit.
      Die Helligkeit erreiche ich allerdings nur wenn ich ein kleines Waitus einbaue. Ohne wären die Anzeigen viel zu dunkel.

      Allerdings werde ich für mein Projekt mit diesen Anzeigen auf das Multiplexen verzichten und die zwei Anzeigen direkt über zwei 74HC595 betreiben.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • New

      Ich würde die ISR anders machen:

      BASCOM Source Code

      1. 'Anzeige
      2. Isr_timer0:
      3. Timer0 = Timer0_preload
      4. Toggle Stellex
      5. If Stellex = 0 Then
      6. Daten_out = Lookup(zahl1 , Segmente) ' Daten holen
      7. Shiftout Daten , Sck , Daten_out , 1 ' Daten rausschieben
      8. Set Stelle2 ' Auf Stelle 2 schalten
      9. Reset Stelle1
      10. Rck = 0 ' Puls für Schieberegister ausgeben
      11. Rck = 1
      12. Else
      13. Daten_out = Lookup(zahl2 , Segmente) ' Daten holen
      14. Shiftout Daten , Sck , Daten_out , 1 ' Daten rausschieben
      15. Reset Stelle2 ' Auf Stelle 1 schalten
      16. Set Stelle1
      17. Rck = 0 ' Puls für Schieberegister ausgeben
      18. Rck = 1
      19. End If
      20. Return
      Display All
      So entfallen die 500µs in der ISR.
      Bei jedem Durchgang wird immer die nächste Stelle ausgegeben und eingeschaltet.
      Die bleibt dann solange an, bis der nächste Interrupt kommt.
    • New

      So wäre es sogar noch etwas geschickter:

      BASCOM Source Code

      1. ' Anzeige
      2. Isr_timer0:
      3. Timer0 = Timer0_preload
      4. Toggle Stellex
      5. If Stellex = 0 Then
      6. Daten_out = Lookup(zahl1 , Segmente) ' Daten holen
      7. Shiftout Daten , Sck , Daten_out , 1 ' Daten rausschieben
      8. Reset Stelle1 ' Auf Stelle 1 aus
      9. Rck = 0 ' Puls für Schieberegister ausgeben
      10. Rck = 1
      11. Set Stelle2 ' Stelle 2 an
      12. Else
      13. Daten_out = Lookup(zahl2 , Segmente) ' Daten holen
      14. Shiftout Daten , Sck , Daten_out , 1 ' Daten rausschieben
      15. Reset Stelle2 ' Stelle 2 aus
      16. Rck = 0 ' Puls für Schieberegister ausgeben
      17. Rck = 1
      18. Set Stelle1 ' Stelle 1 an
      19. End If
      20. Return
      Display All
      Der andere Codeschnipsel sollte aber auch funktionieren.