Hoi ik zit met het volgende probleem.
Voor een pic 16f690 heb ik in asm een "programmatje" geschreven.
De bedoeling is dat op iedere 2e puls die op ingang RA,1 binnenkomt mijn 7 segment display een cijfer hoger aangeeft.Hij telt door t/m 75 waarna hij stopt.
Tot hier lijkt het goed te werken.Maar de displays knipperen licht.
Weet iemand hoe dit te verhelpen ?
#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
ERRORLEVEL -302
ERRORLEVEL -305
ERRORLEVEL -224
;------------------------------------------
; VARIABLE DEFINITION -
;------------------------------------------
;INPUTS
cntr1 EQU H'20' ; adress voor delay
cntr2 EQU H'21' ; " "
#define DISPL1 PORTB,6 ; DISPLAY 1 TALLEN
#define DISPL2 PORTB,5 ; DISPLAY 10 TALLEN
org 0
GOTO RST
;--------------------------------------------
; CREATE A LITTLE MULTIPLEX TEMPO -
;--------------------------------------------
delay movlw 0x01 ; delay loop voor multiplexing
KILL movwf cntr2 ; delay timer voor reset / stop effect
delay1 movlw 0xff
movwf cntr1
delay2 BTFSC PORTA,0 ; is PORTA,0 hoog ( reset knop )
GOTO E_RESET ; ga naar E_RESET
BTFSC PORTA,2 ; is PORTA,2 hoog ( stop knop )
GOTO E_OFF ; ga naar E_OFF
decfsz cntr1, f ; anders vervolg routine
goto delay2
decfsz cntr2, f
goto delay1
return ; ga terug naar laatste commando
;---------------------------------------------
; *** RESET : MAIN BOOT ROUTINE *** -
;---------------------------------------------
RST BSF STATUS,RP1 ;BANK2
MOVLW B'00000000'
MOVWF CM1CON0
MOVLW B'00000000'
MOVWF CM2CON0
CLRF ANSEL ;I/O'S DIGITAL
;
BSF STATUS,RP0 ;BANK1
MOVLW B'11010111'
MOVWF OPTION_REG ;SET PIC OPTIONS
MOVLW B'00000111'
TRIS PORTA
MOVLW B'00000000'
TRIS PORTB
MOVLW B'00000000' ;I/O'S DIRECTION
TRIS PORTC
;
BCF STATUS,RP0 ;BACK TO BANK 0
CLRF PORTA
CLRF PORTB
CLRF PORTC
GOTO E_ON
;--------------------------------------------------
; START OF PROGRAM -
;--------------------------------------------------
E_ON CLRF PORTC
BTFSC PORTA,0 ; is RA,0 hoog ga naar E_RESET
GOTO E_ON ; is RA,0 laag vervolg routine
E_AAN MOVLW H'CF'
CALL SEG2
MOVLW H'CB'
CALL SEG1 ; power attention / displays shows : ON
BTFSC PORTA,0
GOTO E_RESET ; start teller --> E_RESET
GOTO E_AAN
;--------------------------------------------------------------
E_RESET CLRF PORTC
CLRF PORTB ; wis displays
BTFSC PORTA,0
GOTO E_RESET ; wacht tot resetknop wordt losgelaten
BTFSC PORTA,1
GOTO E_1 ; wacht op startpuls van RA,1 en ga dan naar E_1
GOTO E_RESET ; anders blijf wachten op startpuls
; *************************
; * DISPLAY BESTURING *
; *************************
E_1 CLRF PORTC
CLRF PORTB ; wis "ON" op displays
BTFSC PORTA,1 ; kijk naar een puls op input RA,1
GOTO E_1 ; wacht tot PORTA,1 laag is en ga dan verder
E_01 MOVLW H'03'
CALL SEG1 ; zet de nieuwe output waarde op het display "1"
BTFSC PORTA,1 ; wacht op een puls op RA,1 en ga naar E_001
GOTO E_001
GOTO E_01
E_001 BSF DISPL1 ; laat "1" op het display staan
BTFSC PORTA,1
GOTO E_001 ; en wacht tot RA,1 weer laag is
E_0001 MOVLW H'03' ; zet "1"nogmaals op het display
CALL SEG1
BTFSC PORTA,1 ; kijk naar een puls op RA,1
GOTO E_2 ; en ga dan naar E_2
GOTO E_0001
E_2 MOVLW H'03'
CALL SEG1 ; laat "1" op het display staan tot RA,1
BTFSC PORTA,1 ; weer laag is
GOTO E_2
E_02 MOVLW H'9D'
CALL SEG1 ; zet de nieuwe output waarde op het display "2"
BTFSC PORTA,1 ; en herhaal het voorgaande
GOTO E_002
GOTO E_02
E_002 BSF DISPL1
BTFSC PORTA,1
GOTO E_002
E_0002 MOVLW H'9D'
CALL SEG1
BTFSC PORTA,1
GOTO E_3
GOTO E_0002
; *-----------------------------*
; *- X DISPLAY OUTPUT X -*
; *-----------------------------*
SEG1 MOVWF PORTC
BSF DISPL1 ; zet waarde op display 1
CALL DELAY
BCF DISPL1
RETURN
SEG2 MOVWF PORTC
BSF DISPL2 ; zet waarde op display 2
CALL DELAY
BCF DISPL2
RETURN
Maak de volgende waarde eens kleiner: delay1 movlw 0xff
De waarde schrijf je daarna naar cntr1.
Die waarde regelt hoe lang elk display aan staan.
Als het ene display aan staat, staat het andere uit. Als je dit snel genoeg doet zie je niet meer dat ze om en om aan staan (traagheid van je oog).
Doordat de tijd dat elk display aanstaat te lang is zie je nu het geknipper.
[Bericht gewijzigd door gizmo17110 op (59%)]
Hoi gizmo,bedankt voor je reactie.
Ik heb de waarde van delay1 kleiner gemaakt.tot 0x01
Dit is niet het gedeelte waar het probleem in zit.
Met de waarde van delay1 op 0xff bereik ik een frequentie van ongeveer 60 hertz.Dit is ruim voldoende voor het multiplexen.
In het effect waarmee het programma start, E_ON geven de displays ON aan en hier knipperen de displays nog niet.
Als nadat RA,1 hoog is geworden en het programma naar E_1 springt begint het probleem pas.Vanaf dit moment beginnen de displays heel licht te knipperen, dit doen ze op het moment dat een btfsc commando wordt gelezen.
In ieder opvolgend effect 1 t/m 75 knippert het display twee keer.
Nog enig idee hoe dit op te lossen is ?
grtz beest
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
@arco volgens mij mist e3 t/m e75 uit het programma
Nu even wat beter gekeken.
Je display staat uit zolang de puls op poort A 1 hoog is, dit veroorzaakt waarschijnlijk het knipperen.
Display2 staat bij de eerste 3 getallen ook uit.
Als je E 1 t/m 75 hebt gebruikt in je programma, dan kan je het programma een behoorlijk stuk kleiner maken met de INCF instructie en een stukje code die je getallen omzet naar 7 segment.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
@arco volgens mij mist e3 t/m e75 uit het programma
Je gaat me toch zeker niet vertellen dat dat blok code 75 keer is gekopieerd? 
Wouter van Ooijen
Wouter van Ooijen: VOTI webwinkel, docent HvU (Technische Informatica); C++ on mictrocontrollers blog
wrsch. niet 'het' probleem, maar volgens mij doe je bit operaties direct op het poort register: read-modify-write probleem!
Het programma is idd best groot geworden,zodra de displays goed oplichten ga ik proberen het programma op een compactere manier te schrijven.
wel heb ik nog een vraag.
De bit operatie voer ik idd direct op de poort uit.
Om ervoor te zorgen dat tijdens het inlezen van RA,1 het display aanblijft heb ik onderstaand stukje code toegevoegd.
E_01 MOVLW H'03' ; <-
CALL SEG1 ; <-
BTFSC PORTA,1 ; blijf zolang RA,1 hoog is het display aansturen
GOTO E_001 ;
GOTO E_01 ;
Als dit stukje ( eerste twee regels ) wordt weggelaten gaat het display eventjes helemaal uit.Nu dit stukje code er staat. dimt het display iets op het moment dat de code wordt gelezen.
Nu heb ik geprobeerd om de bewerkingen via het TRIS register uit te voeren maar dat geeft nog steeds hetzelfde effect.
Is er een manier om het dimmen te voorkomen ?
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Iets compactere (Q&D)versie zonder knipper:
#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
pclath_temp equ 0x70
w_temp equ 0x71
status_temp equ 0x72
digcount equ 0x73
digit1 equ 0x74
digit2 equ 0x75
digit3 equ 0x76
digit4 equ 0x77
maxdigits equ d'2' ; d'4'
org 0x000
goto Init
Irq org 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
movf status,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf pclath,w ; move pclath register into W register
movwf pclath_temp ; save off contents of PCLATH register
movf digcount,w
banksel portb
call digtab ; select digit
movwf portb
movlw digit1
movwf fsr
movf digcount,w
addwf fsr,f
movf indf,w
call segtab ; set segment data
movwf portc
incf digcount,f
movf digcount,w
xorlw maxdigits
btfsc status,z
clrf digcount
bcf intcon,t0if
goto restore
segtab addwf pcl,f
dt 0x3f,0x03,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
digtab addwf pcl,f
dt 0x20,0x40,0x80,0x10
restore movf pclath_temp,w ; retrieve copy of PCLATH register
movwf pclath ; restore pre-isr PCLATH register contents
movf status_temp,w ; retrieve copy of STATUS register
movwf status ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
Init
banksel tmr0
clrf tmr0
clrf digcount
bsf intcon,t0ie
bsf intcon,gie
bsf intcon,peie
banksel ansel
clrf ansel ;i/o digital
clrf anselh
banksel option_reg
movlw b'10000011'
movwf option_reg ;Set option reg.
banksel trisa
movlw b'00000111'
movwf trisa
movlw b'00000000'
movwf trisb
movlw b'00000000'
movwf trisc
main movlw d'3' ;
movwf digit1
movlw d'7'
movwf digit2
; movlw d'9'
; movwf digit3
; movlw d'4'
; movwf digit4
loop goto loop
end
Display data staat in digit1 en digit2.
Voor 4 displays kun je B7 en B4 als digit select voor resp 3 en 4 gebruiken. (maxdigits dan op 4 zetten)
knoppen kun je in main zelf toevoegen.
Hey arco ingewikkeld stukje code,hier was 'k zelf nooit opgekomen.
Ben nog wel even bezig om uit te zoeken wat het precies doet.
tnks beest.
Arco
Special Member
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Interrupt gestuurde multiplex van displays is eigenlijk de enige juiste manier, omdat dan de displays netjes op tijd gerefreshed worden.
(Zonder hinderlijke knipper-effecten of helderheidswisselingen, veroorzaakt door wachten op toetsen e.d...)
Turbokeu
Golden Member
I love watching conspiracy theorists use the airtight logic of the argument from incredulity: "Well I don't understand how it works so it can't be real!!!"
Zo is het Arco, proper gedaan!
BTW, blij te horen dat er hier nog een 'die hard' ASM'er zit, ik voel me zowat verloren tussen al die 'Basic' en 'C' toestanden hier...