74hc595 timing probleem

trix

Golden Member

hallo met zijn alle op deze regenachtige midag.

zoals sommige mischien al weten ben ik bezig met het maken van een lichtkrant:

  • uC AVR atmega 8, programma in bascom
  • 8x rijen - 160x kolomen
  • rijen rechtstreeks gestuurd uit AVR via drivers met FET irf9540
  • kolomen shiftregisters (74hc595) via drivers met bc547

nu heb ik op breadboard een opstelling gemaakt voor 8 rijen & 16 kolomen en een programma geschreven voor een vaste text op de lichtkrant (3 letters van 5 kolomen is 15 kolomen).
so far so good, de letters verschijnen op de lichtkrant.

nu mijn probleem: als ik de b.v. rij 5 aanstuur dan zie ik nog heel even de data van rij 4 op deze rij 5 gevolg is dat de ligger van de A dan een dubbele lijn word. ik heb dit gecontroleerd door de rijen zo aan te sturen dat ze ieder 0,5 sec. hoog zijn zodat je precies kan zien wat er gebeurd.

zoals al vermeld maak ik gebruik van een 75hc595, die stuur ik als volgd aan: (versimpelde pseudo code)

code:


for row = 0 to 7
 for text = 0 to 25          'max. 25 car. op lichtkrant
  set & reset latchbit       'aan het einde van gewenste text de ingeschoven bits naar de uitgang sturen
   for coloms = 0 to 4       'letter bestaat uit 5 kolomen
    zet data bit klaar       'bit die het schuifreg. ingaat
    set & reset klokbit    
  next kolom
 next text 
next row

nogmaals sterk versimpeld maar het gaat denk ik over de timing van de data - klok & latchbit. indien gewenst kan ik de voledige code uiteraard wel posten.

de 74hc595 is als volgt aangesloten:

  • pin 11 (SH cp) --- de klokbit
    pin 12 (ST cp) --- latchbit (data naar uitgangen)
    pin 14 (DS) --- data bit (data die schuifreg. ingaat)

ik heb me al suf gezocht maar ik zie het gewoon niet ik heb sterk het vermoeden dat het in de timing van de 74hc595 zit, rijen worden mooi 1 voor 1 aangestuurd en hebben op de scoop mooie stijle flanken dit i.v.m. eventuele overlap.
wat ik ook raar vind is dat hoe langazamer ik de rijen aanstuur hoe erger het probleem word.
ik hoop dat ik voldoende duidelijk ben, anders licht ik het nog graag toe.

alvast mijn dank

eigenwijs = ook wijs

Je vermeldt niet hoe je de rijen (FETs) aanstuurt. De juiste (pseudocode) zou zijn

code:


   forever loop
      do something else, maybe some delay
      clock next data into 595 shift registers
      switch row drivers off
      clock the 595 hold register
      enable row driver
   end loop

Let vooral op: eerst rijen uitzetten, dan de 595 holding register clokken, dan de nieuwe rij aan zetten.

Het effect wat jij ziet krijg je als je de oude rij niet eerst uit zet, maar wel de 595 de volgende data naar de holding regsiters laat transporten, *en dan pas de volgende rij selecteert*, dus nog even met de nieuwe data op de oude rij.

Wouter van Ooijen: VOTI webwinkel, docent HvU (Technische Informatica); C++ on mictrocontrollers blog

Een schema ware handiger geweest, al was het maar om onze schemahonger te bevredigen. :-)

Wat het meest in het oog springt, zijn de drivers. Rijen aansturen met FET's, en kolommen met bipolaire torren, is vragen om spookbeelden. Vervang eens een BC547 door een BS170, en ga na of dat verschil maakt. Zo ja, dan weet je wat te doen.

En daarnaast Wouter's raad opvolgen, uiteraard. Ook als je enkel FET's gebruikt, is een pause noodzakelijk - maar met FET's kan die pause aardig wat korter zijn dan met gewone torren.

Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
trix

Golden Member

het probleem is niet met pauzes te verhelpen heb al van alles geprobeerd. nogmaals de code met het moment van rijen sturen erin vermeld:

code:


