list p=18F1320
include <p18F1320.inc>
CONFIG OSC = INTIO2, WDT = OFF, LVP = OFF, DEBUG = ON
LED macro x,y ; MACRO LED <PORTA>, <TRISA>
movlw x
movwf LATA ; LATA = x
movlw y
movwf TRISA ; TRISA = y
endm ; end macro
org 0 ; reset vector
bsf ADCON1, 0 ; make RA0 digital
START
LED1 LED b'00000001', b'10111110' ; LED <PORTA>, <TRISA>
LED3 LED b'01000000', b'00111111'
LED5 LED b'10000000', b'01111110'
goto START ; loop forever
END
Isn't that fun? Took me a few minutes to figure out what was going on there too.UTMonkey said:LED Mux got me confused at first but the penny has dropped.
list p=18F1320
include <p18F1320.inc>
CONFIG OSC = INTIO2, WDT = OFF, LVP = OFF, DEBUG = ON
cblock 0x00
loop1
endc
LED macro x,y ;MACRO LED <PORTA>, <TRISA>
movlw x
movwf LATA ;LATA = x
movlw y
movwf TRISA ;TRISA = y
call delay ;delay just long enough to multiplex LEDs so
;they all look like they're on together
endm ;end macro
org 0 ;reset vector
bsf ADCON1,0 ;make RA0 digital
START
LED1 LED b'00000001',b'10111110' ;LED <PORTA>, <TRISA>
LED3 LED b'01000000',b'00111111'
LED5 LED b'10000000',b'01111110'
goto START ;loop forever
delay movlw 0x0e
movwf loop1
inner decfsz loop1,F
goto inner
return
END
Yes they are. That's how I did the multiplexing for my LED cube.blueroomelectronics said:Timer interrupts are very handy for display refreshing.
Oh geez, I'm embarrassed.blueroomelectronics said:I was on your site Futz, nice bunch of bots there.
list p=18F1320
include <p18F1320.inc>
CONFIG OSC=INTIO2,WDT=OFF,MCLRE=ON,LVP=OFF
cblock 0x00
d1,d2,d3,lednum,ledcount
endc
org 0x0000
goto init
;*************************
;Interrupt Service Routine
org 0x0008
ISR tstfsz lednum ;any LEDs on?
goto display ;yes, go display them
clrf LATA ;no, turn em all off
goto timdone ;and we're done
display incf ledcount,F ;increment led selector
movlw 0x01 ;is it 1?
cpfseq ledcount
goto led_2 ;no, go to led_2
led_1 btfss lednum,1 ;LED 1 on?
goto timdone ;no, we're done
bsf LATA,0 ;yes, display it
bcf LATA,6
movlw b'10000000'
movwf TRISA
goto timdone ;done
led_2 movlw 0x02
cpfseq ledcount
goto led_3
btfss lednum,2
goto timdone
bcf LATA,0
bsf LATA,6
movlw b'10000000'
movwf TRISA
goto timdone
led_3 movlw 0x03
cpfseq ledcount
goto led_4
btfss lednum,3
goto timdone
bsf LATA,6
bcf LATA,7
movlw b'00000001'
movwf TRISA
goto timdone
led_4 movlw 0x04
cpfseq ledcount
goto led_5
btfss lednum,4
goto timdone
bcf LATA,6
bsf LATA,7
movlw b'00000001'
movwf TRISA
goto timdone
led_5 movlw 0x05
cpfseq ledcount
goto led_6
btfss lednum,5
goto timdone
bcf LATA,0
bsf LATA,7
movlw b'01000000'
movwf TRISA
goto timdone
led_6 btfss lednum,6 ;LED 6 on?
goto clearit ;no, we're done
bsf LATA,0 ;yes, display it
bcf LATA,7
movlw b'01000000'
movwf TRISA
clearit clrf ledcount ;reset led multiplex counter
timdone bcf INTCON,TMR0IF ;clear TMR0 flag
quit retfie FAST ;return
;*************************
init bsf OSCCON,IRCF2 ;set to 8MHz clock
bsf OSCCON,IRCF1
bsf OSCCON,IRCF0
clrf TRISA ;make ports all outs
clrf TRISB
clrf LATA ;and zero them
clrf LATB
setf ADCON1 ;make PORTA all digital
clrf ledcount
;init interrupts
movlw b'11001111' ;set up & enable Timer0
movwf T0CON
bcf RCON,IPEN ;disable priority interrupts
bsf INTCON,TMR0IE ;enable TIMER0 Interrupt
bsf INTCON,PEIE ;enable peripheral interrupts
bsf INTCON,GIE ;enable interrupts
main movlw b'00101010' ;turn on LEDs 1, 3 and 5
movwf lednum
call delay
clrf lednum ;turn em off again
call delay
goto main ;go again
delay movlw 0x07 ;half second blink delay
movwf d1
movlw 0x2F
movwf d2
movlw 0x03
movwf d3
delay_0 decfsz d1,F
goto $+6
decfsz d2,F
goto $+6
decfsz d3,F
goto delay_0
return
END
main movlw b'00101010' ;turn on LEDs 1, 3 and 5
movwf lednum
call delay
movlw b'01010100' ;turn on LEDs 2, 4 and 6
movwf lednum
call delay
clrf lednum ;turn em off again
call delay
goto main ;go again
main movlw b'00000010' ;turn on LED 1
movwf lednum
roll rlncf lednum,F
call delay
goto roll ;go again
main movlw 0x02 ;turn on LED 1
movwf lednum
roll incf lednum,F
movlw 0x7f ;is lednum > $7e?
cpfseq lednum
goto rollcnt ;no, continue
movlw 0x01 ;yes, start over
movwf lednum
rollcnt call delay
rollagn goto roll ;go again
That's what it's doing in the above program. You just set what LEDs you want on or off and have your program go do something else. The LED's refresh constantly and automatically, every time that timer rolls over, no matter what your program is doing (unless it's disabling interruptsUTMonkey said:Could the interrupt service handle ALL the LED work, leaving the main code to do something else?
Look very carefully at the Junebug schematic, what pins those LEDs connect to and how they're all connected. Do it while studying the code. You'll soon see what's going on. It's confusing at first, but not so very complex.UTMonkey said:I suppose I still have the question, why do all lamps come on? is this a shortcoming (if thats the right word) of charlieplexing? can someone explain the phenomenon?
I believe the default internal clock speed is 31.25KHz. That's why I bumped it up in my code to 8MHz. 31.25KHz is too slow to do the interrupt thing.One last question, what "speed" does my code run at?
They all come on because you're just not going fast enough. They're probably coming on in my interrupt version, but so briefly that you can't see them.UTMonkey said:I suppose I still have the question, why do all lamps come on? is this a shortcoming (if thats the right word) of charlieplexing? can someone explain the phenomenon?
list p=18F1320
include <p18F1320.inc>
CONFIG OSC = INTIO2, WDT = OFF, LVP = OFF
cblock 0x00
loop1
endc
LED macro x,y ;MACRO LED <PORTA>, <TRISA>
movlw x
movwf LATA ;LATA = x
movlw y
movwf TRISA ;TRISA = y
call delay ;delay just long enough to multiplex LEDs so
;they all look like they're on together
endm ;end macro
org 0x00 ;reset vector
init bsf OSCCON,IRCF2 ;set to 8MHz clock
bsf OSCCON,IRCF1
bsf OSCCON,IRCF0
setf ADCON1 ;make RA0 digital
clrf TRISA
clrf TRISB
clrf LATA
clrf LATB
START
LED1 LED b'00000001',b'10000000' ;LED <PORTA>, <TRISA>
led2 LED b'00000000',b'00000000' ;all off
LED3 LED b'01000000',b'00000001'
led3 LED b'00000000',b'00000000'
LED5 LED b'10000000',b'01000000'
led6 LED b'00000000',b'00000000'
goto START ;loop forever
delay movlw 0xff
movwf loop1
inner decfsz loop1,F
goto inner
return
END
Timer0 does that.blueroomelectronics said:You need to call it 50Hz * 6 (LEDs) so 300 times a second is about right.
lednumThen you need shadow register (6 bits to hold the LED state, this is the only register you should use within your main code)
ledcountand a modulo 6 counter to determine which LED to service.
LED macro x,y ; MACRO LED <PORTA>, <TRISA>
movlw x
movwf LATA ; LATA = x
movlw y
movwf TRISA ; TRISA = y
endm ; end macro
org 0 ; reset vector
bsf ADCON1, 0 ; make RA0 digital
bsf TRISB, 0
START
LED3 LED b'01000000', b'00111111'
LED5 LED b'10000000', b'01111110'
goto START
Oh, that explains it!UTMonkey said:As the MACRO indicates the first thing that happens is that LATA changes from b'01000000' to b'10000000', this means effectively that the path of current changes, from originally flowing through LED3 to flowing back to RA6 through LED4 (making it light) before getting to the TRISA b'01111110' which changes the outputs.
This is only brief, but enough to make LED 4 light.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?