PIC 16F887 en MikroBasic

Arco

Special Member

In een ander artikel las ik dat de instructietijd = 4 / oscillatorfrequentie.

Instructieclock is oscillatorfrequentie / 4...
( sysclock >> 2 is hetzelfde als sysclock / 4 )

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

Golden Member

Ik heb het programmaatje wat versimpeld zodat er een knipperfrequentie overblijft van ca 1 sec.
Het lukt nu allemaal. Het blijft wel even wennen bij het maken van loops en condities, omdat door bijvoorbeeld de Decfsz er één statement wordt overgeslagen.

Er is geen end if of wat daar op lijkt, waarmee je een aantal statements zou kunnen vangen in het blok (zoals in basic).
In plaats daarvan moet het dan worden opgevangen met goto's.

Ik heb het nu zo:

pic asm code:

 ;**********************************************************************
                #include <p16f1827.inc>     ;processor specific variable definitions
   				__CONFIG _CONFIG1, _FOSC_XT & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _CP_OFF & _CPD_OFF & _MCLRE_OFF & _IESO_ON
				__CONFIG _CONFIG2, _LVP_OFF & _PLLEN_OFF & _BORV_19
                ErrorLevel - 302
;**********************************************************************
   	org		00h                ;beginadres kiezen
		banksel	TRISA            	 ;kies bank 1
		clrf		TRISA              ;alles pinnen poort A uitgang maken
				
	CBLOCK 0X20
		Count1 ; delen door 250
		Count2 ; delen door 200
		Count3 ; delen door 4		
	ENDC 				
          
                
knipper	        
		banksel	LATA
		movf		LATA,w		 		;laad 01h in W
		xorlw  	1
		movwf		LATA		   		;zet de waarde van W
	        call 	        delay_1sec
		goto		knipper	

Delay_1sec								;delen door 4*200*250 = 200.000
		movlw d'4'
		movwf count3
loop1
		movlw d'200'
		movwf count2
loop2
		movlw d'250'
		movwf count1
loop3
		nop
		nop
		decfsz count1,f
		goto loop3
		decfsz count2,f
		goto loop2
		decfsz count3,f
		goto loop1
		return		
 END 
Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

MPSIM is heel handig om timeloops te bestuderen, kun je stap voor stap of animated er doorheen lopen...
Er zweven wel hulpfiles met macro's rond die FOR/WHILE/DO/SELECT CASE functionaliteit bieden, zoals ENGR2210.INC (een keer getest en werkt, maar ik gebruik 't niet)

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

Golden Member

Bij nieuwe projecten wordt de vraag gesteld of het 'absolute' of 'relocatable' moet worden gebuild.

Wat is aanbevelenswaardig?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Het hangt er vanaf of het een klein project met 1 source is of uit meerdere sources bestaat...

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

Golden Member

Op 6 november 2019 16:12:56 schreef Arco:

Hier heb ik al eens een leuk voorbeeld gegeven in assembly: een 4 digit led klok met gelijkzetmogelijkheid in maar 171 words geheugen... ;)
https://www.circuitsonline.net/forum/view/message/2107242#2107242

Ik heb geen 648A. De uitdaging is om dit aan de praat te krijgen met een PIC16F628A.
Beiden lijken veel op elkaar als ik in de datasheets kijk, zij het dat de 648A meer Flash geheugen heeft zo te zien.

De displays lichten echter niet op.
(connecties / aansluitingen zijn goed, een testprogrammaatje toont dit aan).
Ik gebruik een extern kristal van 4 Mhz.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Zou gewoon moeten werken. Je moet wel de clock goedzetten met _FOSC_XT. (staat op externe oscillator 10MHz)
Voor 4 MHz moet je dan

code:


                banksel pr2                     ;Timer 2 value 
                movlw   d'124'
                movwf   pr2

veranderen in

code:


                banksel pr2                     ;Timer 2 value 
                movlw   d'49'
                movwf   pr2

Je kunt ook de 1827 code gebruiken. (die heb je toch ook?)

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

Golden Member

Ik heb er voor alle zekerheid een 10Mhz kristal in gedaan en de oude waarden laten staan.
Maar help niet.
Het programma lijkt niet te 'lopen'; zo staan alle Poorten B op 0, net zoals de vier 'driver' Poorten A3 t/m A0.
De MCLR is hoog, met een pull-up naar de +5V.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Zoals gezegd, hij staat op externe oscillator, dus geen kristal. Voor 10MHz moet je die op _FOSC_HS zetten...
Werkt hier prima met een 628a/648a/1827
Hexfile voor de 628a attached.

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