for row = 0 to 7
 set & reset portd.X          'de juiste rij aan/uit zetten
  for text = 0 to 25          'max. 25 car. op lichtkrant
   set & reset latchbit       'aan het einde van gewenste text de ingeschoven bits naar de uitgang sturen
    for coloms = 0 to 4       'letter bestaat uit 5 kolomen
     zet data bit klaar       'bit die het schuifreg. ingaat
     set & reset klokbit    
   next kolom
  next text 
next row

Op 5 april 2008 19:28:31 schreef Wouter van Ooijen:
dus nog even met de nieuwe data op de oude rij.

het is eigenlijk de oude data op de nieuwe rij :)

eigenwijs = ook wijs
trix

Golden Member

besluit toch maar om de voledige code te posten, let op !!! de data gedeelte onderaan is normaal veel langer maar om te voorkomen dat het hier te lang word heb ik dit terug gebracht naar een "blok" voor "display_text" (eigenlijk 25 blokken) en een voor "alfabet" (eigenlijk 58 blokken).

code:


  $regfile = "m8def.dat"
$crystal = 4000000                                          'internal crystal cksel(3-0) = 0011
                                                             'fuses
                                                             'let op !! geinverteerd invoeren
Ddrc = &B0000_0111
Portc = &B1111_1000

Dim Masker0 As Byte                                         'select bit for row 0
Dim Masker1 As Byte                                         'select bit for row 1
Dim Masker2 As Byte                                         'select bit for row 2
Dim Masker3 As Byte                                         'select bit for row 3
Dim Masker4 As Byte                                         'select bit for row 4
Dim Masker5 As Byte                                         'select bit for row 5
Dim Masker6 As Byte                                         'select bit for row 6
Dim Masker7 As Byte                                         'select bit for row 7
Dim Lettercolum As Byte
Dim Pointer_alfabet As Byte
Dim Pointer_display_text As Byte
Dim Row As Byte
Dim X As Byte                                               'flag for databit
Dim Columx5 As Byte                                         'to pick up 5 colums from alfabet
Dim Character As Byte                                       'letter wich has to pick up from alfabet
Dim Aa As Byte                                              'temp valeu for translate : display_text ---> alfabet
Dim Cc As Byte                                              'temp valeu for translate : display_text ---> alfabet
Dim Qq As Byte                                              'temp valeu for create databit
Dim Empty_display As Byte


Ddrd = &B1111_1111                                          'portD = output for row drivers


Clockbit Alias Portc.0                                      'pin 11 (on 74hc595) SHcp
Databit Alias Portc.1                                       'pin 14 (on 74hc595) DS
Latchbit Alias Portc.2                                      'pin 12 (on 74hc595) STcp

Masker0 = &B00000001                                        'select bit for row 1
Masker1 = &B00000010                                        'select bit for row 2
Masker2 = &B00000100                                        'select bit for row 3
Masker3 = &B00001000                                        'select bit for row 4
Masker4 = &B00010000                                        'select bit for row 5
Masker5 = &B00100000                                        'select bit for row 6
Masker6 = &B01000000                                        'select bit for row 7
Masker7 = &B10000000                                        'select bit for row 8

Do

For Row = 0 To 7
                                            'control row drivers
   If Row = 0 Then
   Portd = &B0000_0001
   End If
   If Row = 1 Then
   Portd = &B0000_0010
   End If
   If Row = 2 Then
   Portd = &B0000_0100
   End If
   If Row = 3 Then
   Portd = &B0000_1000
   End If
   If Row = 4 Then
   Portd = &B0001_0000
   End If
   If Row = 5 Then
   Portd = &B0010_0000
   End If
   If Row = 6 Then
   Portd = &B0100_0000
   End If
   If Row = 7 Then
   Portd = &B1000_0000
   End If






