Mikrobasic, Interrupts en multiplexen

Arco

Special Member

De toestand van het data (ram) geheugen is 'unknown' bij power-up. Al je bepaalde waardes wilt moet je dat zelf doen.
Bij alle GPR SFR registers staat duidelijk wat hun waarde is bij diverse soorten resets...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Hm, Dit voorbeeld is een opsomming van de waarde van PoortB.

Een byte definiëren in het programma komt toch in het flash geheugen?

Het probleem wat ik zelf een beetje heb, is dat dankzij de snelle respons van Arco ik iedere keer weer een stapje meer leer.
Maar hoe je nu uit jezelf uit de (omvangrijke) datasheet bij een GPR register komt.. ;(

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Ramlocaties kunnen willekeurige waardes hebben na een power-up, ik heb ook vaak dat ze 0xFF zijn...
(met GPR bedoelde ik eigenlijk SFR in het voorbeeld...)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik heb het programmaatje inmiddels weer wat opgeschoond en uitgebreid met seconden.
Het ding loopt perfect op tijd (2x 22pF aan het 10Mhz kristal).

Het 'grappige' is dat het lastig lijkt om tussen digit 3 en 4 twee dubbele puntjes te maken.
Dat kan ik wel, maar kost een heleboel IF's en andere code, wat ik weer jammer vindt omdat het programma nu lekker kort is.

Je kan ook niet standaard enkele ledjes (puntjes) aanzetten, omdat de hele rij wordt geschreven via de MAX7219 chips.

Tenzij het toch wat korter kan...(wellicht extra regel schrijven met een AND?)

pic basic code:

Program MatrixKlok
'Klok met uren, minuten en seconden
'Display Matrix Led 8 * 8, type 1088AS

Dim Digit      As Byte[6]
    Seccount   As Byte
    MinCount   As Byte
    KeyCount   As Byte
    Flags      As Byte
    fKeyRpt    As sBit At Flags.0
    fDigit     As Byte                   'Indicates which Digit has to be updated
    ClockPin   as sbit at PORTC.3        'pin 18
    Latch      as sbit at PORTC.7        'pin 26
    Datapin    as sbit at PORTC.5        'pin 24
    Row        as Byte
    
Const Keytime        = 120             '0.6sec
      Keydebounce    = 10              '40mS

Const font as byte[80] =               'Character tabel, 90 Degrees turn left
(
  0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c,
  0x00, 0x7e, 0x18, 0x18, 0x18, 0x1c, 0x18, 0x18,
  0x00, 0x7e, 0x06, 0x0c, 0x30, 0x60, 0x66, 0x3c,
  0x00, 0x3c, 0x66, 0x60, 0x38, 0x60, 0x66, 0x3c,
  0x00, 0x30, 0x30, 0x7e, 0x32, 0x34, 0x38, 0x30,
  0x00, 0x3c, 0x66, 0x60, 0x60, 0x3e, 0x06, 0x7e,
  0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c,
  0x00, 0x18, 0x18, 0x18, 0x30, 0x30, 0x66, 0x7e,
  0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c,
  0x00, 0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c
)
'  0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c,
'===============================================================================
Sub Procedure Max_Write(Dim pCol, pDig0, pDIg1, pDig2, pDig3, pDig4, pDig5 as Byte)
'===============================================================================
 Latch = 0
 SPI1_Write(pCol)
 SPI1_Write(pDig0)
 SPI1_Write(pCol)
 SPI1_Write(pDig1)
 SPI1_Write(pCol)
 SPI1_Write(pDig2)
 SPI1_Write(pCol)
 SPI1_Write(pDig3)
 SPI1_Write(pCol)
 SPI1_Write((pDig4))
 SPI1_Write(pCol)
 SPI1_Write(pDig5)
 Latch = 1
 delay_ms(2)
End sub

'===============================================================================
Sub Procedure Max7219_Init()
'===============================================================================
Max_Write(0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
Max_Write(0x0B, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07)
Max_Write(0x0C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01)
Max_Write(0x0A, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01)
End sub

'===============================================================================
Sub Procedure Display_Testen()      'Testen van het display; alle LEDS aan
'===============================================================================
Max_Write(0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01)
DELAY_MS(50)
Max_Write(0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
DELAY_MS(50)
End sub

'===============================================================================
Sub Procedure Uitzetten_Leds()      'Leds uitzetten per Row
'===============================================================================
FOR Row = 1 TO 8
   Max_Write(Row, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
   delay_ms(5)
NEXT Row
End sub

'===============================================================================
Sub Procedure Update_LED            'Update LED
'===============================================================================
  If (Digit[0] > 9) then Digit[0] = 0 inc (Digit[1]) end if
  If (Digit[1] > 5) then Digit[1] = 0 inc (Digit[2]) end if
  If (Digit[2] > 9) then Digit[2] = 0 inc (Digit[3]) end if
  If (Digit[3] > 5) then Digit[3] = 0 inc (Digit[4]) end if
  If (Digit[4] > 9) then Digit[4] = 0 inc (Digit[5]) end if
  If (Digit[5] > 2) then Digit[5] = 0 end if
  If (Digit[5] = 2) And (Digit[4] > 3) Then
      Digit[0] = 0  Digit[1] = 0    Digit[2] = 0  Digit[3] = 0 
      Digit[4] = 0  Digit[5] = 0
  end if

  For Row = 1 to 8
     Max_Write(Row, Font[(Digit[0]<<3) + (Row - 1)],
                    Font[(Digit[1]<<3) + (Row - 1)],
                    Font[(Digit[2]<<3) + (Row - 1)],
                    Font[(Digit[3]<<3) + (Row - 1)],
                    Font[(Digit[4]<<3) + (Row - 1)],
                    Font[(Digit[5]<<3) + (Row - 1)])
  Next Row
End sub

'===============================================================================
sub procedure Interrupt() iv 0x0004 ics ICS_AUTO
'===============================================================================
  If TMR2IF_bit Then                                    'See if timer2 irq
    Inc(Seccount)                                       'If so, update coun-
    If Seccount = 250 Then                              'ters.
       Seccount = 0                                     'Set flag if second is passed
       fDigit = 7                                       'Set Flag to Update LED
    End If
   '----------------------------------------------------------------------------
    if portb = 255 then                                 'No key pressed
       fKeyRpt = 0 
       KeyCount  = 0 
    Else
       Inc(KeyCount)
         if KeyCount = KeyDebounce then                                           '
            if portb.3 = 0 then FDigit = 6 end if
            if portb.2 = 0 then FDigit = 5 end if
            if portb.1 = 0 then FDigit = 4 end if
            if portb.0 = 0 then FDigit = 3 end if
            Digit[0] = 0
            Digit[1] = 0                                   '
            SecCount  = 0                                             '
         End if
    End if                                                 '
   TMR2IF_bit = 0
  End If
End sub

'===============================================================================
Main:

'===============================================================================
  T2CON      = %00100110                                      'Post:5 - Pre:16
  PR2        = 124                                            'Timer load value
  ANSELh     = %00000000                                      'Port B   digital
  TRISC      = %00111101
  TRISB      = %00000000
  PORTB      = %11111111

  GIE_bit    = 1                                              'Enable timer2 irq
  PEIE_bit   = 1
  TMR2IE_bit = 1 

  For fDigit = 0 to 5                                         'Start with 00:00
   Digit[fDigit] = 0
  Next fDigit                                                 'Flag Display
  fDigit     = 0
  
  SPI1_Init()
  Max7219_Init()
  Display_Testen()
  Uitzetten_Leds()
  Update_LED()

  'Loop ----------------------------------------------------------------------
  While True
  if fDigit > 0 then
     select case fDigit
     case 1, 2, 3, 4, 5, 6
        Inc (Digit[(fDigit - 1)])
        Update_LED()
     case 7
        Inc(Digit[0])
        Update_Led()
     end select
     Fdigit = 0
  End if
  Wend

  End. 
Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Ramlocaties kunnen willekeurige waardes hebben na een power-up, ik heb ook vaak dat ze 0xFF zijn...
(met GPR bedoelde ik eigenlijk SFR in het voorbeeld...)

SFR snap ik :)

Het sterkt me in de gedachte gewoon initiële waarden altijd te zetten voordat een programma begint.

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Oplossing voor dubbel punten is gelukt en is eigenlijk best wel simpel:

pic basic code:

For Row = 1 to 8
     if (Row = 2) or (Row = 7) then i1= 128 else i1 =0 end if     'Double Points
     Max_Write(Row, Font[(Digit[0]<<3) + (Row - 1)],
                    Font[(Digit[1]<<3) + (Row - 1)],
                    Font[(Digit[2]<<3) + (Row - 1)],
                    Font[(Digit[4]<<3) + (Row - 1)],
                    Font[(Digit[4]<<3) + (Row - 1)] >>1 + i1,
                    Font[(Digit[5]<<3) + (Row - 1)] >>1)
  Next Row 

Op de 2e en 7e rij een extra ledje laten branden door 128 op te tellen bij het getoonde cijfer. De display's 4 en 5 eentje naar links opschuiven voor de sym

metrie.

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Zo nog eens een vraagje over de PIC16F1826:

Poort A.6 is de datapin voor een SPI interface. Maar ook de clockout voor een extern kristal.
Zijn die dan door elkaar te gebruiken of is het het één of het ander?

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Als ik wil afvragen of de eerste 4 bits (0 t/m 3) van een poort '1' zijn, kan ik het natuurlijk zo afvragen:

pic basic code:

if (PORTA.0 = 1) AND (PORTA.1 = 1) AND (PORTA.2 = 1) AND (PORTA.3 = 1) then   ....etc  

Maar ik vermoed dat het ook makkelijker kan.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

pic basic code:


if (PORTA And 0x0F) = 0x0F Then   ...etc

De SPI pin kun je verplaatsen in het APFCON0 register... (zit default trouwens op RB2, niet op RA6)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

De SPI pin kun je verplaatsen in het APFCON0 registe

Jawel, maar stel dat je de SPI pin dus op RA6 zet, dan betekent dat automatisch dat je dan in dat geval geen externe oscillator kunt gebruiken?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Ja, uiteraard...
Je kunt 1 pin niet tegelijk voor twee dingen gebruiken...

Geldt voor een kristal: een externe oscillator kan wel (die zit aan RA7)

[Bericht gewijzigd door Arco op woensdag 18 december 2019 14:29:07 (33%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik moet zeggen dat de 'truc' die Arco aangaf om een offset in de klok in te bouwen die ieder uur een correctie aanbrengt goed werkt en makkelijker is dan met condensatortjes met de klokfrequentie aan de gang te gaan.

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Soms kunnen kleine dingen je lang bezighouden (dwz vermoedelijk ergens zwaar overheen kijken... |:(

Hieronder een simpel voorbeeld van een tabel (16 bytes).
Het werkt als ik een waarde van i1 invul:

pic basic code:

const Font As Byte[16] = (       'Character table
     0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x78, 0x00,
     0x3e, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x3e, 0x00
     )
   
Main:


    Row = 2
    i1 = 0
    Max_Write(Row, Font[(i1*8) + (Row - 1)]*2) 

i1 staat dus op 0.
Maar wanneer ik dan de waarden invul in de formule, dan krijg ik een foutmelding: Getal '408' buiten de waarde van een byte.

pic basic code:

const Font As Byte[16] = (       'Character table
     0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x78, 0x00,
     0x3e, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x3e, 0x00
     )
   
    Row = 2
    i1 = 0
    Max_Write(Row, Font[(0*8) + (2 - 1)]*2) 

Deze gaat dus fout. Maar wat is nu het verschil met de eerste regels? i1 is toch immers 0 en row 2?

Ik heb al we gezien dat 408 een tweevoud is van 204 (0x66). Er gebeurt in mijn ogen iets onverklaarbaars..

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

204 = 0xCC, x2 = 408. Dit is meer als een byte dus foutmelding klopt... (zouden beide een foutmelding moeten geven...)
Zou kunnen dat de compiler de eerste niet controleert, omdat die niet 'hard-coded' is...

[Bericht gewijzigd door Arco op donderdag 2 januari 2020 01:28:55 (28%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Dat zou het idd kunnen verklaren.
(Grappig dat het wel werkt in de uitvoering)

In dat geval zit er wel een fout in de code.
Het is de bedoeling om het juiste byte te selecteren aan de hand van de waarde van i1.
Maar hij slaat blijkbaar aan het rekenen met de inhoud van de byte,

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

De code komt voor in mijn (nog steeds op de seconde gelijk lopende klok)

pic basic code:

For Row = 1 to 8
     if (Row = 2) or (Row = 7) then i1 = 128 else i1 = 0 end if   'Double Points
     if (Row = 2) or (Row = 7) then j1 = 1 else j1 = 0 end if
     Max_Write(Row, Font[(Digit[0]<<3) + (Row - 1)]<<1,
                    Font[(Digit[1]<<3) + (Row - 1)]<<1 + j1,
                    Font[(Digit[2]<<3) + (Row - 1)],
                    Font[(Digit[3]<<3) + (Row - 1)],
                    Font[(Digit[4]<<3) + (Row - 1)] >>1 + i1,
                    Font[(Digit[5]<<3) + (Row - 1)] >>1)
  Next Row

In dit geval met 6 digits.
Ik ben nu aan het testen met 1 Led Matrix, maar dan met karakters cijfers en letters)

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

bericht verwijderd

[Bericht gewijzigd door Bavelt op donderdag 2 januari 2020 02:05:46 (89%)

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

pic basic code:

 Max_Write(Row, Font[(Digit[0]<<3) + (Row - 1)]<<1,

Ik begin nu zelf te twijfelen of die <<1 wel goed is...

Ik snapte al niet wat die daar deed (vermenigvuldigen met 2)

[Bericht gewijzigd door Bavelt op donderdag 2 januari 2020 02:05:27 (20%)

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Een << 1 en vermenigvuldigen met 2 zijn hetzelfde. (de compiler maakt zelf al een '<<1' van een '*2')
(wat je er mee wilt is me ook duister. Je kunt ermee het font 1 rij naar links verschuiven, maar met waardes groter als 127 gaat dat niet)

[Bericht gewijzigd door Arco op donderdag 2 januari 2020 02:17:27 (12%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik ga het gewoon aanpassen; dingen die ik zelf al niet snap haal ik er uit.
Maar niet voordat ik de beste wensen voor 2020 heb overgebracht! :)

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Er is een aardig programma online beschikbaar, waarmee je cijfers, letters, etc kan maken voor een 8*8 Matrix: LED Matrix Editor.
Hij genereert zelfs de bijbehorende code, maar die is geënt op C.

Dan krijg je bv

c code:

const uint64_t IMAGES[] = {
  0x6666667e66663c00 } 

Het grappige is dat je hier blijkbaar een reeks kan opgeven, waarbij je eerst aangeeft dat alle volgende bytes hexadecimaal zijn en daarna de inhoud per byte.

Vertaald naar MikroBasic is dat:

pic basic code:

const Font As Byte[8] = (       'Character table
0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x3c, 0x00)

Je moet dus voor iedere byte er 0x voor zetten om aan te geven dat het hexadecimaal is.

Of is er wellicht een mogelijkheid zoals in C?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

0x moet altijd voor een hex getal notatie. En 64 bit variabelen zijn er alleen bij de PIC32 32 bits compiler. (bij een 8 bit MCU niet erg efficient)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ok, de LED Editor genereert de codes voor de karakters.
Dat betekent dan dat je voor de reeks maximaal 255 * 8 = 2040 keer '0x' (plus een komma) voor de bytes moet tikken.
Met wat handigheid met de editor is dat wat te verlichten.

En als je dan bv alles 90 Graden wilt draaien (Led matrix kwart slag gedraaid) je het nog een keer moet doen.
Tja..

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Tja... ;)

Niemand gaat een 255 karaktertabel bouwen, de meeste karakters gebruik je nooit en/of heb je niks aan...
En karakters in twee posities zie je ook al zelden (je weet vooraf toch wel in welke positie je de zaak wilt laten zien?)
Daarbij kun je ook een functie schrijven die het karakter desnoods 90 graden draait...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Klopt.
Ik heb het al voor elkaar, mbv Find-Replace kom je al een knap eind.
En kwart slag draaien ga ik een routine-tje schrijven, mooie oefening :) .

Fouten zijn het bewijs dat je het probeert..