Anonymní profil CaCaO – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Anonymní profil CaCaO – Programujte.comAnonymní profil CaCaO – Programujte.com

 

Příspěvky odeslané z IP adresy 95.102.195.–

CaCaO
Assembler › PIC - vykreslovač hodín
22. 4. 2013   #175364

 Dobrý deň,

potreboval by som pomoc s objasnením nasledovného programu na vykreslovanie LED hodín pomocou rotujúcich LEDiek na motorčeku.

;--------
; Noblink.asm
; mechanically scanned LED clock
; Original file mclock.asm
; display of seconds added
; turned off the blinking double dots
;
;--------
                list    p=16F84
                radix   hex
                include "p16F84.inc"
;--------
; remember to set blast-time options: OSC=regular xtal, WDT=ON
; timings all based on 4 MHz crystal
;--------
w               equ     0
f               equ     1
;--------
; Start of available RAM.
;--------
        cblock  0x0C
                safe_w          ;not really temp, used by interrupt svc
                safe_s          ;not really temp, used by interrupt svc
                period_count    ;incremented each interrupt
                period_dup      ;copy of period_count safe from interrupt
                period_calc     ;stable period after hysteresis calc.
                period_use      ;stable period after hysteresis calc.
                flags           ;b2=int b1=minute b4=edge b5=seconds
                dot_index       ;which column is being displayed
                digit_index     ;which digit is being displayed
                hours           ;in display format, not hex(01-12)
                minutes ;00 to 59
                seconds ;00 to 59
                bigtick_dbl     ;incremented each interrupt
                bigtick_hi
                bigtick_lo
               sectick_hi
                sectick_lo
                keys            ;key value
                scratch         ;scratch value
                tick            ;used by delay
        endc
;--------
; Start of ROM
;--------
                org     0x00            ;Start of code space
                goto    Start
;--------
; INTERRUPT SERVICE ROUTINE
;--------
                org     0x04            ;interrupt vector
Intsvc          movwf   safe_w          ;save w
                swapf   STATUS,w        ;swap status, w
                movwf   safe_s          ;save status(nibble swap, remember)
;--------
; done saving, now start working
;--------
; clear watchdog timer to ensure startup
                clrwdt
;
; increment period count
;       incf    skip_cnt,f
;       btfss   STATUS,Z
;       goto    Bigticker
;       movlw   0xfe                    ;play with this one for width of displayed characters
;       movwf   skip_cnt
                incf    period_count,f
                btfsc   STATUS,Z        ;zero set means overflow
                decf    period_count,f
; 234375 interrupts every minute. Increment the bigtick each time.
Bigticker
                incf    bigtick_lo,f
                btfsc   STATUS,Z
                incf    bigtick_hi,f
                btfsc   STATUS,Z
                incfsz  bigtick_dbl,f
                goto    Bigtick_out
;--------
; here? bigtick has rolled over to zero and one minute has passed.
; reload bigtick and set a flag for the main counter
;--------
                movlw   0xFC            ;234375 = 0x039387
                movwf   bigtick_dbl     ;0 - 0x039387 = 0xFC6C79
                movlw   0x6C
                movwf   bigtick_hi
                movlw   0x79
                movwf   bigtick_lo
                bsf     flags,1         ;notify Keep_time
Bigtick_out
;-------- now start with the seconds
                incf    sectick_lo,f
                btfsc   STATUS,Z
                incfsz  sectick_hi,f
                goto    Sectick_out
;--------

; here? sigtick has rolled over to zero and one second has passed.
; reload sectick and set a flag for the main counter
;--------
                movlw   0xF0            ;3907 = 0x0F43
                movwf   sectick_hi      ;0 - 0x0F43 = 0xF0BD
                movlw   0xBD
                movwf   sectick_lo
                bsf     flags,5         ;notify Keep_time
Sectick_out
;--------
; done working, start restoring
;--------
                swapf   safe_s,w        ;fetch status, reswap nibbles
                movwf   STATUS          ;restore status
                swapf   safe_w,f        ;swap nibbles in preparation
                swapf   safe_w,w        ;for the swap restoration of w
                bcf     INTCON,2        ;clear interrupt flag before return
                retfie                  ;return from interrupt
;--------
; CHARACTER LOOKUP TABLE
; ignore high bit. set=LED off, clear=LED on, bit0=bottom LED, bit6=top LED
;--------
Char_tbl
                addwf   PCL,f
                dt      0xC1,0xBE,0xBE,0xBE,0xC1        ;"O"
                dt      0xFF,0xDE,0x80,0xFE,0xFF        ;"1"
                dt      0xDE,0xBC,0xBA,0xB6,0xCE        ;"2"
                dt      0xBD,0xBE,0xAE,0x96,0xB9        ;"3"
                dt      0xF3,0xEB,0xDB,0x80,0xFB        ;"4"
                dt      0x8D,0xAE,0xAE,0xAE,0xB1        ;"5"
                dt      0xE1,0xD6,0xB6,0xB6,0xF9        ;"6"
                dt      0xBF,0xB8,0xB7,0xAF,0x9F        ;"7"
                dt      0xC9,0xB6,0xB6,0xB6,0xC9        ;"8"
                dt      0xCF,0xB6,0xB6,0xB5,0xC3        ;"9"
