Interrupted LED flashing

published: 14 June 2019 / updated 22 June 2019

Lire cette page en français

 


Blinking of an LED

This topic has already been discussed here: ARDUINO ports: turning on an LED.

Here the word that manages this blink:

: clignote ( ---)       \ boucle de clignotement 
    init-ddrb 
    begin 
        led13-on   500 ms 
        led13-off  500 ms 
    key? until ; 

The disadvantage of this program, purely didactic, is that it can not do only that. And immobilize an ARDUINO card just to flash an LED, that's a real mess! Because in the loop begin .. until we manage a delay 500 milliseconds, a delay that prevents any other action.

LED flashing on ARDUINO board

By properly handling interrupts, we will be able to release this machine time fruitfully.

Turn LED on and off

Here is the minimum code for managing the LED connected to connector 13:

\ Port Register Definitions 
$24 constant DDRB       \ Direction Data Register PORT B 
$25 constant PORTB      \ data in PORT B 
 
%10000000 constant pLED \ mask for LED connector 13 (onboard LED) 
 
: toggleLed   ( --- )   \ toggle LED off if LED is on, and inverse... 
  PORTB c@              \ get LED status 
  pLED xor              \ invert bit x0000000 
  PORTB c!              \ turn ON or OFF led 
; 

You can test this code immediately after compiling it:

pLED DDRB c!            \ positionne DDRB en sortie pour led 13 
toggleLed               \ si LED éteinte, elle s'allume 
toggleLed               \ si LED allumée, elle s'éteint 

No electrical diagram. We will only manage this LED already mounted on the ARDUINO board.

The TIMER interrupt

A timer is a TCNTx register in the microcontroller. It is incremented each time an impulse is received clock. This clock signal may be specific to the microcontroller or external. A timer is a counter capable of counting the time that elapses.

The timer register we are interested in, TCNT3 has 8 bits. He is able to count from 0 to 255 (from 00 to FF in hexadecimal). When it reaches 255, an additional clock tick makes it pass to 256, but since it is impossible, this register having only 8 bits, it returns to zero. The TIFRx register experiences an overflow, which causes a special bit to be set in 1 the control register associated with the timer.

We define:

$91 constant TCCR3B     \ Timer/Counter3 Control Register B 
$71 constant TIMSK3     \ Timer/Counter3 Interrupt Mask Register 
36 constant ovf3Ivec    \ interrupt vector 

Then we define a variable counter:

\ Counter for timer overflows 
variable counter 

With each overflow of the TIMER interrupt, this variable will be incremented:

\ The interrupt routine 
: t3OverflowIsr ( ---) 
    1 counter +!                    \ increment counter 
;i 

 WARNING : the word t3OverflowIsr should not be performed in interpretation. You will notice that it ends with ; i while "colon" definitions always end with ;

We prepare the initialization of the TIMER interrupt:

: irqOvf3Init ( ---) 
    ['] t3OverflowIsr ovf3Ivec int! \ Store the interrupt vector 
    1 TCCR3B mset                   \ Activate counter 3 
    1 TIMSK3 mset                   \ Activate timer3 overflow interrupt 
; 

Et voilà! On peut tester notre interruption:

$80 DDRB c!             \ init DDRB in OUTPUT mode 
irqOvf3Init             \ init TIMER interrupt 
counter @ .             \ fetch counter value and display it 
#1000 ms                \ wait 1 sec. 
counter @ .             \ fetch counter value 

If the value of counter has evolved, we have confirmation that the TIMER interrupt is operational.

We repeat our definition:

: t3OverflowIsr ( ---) 
    1 counter +!                    \ increment counter 
;i 

We will add the blinking management of our LED:

: t3OverflowIsr ( ---) 
    1 counter +!                    \ increment counter 
    counter @ 500 >                 \ test if counter up to 500 
    if     
        0 counter !                 \ reset counter 
        toggleLed                   \ toggle LED on or off 
    then 
;i 

Recompile the entire program. Then execute this:

$80 DDRB c!             \ init DDRB in OUTPUT mode 
irqOvf3Init             \ init TIMER interrupt 

Look at the LED on the ARDUINO board. She's blinking! There is nothing else to do...

Oh yes!

If you recompile the program, you must first execute this new word: irqOvf3Dis:

: irqOvf3Dis ( ---)                 \ Disable interrupt 
    1 TIMSK3 mclr 
; 

The complete listing is available here: Clignotement LED par interruption timer 03