Det första steget är nu klart. En 16F628 kombineras med en DS2406 och en RGB-diod, 1-wirenätet ska kunna användas för att ändra färg på dioden. I dagsläget finns en enkel kod där det enbart växlas mellan de tre grundfärgerna, detta är tänkt att utvecklas med fler färger.
Schema:

Detta skulle kunna förenklas genom att använda en mindre Pic som tex 12F629. Ytterligare en förenkling hårdvarumässigt vore att implementera 1-wire-slav-kod i processorn, något som ska vara möjligt med en AVR-processor. Det finns även utvecklingsmöjligheter för styrningen, eftersom en dator kontrollerar 1-wire nätet finns möjligheter som tex att låta diodens färg bero på utetemperaturen. En tänkt fortsättning är även att komplettera med tre mosfet så att större diodarrangemang kan styras (tex en RGB-list).
Kod för Mplab:
Kod: Markera allt
;---------------------------------------------------------------------------------------------
; HEADER:
;---------------------------------------------------------------------------------------------
LIST P=16f628a
RADIX DEC
INCLUDE "p16f628a.inc"
;Program Configuration
__CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTOSC_OSC_NOCLKOUT
;---------------------------------------------------------------------------------------------
; EQUATES:
;---------------------------------------------------------------------------------------------
#define Clock_Freq 8000000
#include "wait.mac"
#define REDLED PortAShadow, 0
#define BLUELED PortAShadow, 1
#define GREENLED PortAShadow, 2
#define redled PortAShadow, 4
STARTOFRAM equ 0x20 ;First Usable RAM Location for 16f628
ENDOFBANK0 equ 0x6F ;Last Usable RAM Location for 16f628
FIXEDAREA equ 0x70 ;Start of shared memory between banks
BANK1RAM equ 0xA0 ;Start of Bank 1 RAM
ENDOFBANK1 equ 0xEF ;End of Bank 1 RAM
cblock STARTOFRAM
;
; Application specific variables
;
DutyRed ;Duty cycle of Red LED
DutyGreen ;
DutyBlue
DutyCount ;Counter that indicates which time unit of period we are on
RedDelta
GreenDelta
BlueDelta
PortAShadow
tempone
temptwo
cnt ;counter
pclval ;lookup table offset
endc
cblock FIXEDAREA
;
; ISR Register Save Areas
;
INT_FLAGS
W_TEMP
STATUS_TEMP
FSR_TEMP
PCLATH_TEMP
endc
;---------------------------------------------------------------------------------------------
; START:
;---------------------------------------------------------------------------------------------
org 0x000
goto Start
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
org 0x004
; Interrupt handler right here
movwf W_TEMP ;Save everything
swapf STATUS, W
movwf STATUS_TEMP
movfw FSR
movwf FSR_TEMP
movfw PCLATH
movwf PCLATH_TEMP
bcf STATUS, RP0 ;Back to Bank 0 to make sure otherwise we clobber OPTION reg when reloading TMR0
;Timer2 interrupt?
btfsc PIR1, TMR2IF ;Is it a TMR2 interrupt
goto TMR2Int ; Yes
;RB0 change?
BTFSC INTCON, INTF
goto intRB0
;No legal interrupt, exit
goto IntExit
;-----------------------------------------------------------------------------
;
; ISR routines
;
;-----------------------------------------------------------------------------
intRB0
bcf PIE1 & 0x07F, TMR2IE ; Turn off TMR2 ints
bcf INTCON, INTE ;disable RB0 interrupt
bsf redled ;Indicate RB0 int
;cnt = 0001 1 4
incf cnt ;Increase counter ; 0010 2 0101 5 1000 8 1011 11
incf cnt ;Increase counter ; 0011 3 0110 6 1001 9 1100 12
incf cnt ;Increase counter ; 0100 4 0111 7 1010 10 1101 13
movlw b'00001010'
xorwf cnt, W ;Check counter value
btfss STATUS, Z
goto cont
clrf cnt
incf cnt
cont
bcf INTCON, INTF ;clear mismatch
bsf INTCON, INTE ;enable RB0 interrupt
bsf PIE1 & 0x07F, TMR2IE ;Turn on TMR2 ints
goto IntExit
;------------------------------------------------------
;
; Timer 2 used for PWM duty cycle
;
; There are 256 time units in a full period. Thus the duty cycle has 256 possible
; settings from 0 to 100%. Each time unit is 50uS long thus a full period is 12.8mS. This gives
; a refresh rate of about 80Hz (78.12)
;
TMR2Int
incf DutyCount, F ; gives 256 levels of intensity
movfw DutyRed
subwf DutyCount, W
btfsc STATUS, C
goto _RedOff
_RedOn
bsf REDLED
goto _ckgreen
_RedOff
bcf REDLED
; fall thru ok
_ckgreen
movfw DutyGreen
subwf DutyCount, W
btfsc STATUS, C
goto _GreenOff
_GreenOn
bsf GREENLED
goto _ckblue
_GreenOff
bcf GREENLED
; fall thru ok
_ckblue
movfw DutyBlue
subwf DutyCount, W
btfsc STATUS, C
goto _BlueOff
_BlueOn
bsf BLUELED
goto _ckdone
_BlueOff
bcf BLUELED
_ckdone
movfw PortAShadow
movwf PORTA
bcf PIR1, TMR2IF ; clear the interrupt flag
; FALL THRU TO INTEXIT goto IntExit
IntExit
movfw PCLATH_TEMP
movwf PCLATH
movfw FSR_TEMP
movwf FSR
swapf STATUS_TEMP, W
movwf STATUS
swapf W_TEMP, F
swapf W_TEMP, W
retfie
;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
;
;
; Main level code begins here
;
;
Start
bsf STATUS, RP0 ;Switch to Bank 1
movlw b'00100001' ;Define I/O on Port B, RB0=in/int
movwf TRISB & 0x7F
bcf OPTION_REG, NOT_RBPU ;Activate soft pull-up
bcf OPTION_REG, INTEDG ;RB0/int interrupt on falling edge
bsf INTCON, INTE ;RB0/int interrupt enable
movlw b'00000000'
movwf TRISA
bcf STATUS, RP0 ;Back to Bank 0
clrf PORTA ;Initialize PORTA
clrf PORTB ;Initialize PORTB
;Reset variables
clrf DutyRed
clrf DutyGreen
clrf DutyBlue
clrf DutyCount
clrf PortAShadow
;Init timer2, used for PWM
call TMR2Init
bsf INTCON, PEIE ; Enable peripheral interrupts
bsf INTCON, GIE ; Turn on GLOBAL Interrupts
; Start off with LED off and not doing anything
movlw d'0' ;
movwf RedDelta
movlw d'0' ;
movwf GreenDelta
movlw d'0' ;
movwf BlueDelta
movlw d'0' ; con 5
movwf DutyRed
movlw d'0' ; con 7
movwf DutyGreen
movlw d'0' ; con 6
movwf DutyBlue
clrf cnt ;Reset counter
incf cnt ;and add 1
loop
;Fetch color values that depends on counter
;Each button press creates an interrupt which increases tre counter
movf cnt,w ; Put counter to look up into w.
movwf pclval
CALL Lookup ; Call the table.
MOVWF DutyRed
;Next value
incf pclval
movf pclval,w ; Put number to look up into w.
CALL Lookup ; Call the table.
MOVWF DutyGreen
;Third value
incf pclval
movf pclval,w ; Put number to look up into w.
CALL Lookup ; Call the table.
MOVWF DutyBlue
;Loop
goto loop
;
;---------------------------------------------------------------------------------------------
;
TMR2Init
; Setup of TMR2 (Based on 8Mhz clock)
; (8 Mhz clock)
; Fill in T2CON
movlw b'00000001' ; TMR2 timer stopped, prescale /4, no post scale
; |||||||+-------------- T2CKPS0
; ||||||+--------------- T2CKPS1
; |||||+---------------- TMR2ON
; ||||+----------------- TOUTPS0
; |||+------------------ TOUTPS1
; ||+------------------- TOUTPS2
; |+-------------------- TOUTPS3
; +--------------------- Unused
movwf T2CON
; Clear the interrupt flag
bcf PIR1, TMR2IF
; Enable Peripheral interrupts
; bsf INTCON, PEIE
; Set Period and turn on the interrupts
bsf STATUS, RP0 ; Select BANK 1
movlw d'24' ; Set period to 12.5mS
movwf PR2 & 0x07F
bsf PIE1 & 0x07F, TMR2IE ; Turn on TMR2 ints
bcf STATUS, RP0 ; Select BANK 0
; Enable the timer
clrf TMR2
bsf T2CON, TMR2ON ; Start counting
return
Lookup ADDWF PCL ; Jump to entry spec'd by w.
RETLW d'0' ;dummy
RETLW d'255'
RETLW d'000' ; 4, 5, 6
RETLW d'000'
RETLW d'000'
RETLW d'000' ; 7, 8, 9
RETLW d'255'
RETLW d'0' ; 0, 1, 2, 3
RETLW d'255'
RETLW d'0'
end