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