Golden Member

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

Nu weer even terug naar MikroBasic om 7-segment displays te multiplexen.
Ik tel tot 59 met 1 seconde als telfrequentie.

Op zich lukt dat wel, maar ik worstel alleen nog even met de vraag waar je nu de delay van 1000 ms neerlegt.
Onderstaand programma telt tot 59, maar je ziet de displays maar in een flits van 5ms vanwege de delay_ms(5).
Verhoog ik die delay, dan krijg je knipperen als effect.

Eigenlijk zou je de display loop continue willen laten lopen voor een strak beeld, maar hoe krijg je er dan in dat je per seconde de waarden ververst?

pic basic code:

program LedBasic

' Declarations section 

Const Cijfer as Byte [10] = (63, 6,  91, 79, 102, 109, 125, 7, 127, 111)
Const Disp as Byte [4] = (1, 2, 4, 8)

Dim Inhoud as Byte[4]

Dim D1 as byte
Dim D2 as byte
Dim X1 as byte

sub procedure Tonen()
for x1 = 0 to 1
   Portb = Inhoud[x1]
   Porta = Disp[x1]
   delay_ms(5)
   Porta = %00000000
next x1
end sub

main:

    trisa = %00000000
    porta = %00000000
    
    trisb = %00000000
    portb = %00000000

while true
   For D2 = 0 to 5
       Inhoud[1] = Cijfer[D2]
       For D1 = 0 to 9
          delay_ms(1000)
          Inhoud[0] = Cijfer[D1]
          Tonen()
       Next D1
   Next D2
wend
end.  
Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Eigenlijk heb je voor nette timing interrupts nodig zoals in mijn klok voorbeeld...
Belangrijkste is dat je alle displays om de beurt even lang laat zien. En dat met een snelheid hoger als een mens kan waarnemen.
(in mijn klok voorbeeld is de multiplexrate 250Hz, dwz. elk display is 1/250 seconde aan)

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

Golden Member

Jawel,
Maar als je ergens een delay inbouwt van 1 sec, dan wordt de subroutine Tonen pas om de seconde aangeroepen. En zie je daardoor maar heel even de displays oplichten.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Je moet ook 250x per seconde van display wisselen, niet 1 seconde lang hetzelfde display... ;) Dus:

- Disp1 aan, 4mS wachten, disp1 uit.
- Disp2 aan, 4mS wachten, disp2 uit.
- Disp3 aan, 4mS wachten, disp3 uit.
- Disp4 aan, 4mS wachten, disp4 uit.
- Disp1 aan, 4mS wachten, disp1 uit.
...
...

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

Golden Member

Dat was dus inderdaad de truc.

Het MikroBasic programma werkt nu.
Misschien wel niet helemaal zuiver qua tijd: 4 display's met een vertraging van 1ms 250 keer laten knipperen levert in principe 1000ms op.
Daarbij is de tijd die nodig is voor het aansturen van de displays niet meegeteld (wellicht valt dat mee).

In ieder geval hier mijn programma. (Wie had dat kunnen denken nog geen 2 maanden geleden...)

pic basic code:

  program LedBasic

' Declarations section 

Const Cijfer as Byte [10] = (63, 6,  91, 79, 102, 109, 125, 7, 127, 111)
Const Disp as Byte [4] = (1, 2, 4, 8)

Dim Inhoud as Byte[4]

Dim D1 as byte
Dim D2 as byte
Dim D3 as byte
Dim D4 as byte
Dim X1 as byte
Dim T1 as byte

sub procedure Tonen()
For T1 = 1 to 250
   For X1 = 0 to 3
      Portb = Inhoud[x1]
      Porta = Disp[x1]
      delay_ms(1)
      Porta = %00000000
   Next X1
Next t1
end sub

main:

    trisa = %00000000
    porta = %00000000
    trisb = %00000000
    portb = %00000000

while true
   For D4 = 0 to 5
      Inhoud[3] = Cijfer[D4]
      For D3 = 0 to 9
         Inhoud[2] = (Cijfer[D3] OR %10000000)
            For D2 = 0 to 5
               Inhoud[1] = Cijfer[D2]
               For D1 = 0 to 9
                  Inhoud[0] = Cijfer[D1]
                  Tonen()
               Next D1
           Next D2
    Next D3
   Next D4
wend

end. 
Fouten zijn het bewijs dat je het probeert..