Hey.

heb vandaag een counter gemaakt met 7segment displays, bestuurd door een pic (16F690). Ik bestuur het door multiplexing. Maar het lukt slechts met 2 digits. Wanneer ik de code aanpas voor 3 digits (en uiteraard het derde display correct aansluit) dan geeft het derde display de eerste twee displays samen weer. Het probleem moet softwarematig zijn, ofwel hou ik ergens geen rekening met iets ivm multiplexing. Het eigenaardige is dat het wel lukt met 2 displays.
Hieronder de code voor 3 displays.

program segmentcounter

dim shifter, digit, portc_index as byte
dim number as word
dim port as byte[3]

sub function Mask(dim num as byte) as byte    ' this function returns masks
  select case num                             ' for common cathode 7-seg. display
    case 0  result = $C0
    case 1  result = $F9
    case 2  result = $A4
    case 3  result = $B0
    case 4  result = $99
    case 5  result = $92
    case 6  result = $82
    case 7  result = $F8
    case 8  result = $80
    case 9  result = $90
  end select                                  'case end
end sub

sub procedure interrupt
  PORTA  = shifter             ' turn on appropriate 7seg. display
  PORTC  = port[portc_index]
  Inc(portc_index)             ' increment value of variable portc_index
  shifter = shifter << 1
  if shifter > 4 then
    shifter = 1                ' prepare mask for digit
  end if
  if portc_index > 2 then
    portc_index = 0            ' turn on 1st, turn off 2nd 7seg.
  end if
  TMR0   =   0
  INTCON = $20
end sub

main:
  OPTION_REG = $80
  digit      =   0
  portc_index =   0
  shifter    =   1
  TMR0       =   0
  INTCON     = $A0             ' Disable PEIE,INTE,RBIE,T0IE
  TRISA      =   0
  TRISC      =   0
  PORTC      =   0
  PORTA      =   0
  number     =   0

  while TRUE
    digit = number div 100 mod 10
    port[2] = Mask(digit)
    digit = number div 10 mod 10       ' prepare digits for diplays
    port[1] = Mask(digit)
    digit = number mod 10
    port[0] = Mask(digit)
    Delay_ms(100)
    Inc(number)                         ' increment counter
    if number > 999 then
      number = 0
    end if
  wend
end.

Voor zover ik iets van basic ken, zie ik daar geen fouten.

Maar misschien zijn het spook-segmenten, die de uitlezing verzieken. Ik zou --in de interrupt-routine-- eerst PORTA 0 maken, vervolgens PORTB instellen, en pas dan het gepaste bit op PORTA hoog maken.
Als er bipolaire transistors gebruikt worden, kan de tijd --tijdens dewelke PORTA 0 is-- best nog verlengd worden.

Staat er nog een analoge functie aan op port a misschien?
Is de multiplex frequentie niet te hoog?
Weet niet welke basic dit is, maar dit kan waarschijnlijk ook:


sub procedure interrupt
  PORTA  = 1 << portc_index                'turn on appropriate 7seg. display
  PORTC  = port[portc_index]
  portc_index = (portc_index + 1) mod 3    'turn on 1st, turn off 2nd 7seg.
  TMR0   =   0
  INTCON = $20
end sub

Werk je soms ergens met inverse logic? Pinnetje moet laag zijn ipv. hoog om wat aan te sturen? Met 2 gaat dat inderdaad goed en met 3 niet...

Als het inderdaad een inverse logic probleem is moeten ze (bij 3 displays) allemaal verkeerd weergeven...

De code ziet er goed uit. Ik zou als eerste hardware probleem proberen uit te sluiten door een test programma te schrijven dat bijvoorbeeld 1 seconde op display 1 een 1 zet, daarna 1 seconde op display 2 een 2 en daarna een 3 op display 3.

Bedankt voor de vele hoogstwaarschijnlijk probleemoplossende reacties. Ik ga jullie suggesties onmiddellijk es proberen.

Een hardwaretest heb ik al es uitgeprobeerd. Het enige wat ik niet kan testen is of de transistoren zouden te traag zijn, maar dat denk ik niet, want met 2 displays lukt het wel.

Ik zie:

  if shifter > 4 then
    shifter = 1                ' prepare mask for digit
  end if
  if portc_index > 2 then
    portc_index = 0            ' turn on 1st, turn off 2nd 7seg.
  end if

Het is logischer om gewoon dit te doen:

  if portc_index > 2 then
    shifter = 1                ' prepare mask for digit
    portc_index = 0            ' turn on 1st, turn off 2nd 7seg.
  end if
  TMR0   =   0

overbodig, het vertraagd het interrupt alleen maar. het interrupt it requested wanneer TMR0 al overflowde naar 0, en nu zet je hem even later weer op 0.

  INTCON = $20

Hoe kan dit ooit werken? Met dat commando zet je GIE uit. Ik zou doen:

  INTCON.T0IF = 0

of

  LOW INTCON.T0IF

afhankelijk van welke vasic je hebt (ik werk zelf niet met basic, dus kenners, klopt dit?)

Misschien niet de oplossing die je zoekt, maar wel wat pic basics om je vertrouwd te laten raken in basic

Ik heb nu het hele topic overlopen en alles geprobeerd wat jullie voorstelden, behalve de verversingsfrequentie (dus de interrupt) te verlagen. Ik ga direct nog es de info over timer0 en interrupts in de datasheet herlezen en trachten de frequentie te verlagen.

Werk je soms ergens met inverse logic?

De 8 pinnen van poort c worden laag gezet om het overeenkomstige segment te laten oplichten. De displays zijn dus uiteraard common anode. De 3 transistoren (2N3906) worden aangestuurd via poort A, waarbij een logische 1 de transistor doet geleiden en dus de overeenkomstige digit activeert.

Zijn er nog suggesties om uit te proberen? Is er iemand die nog zijn hersenen es wil pijnigen en een verklaring zoeken waarom het wel lukt voor 2 displays en niet voor 3.

[Bericht gewijzigd door jefkeVV op (13%)]

Op 8 september 2008 12:22:59 schreef jefkeVV:
De 3 transistoren (2N3906) worden aangestuurd via poort A, waarbij een logische 1 de transistor doet geleiden en dus de overeenkomstige digit activeert.

Nee, dit zijn pnp transistoren, dus een logische nul doet de transistor geleiden.....

Zou het kunnen dat de het komt omdat de interne rc-oscillator wordt geberuikt ipv een extern kristal?

@zonnepaneeltje:
Het zijn idd pnp-transistoren. Ik sluit ze als volgt aan:
collector naar 5V, emittor naar common anode, basis naar uitgangspin pic. Maak ik de correcte uitganspin hoog, dan licht de overeenkomstige digit op.

Dit klopt toch, of niet?

[Bericht gewijzigd door jefkeVV op (56%)]

Nee, de emitter moet aan de 5V.
De basis via een weerstandje naar de pic.
Als je de poortpin laag maakt gaat het desbsteffende digit aan.

De door jou beschreven aansluiting kan wel, maar dan moet je een NPN tor nemen.

[Bericht gewijzigd door Zonnepaneeltje op (22%)]

Maar waarom lukt het dan wel met 2 displays en niet met 3? Zo'n rare zaken heb ik nu nog nooit meegemaakt.
Weet je wat, om zeker te zijn dat de fout niet bij de transistoren ligt, ga ik es een uln2803 gebruiken.

[Bericht gewijzigd door jefkeVV op (33%)]