Blink8LED
When asked on the forum:- To do the equivalent of the code below with each LED blinking at a different rate - except that all 8 LEDs must blink concurrently.
PORTB = 0
TRISB = 0
MAIN:
LOOP1:
TOGGLE PORTB.0
PAUSE 500
GOTO LOOP1
LOOP2:
TOGGLE PORTB.1
PAUSE 220
GOTO LOOP2
LOOP3:
TOGGLE PORTB.2
PAUSE 380
GOTO LOOP1
LOOP4:
TOGGLE PORTB.3
PAUSE 750
GOTO LOOP4
LOOP5:
TOGGLE PORTB.4
PAUSE 170
GOTO LOOP5
LOOP6:
TOGGLE PORTB.5
PAUSE 400
GOTO LOOP6
LOOP7:
TOGGLE PORTB.6
PAUSE 620
GOTO LOOP7
LOOP8:
TOGGLE PORTB.7
PAUSE 130
GOTO LOOP8
GOTO MAIN
Darrel responded with this little Gem:
I've always said PAUSE is the worst statement in the BASIC language. It got me again.
Here's a version that should compensate ... It uses the CCP module in "Compare" mode to create a precise 10mS interval. So when you give a delay value of 50, it actually takes 500mS, on the nose.
DEFINE OSC 4
DEFINE BLINKYFREQ 100 ; 10mS periods
DATA 50,22,38,75,17,40,62,13 ; default periods for each Output
;----------------------------------------------------------------
CCPR1val CON EXT : @CCPR1val = (OSC*1000000/4)/ BLINKYFREQ
CCPR1 VAR WORD EXT : @CCPR1 = CCPR1L
Timer1 VAR WORD EXT : @Timer1 = TMR1L
CCPIF VAR PIR1.2
LoopLED VAR BYTE[8]
LoopCON VAR BYTE[8]
x VAR BYTE
;----[Initialize]------------------------------------------------
FOR x = 0 to 7 ; load the periods from EEPROM
READ x, LoopCON(x)
NEXT X
;-- setup CCP1 and Start Timer1 --
CCPR1 = CCPR1val ; set compare value
CCP1CON = %00001011 ; compare mode, special event
Timer1 = 0 ; clear Timer1
T1CON.0 = 1 ; start Timer1
TRISB = 0 ; PORTB all OUTPUT
;----[Main Program Loop]----------------------------------------
Main:
x = (x + 1) // 8
PORTB.0(x) = !(LoopLED(x) < LoopCON(x))
LoopLED(x) = (LoopLED(x) + 1) // (LoopCON(x) << 1)
IF x != 7 THEN Main
Waiting: IF !CCPIF THEN Waiting
CCPIF = 0
GOTO Main
Code:
'****************************************************************
'* Name : HWTX.BAS *
'* Author : Henrik Olsson *
'* Notice : Copyright (c) 2010 Henrik Olsson 2010 *
'* : All Rights NOT Reserved - use as you see fit. *
'* Date : 2010-11-16 *
'* Version : 0.0 *
'* Notes : Test for interrupt based USART transmit using *
'* : DT_ints-18 on a 18F4520 *
'****************************************************************
DEFINE LOADER_USED 1 ' We're using a bootloader
DEFINE OSC 20 ' 20Mhz x-tal is used
DEFINE HSER_BAUD 38400 ' Baudrate is 38400
CMCON = 7 ' Comparators OFF
ADCON1 = %00001111 ' No analog inputs
TRISC.7 = 1 ' RxPin is input
TRISC.6 = 0 ' TxPin is output
TRISB.0 = 1 ' PortB.0 is input
TxBuffer VAR BYTE[128] ' Transmit buffer array.
TxPointer VAR Byte ' Pointer into the above array
INCLUDE "DT_INTS-18.bas" ' Include Darrels interrupt engine.
INCLUDE "ReEnterPBP-18.bas" ' And the stub needed for interrupts in PBP
ASM ; Set up the USART transmit interrupt.
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TX_INT, _USART_TX, PBP, no
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
Boot:
HSEROUT ["Program start",13] ' A dummy HSEROUT here to init the USART and show we're alive.
' Now load the array with something we want to send. The string is, in this case, terminated with a CR (13).
ArrayWrite TxBuffer,["This is the TX Array Buffer and we're sending it with an interupt based routine",13]
Main:
If PortB.0 = 0 then ' PortB.0 going low is what
TxPointer = 0 ' Initialize pointer to beginning of array
@ INT_ENABLE TX_INT ; Enable USART TX interrupt
Pause 100 ' Simple debounce for the button
ENDIF
Goto Main ' And do it again.
USART_TX:
TXREG = TxBuffer[TxPointer] ' Load character from array into USART TX register
If TxBuffer[TxPointer] = 13 then ' If that character was a CR we're done so we.....
@ INT_DISABLE TX_INT ; ...disable the any further USART TX interrupts.
ELSE ' If the character was not a CR we.....
TxPointer = TxPointer + 1 ' ...increase prepare to send the next character.
ENDIF
@ INT_RETURN
Page last modified on March 24, 2018, at 11:38 PM