;               dt      0xE0,0xDB,0xBB,0xDB,0xE0        ;"A"
;               dt      0x80,0xB6,0xB6,0xB6,0xC9        ;"B" 
;               dt      0xC1,0xBE,0xBE,0xBE,0xDD        ;"C" 
;               dt      0x80,0xBE,0xBE,0xBE,0xC1        ;"D" 
;               dt      0x80,0xB6,0xB6,0xBE,0xBE        ;"E" 
;               dt      0x80,0xB7,0xB7,0xBF,0xBF        ;"F"
                dt      0xFF,0xFF,0xC9,0xFF,0xFF        ;":"

Char_tbl_end
;--------
; SUBROUTINES STARTING HERE
;--------
; clear important bits of ram
;--------
Ram_init        movlw   0x07
                movwf   keys
                movlw   0x12            ;why do clocks always start
                movwf   hours           ;at 12:00 ?
                clrf    minutes
                clrf    seconds
                clrf    dot_index
                clrf    digit_index
                movlw   0xFC            ;234375 = 0x039387
                movwf   bigtick_dbl     ;0 - 0x039387 = 0xFC6C79
                movlw   0x6C
                movwf   bigtick_hi
                movlw   0x79
                movwf   bigtick_lo
                movlw   0xF0            ;3907 = 0x0F43
                movwf   sectick_hi      ;0 - 0x0F43 = 0xF0BD
                movlw   0xBD
                movwf   sectick_lo
                movlw   0x40
                movwf   period_calc
                retlw   0
;--------
; unused pins I am setting to be outputs
;--------
Port_init       movlw   0x00            ;all output, b7=unused
                tris    PORTB           ;on port b attached to LEDs
                movlw   b'00010111'     ;port a has 5 pins. I need 4 inputs
                                        ;b0=minutes, b1=10mins, b2=hours
                                        ;b3=unused, b4=rotation index
                tris    PORTA           ;on port a
                retlw   0
;--------
; get timer-based interrupts going
;--------
Timer_init      bcf     INTCON,2        ;clear TMR0 int flag
                bsf     INTCON,7        ;enable global interrupts
                bsf     INTCON,5        ;enable TMR0 int
                clrf    TMR0            ;clear timer
                clrwdt                  ;why is this needed? just do it..
                movlw   b'11011000'     ;set up timer. prescaler(bit3)bypassed 
                option                  ;send w to option. generate warning.
                clrf    TMR0            ;start timer
                retlw   0
;--------
; test for index in rotation and store period in period_dup
;--------
Check_index     movf    PORTA,w         ;get the state of port a
                xorwf   flags,w         ;compare with saved state
                andlw   b'00010000'     ;only interested in bit 4
                btfsc   STATUS,Z        ;test for edge
                retlw   0               ;not an edge, same as last
                xorwf   flags,f         ;save for next time
                btfsc   flags,4         ;test for falling edge
                retlw   0               ;must have been a rising edge
                movf    period_count,w  ;make a working copy
                movwf   period_dup      ;called period dup
                clrf    period_count    ;a fresh start for next rotation
                clrf    digit_index     ;set to first digit
                clrf    dot_index       ;first column
; calculate a period that does not dither or jitter
; period will not be changed unless new period is really different
                movf    period_calc,w
                subwf   period_dup,w    ;find difference
                btfss   STATUS,C        ;carry flag set means no borrow
                goto    Calc_period_neg ;must be other way
                sublw   2               ;allowable deviation = 3
                btfss   STATUS,C        ;borrow won't skip
                incf    period_calc     ;new value much larger than calc
                movf    period_calc,w
                movwf   period_use
                bcf     STATUS,C        ;clear carry before a rotate
                rrf     period_use,f    
                bcf     STATUS,C        ;clear carry before a rotate
                rrf     period_use,f    
                retlw   0
Calc_period_neg addlw   2               ;allowable deviation = 3
                btfss   STATUS,C        ;carry will skip
                decf    period_calc     ;no carry means it must be changed
                retlw   0
;--------
; change LED pattern based on state of digit_index and dot_index
;--------
Display_now	movlw	0x05
		xorwf	dot_index,w	;test for end of digit
		movlw	0xFF		;pattern for blank column
		btfsc	STATUS,Z
		goto	D_lookup_3	;it needs a blank
		bcf	STATUS,C	;clear carry before a rotate
		rlf	digit_index,w	;double the index because each
		addwf	PCL,f		;takes two instructions
D_10hr		swapf	hours,w	;D_10hr		
;swapf		period_calc,w
		goto	D_lookup	;what a great rush of power
D_1hr		movf	hours,w		;I feel when modifying
;D_1hr		movf	period_calc,w		;I feel when modifying
		goto	D_lookup	;the program counter