Restore Display_text
   For Pointer_display_text = 0 To 25                       'read the text from the : display_text
      Cc = Lookup(pointer_display_text , Display_text)
      If Cc = &H00 Then
      Waitms 1
      Set Latchbit                                          'to put bits on outputs 74hc595
      Waitus 1
      Reset Latchbit
      Goto End_text_display

      End If

      Aa = Cc - &H20                                        'transfere to place in alfabet
      Character = Aa * 5


   Restore Alfabet
      For Columx5 = 0 To 4

         Pointer_alfabet = Character + Columx5
         Lettercolum = Lookup(pointer_alfabet , Alfabet)    'pick up letter fonttable (alfabet)

         If Row = 0 Then
         X = Lettercolum And Masker0                        'select bit for row 0
         End If
         If Row = 1 Then
         X = Lettercolum And Masker1                        'select bit for row 1
         End If
         If Row = 2 Then
         X = Lettercolum And Masker2                        'select bit for row 2
         End If
         If Row = 3 Then
         X = Lettercolum And Masker3                        'select bit for row 3
         End If
         If Row = 4 Then
         X = Lettercolum And Masker4                        'select bit for row 4
         End If
         If Row = 5 Then
         X = Lettercolum And Masker5                        'select bit for row 5
         End If
         If Row = 6 Then
         X = Lettercolum And Masker6                        'select bit for row 6
         End If
         If Row = 7 Then
         X = Lettercolum And Masker7                        'select bit for row 7
         End If

         If X = 0 Then                                      'becouse the bit after the masker can be on 8 different places
         Qq = 0
         Else
         Qq = 1
         End If

         Databit = Qq                                       'shift bit to 74hc595
         Set Clockbit
         Waitus 10                                          'shift bit to 74hc595
         Reset Clockbit                                     'shift bit to 74hc595


      Next Columx5

   Next Pointer_display_text
End_text_display:

   For Empty_display = 0 To 159
      Databit = 0
      Set Clockbit
      Waitus 10
      Reset Clockbit

      If Empty_display = 159 Then
      Set Latchbit
      Waitus 10
      Reset Latchbit
      End If
      Waitus 1
   Next Empty_display
                                                    'ontime leds
Next Row

Loop

End

Display_text:

'character 1  !!! DIT ZIJN EIGENLIJK 26 BLOKKEN !!!
Data &H41



Alfabet:

' H41      A    !!! DIT ZIJN EIGENLIJK 58 BLOKKEN !!!
Data &B11111100
Data &B00010010
Data &B00010001
Data &B00010010
Data &B11111100

edit: dit is de gecorigeerde werkende code (5-4-2008 21:35)

eigenwijs = ook wijs

Basic? Gruwelijk spul, waar ik 26 jaar geleden al een hekel aan had... :-)

'k Zal toch maar een poging doen:

code:


Do
    Portd = 0                                      'Alle kolommen uitschakelen

Restore Display_text
   For Pointer_display_text = 0 To 25              'read the text from the : display_text
      Cc = Lookup(pointer_display_text , Display_text)
      If Cc = &HFF Then                             'enz...

If Row = 0 Then                                     'Nu een nieuwe kolom activeren
   Portd = &B00000001
   End If
   If Row = 1 Then                                  'enz...

Het is dus de bedoeling dat je:
1) de data voor de volgende rij berekent
2) alle kolommen uitschakelt
3) de data van een volgende rij doorsluist naar de schuifregisters
4) de bijbehorende kolom inschakelt

Dat wordt niet helemaal duidelijk gemaakt in het stukje code hierboven, maar misschien wil een brave ziel het wel vertalen voor je...

Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
klein is fijn

Moderator

Op 5 april 2008 19:28:31 schreef Wouter van Ooijen:
Let vooral op: eerst rijen uitzetten, dan de 595 holding register clokken, dan de nieuwe rij aan zetten.

Het klinkt inderdaad of dat het probleem is.

Waarom gebruik je trouwens niet het SHIFTOUT commando van Bascom?

trix

Golden Member

het probleem lijkt opgelosd:

wat gebeurde er: ik zette de data naar de uitgangen van de 74hc595 met de latchbit vervolgen selecteerde ik de volgende rij waardoor de data nog even op de nieuwe rij te zien was totdat ik hier een nieuwe rij data opzet.

oplossing: voor de functie "next row" doe ik nu 160x een "0" inklokken en zet deze met de latch op de uitgang, dus voor de nieuwe rij geselecteerd word.

ik zal de nieuwe code vervangen voor de oude en dit met een edit aangeven (als dit nog gaat). edit: is gebeurd

Op 5 april 2008 20:53:32 schreef klein is fijn:
Waarom gebruik je trouwens niet het SHIFTOUT commando van Bascom?

omdat ik nog maar een driekwart jaar programeer en ik niet alle functies ken, maar ik zal er zeker naar kijken

iedereen bedankt voor het meedenken

eigenwijs = ook wijs