D_colon	movlw	0x0A   ;the semicolon
		goto	D_lookup
D_10min	swapf	minutes,w
		goto	D_lookup
D_1min		movf	minutes,w
		goto	D_lookup
D_colon2	movlw	0x0A   ;the semicolon
		goto	D_lookup
D_10sec	swapf	seconds,w
		goto	D_lookup
D_1sec		movf	seconds,w
		goto	D_lookup
D_nothing	retlw	0
D_lookup	andlw	b'00001111'	;strip off hi bits
		movwf	scratch		;multiply this by 5 for lookup
		addwf	scratch,f	;table base position
		addwf	scratch,f	;is this cheating?
		addwf	scratch,f	;I think not.
		addwf	scratch,f	;I think it is conserving energy!
		btfss	STATUS,Z	;test for zero
		goto	D_lookup_2	;not a zero
		movf	digit_index,f	;this is just to test/set flag
		movlw	0xFF		;this makes a blank LED pattern
		btfsc	STATUS,Z	;test if it is 10 hrs digit
		goto	D_lookup_3	;it's a leading zero
D_lookup_2	movf	dot_index,w	;get column
		addwf	scratch,w	;add it to digit base
		call	Char_tbl	;get the dot pattern for this column
D_lookup_3	movwf	PORTB		;send it to the LEDs
;		movlw	0x2C		;overhead value sub from period
;		subwf	period_use,w	;compensate for overhead and set
		movfw	period_use
		call	Delay		;width of digits with this delay
		incf	dot_index,f	;increment to the next column
		movlw	0x06		;6 columns is a digit plus space
		xorwf	dot_index,w	;next digit test
		btfss	STATUS,Z
		retlw	0		;not a new digit
		clrf	dot_index	;new digit time
		incf	digit_index,f
		retlw	0		;Display_now done.
;--------
; a short delay routine
;--------
Delay           movwf   tick
Delay_loop      decfsz  tick,f
                goto    Delay_loop      ;w is not damaged, so Delay can
                return                  ;be recalled without reloading
;--------
; test for keypress and call time adjust if needed
;--------
Check_keys      movf    PORTA,w         ;get port "a"
                xorwf   keys,w          ;compare with previous
                andlw   b'00000111'     ;only care about button pins
                btfsc   STATUS,Z        ;zero set=no buttons
                retlw   0               ;return
                xorwf   keys,f          ;store key value
                movlw   0x64            ;a fairly long delay will
                movwf   scratch         ;prevent key bounces
Key_delay       movlw   0xFF
                call    Delay
                decfsz  scratch
                goto    Key_delay
                btfss   keys,2          ;test "minutes" button
                goto    Inc_mins
                btfss   keys,1          ;test "tens" button
                goto    Inc_tens
                btfss   keys,0          ;test "hours" button
                goto    Inc_hours
                retlw   0               ;must be a glitch. yeah, right!
;--------
; increment ten minutes
;--------
Inc_tens        movlw   0x0A
                movwf   scratch         ;scratch has ten
Inc_tens_loop   call    Inc_mins
                decfsz  scratch
                goto    Inc_tens_loop   ;another minute added
                retlw   0
;--------
; increment one hour
;--------
Inc_hours       movlw   0x12
                xorwf   hours,w
                btfsc   STATUS,Z
                goto    Inc_hours_12
                movlw   0x07            ;this part gets a little sloppy
                addwf   hours,w
                movlw   0x07
                btfss   STATUS,DC
                movlw   1
                addwf   hours,f
                retlw   0
Inc_hours_12    movlw   0x01
                movwf   hours
                retlw   0
;--------
; increment the time based on flags,1 as sent by interrupt routine
; Inc_mins loop also used by time-setting routine
;--------
Keep_time       btfss   flags,5         ;the minutes flag
                goto    Keep_time2              ;no change in seconds
                bcf     flags,5         ;clear the minutes flag
                movlw   0x07            ;start incrementing time
                addwf   seconds,f       ;add 7 seconds into f
                movlw   0x06            ;'oops' decrementing time
                btfsc   STATUS,DC       ;did adding 7 cause digit carry?
                goto    Keep_time2      ;then test for an hour change
                subwf   seconds,f       ;dec 6 seconds into f
Keep_time2      btfss   flags,1         ;the minutes flag
                retlw   0               ;not this time
                bcf     flags,1         ;clear the minutes flag
                clrf    seconds ; clear the seconds & seconds timervalues
                movlw   0xF0            ;3907 = 0x0F43
                movwf   sectick_hi      ;0 - 0x0F43 = 0xF0BD
                movlw   0xBD
                movwf   sectick_lo
Inc_mins        movlw   0x07            ;start incrementing time
                addwf   minutes,w       ;add 7 minutes into w
                btfsc   STATUS,DC       ;did adding 7 cause digit carry?
                goto    Sixty_mins      ;then test for an hour change

 

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý