8051 Interrupts in Turbo51

Pascal Compiler for 8051 Microcontrollers

Interrupts are procedures declared with the Interrupt directive and interrupt address. In this example Timer0 is a constant defined in the System unit. For any procedure we can optionally define register bank to be used in this procedure by Using and number of bank (0 to 3) or we can define bank independent procedure with UsingAny. Such procedure can be called from any interrupt.

Warning: make sure that all varables that might be changed in the interrupt procedure are marked with the Volatile directive. This will tell the compiler that their value can be modified outside of current program flow so many optimizations on these varables will not be performed since their value is not known. Do not place in an interrupt routine time consuming operations like floating point operations, file I/O, string manipulations, large memory moves, etc.

Example of interrupt declaration:

Program InterruptDemo;

Const
  Const1ms = - 22118400 div 12 div 1000;

Var
  RS485_TX: Boolean absolute P0.3;
  RX_Led:   Boolean absolute P0.4;
  TX_Led:   Boolean absolute P0.5;

  BlinkTimer:         Word; Volatile;
  KeyProcessingTimer: Word; Volatile;
  DelayTimer:         Word; Volatile;
  RS485_Timer:        Byte; Volatile;
  RX_LedTimer:        Byte; Volatile;
  TX_LedTimer:        Byte; Volatile;

Procedure TimerProc; Interrupt Timer0; Using 2; { 1 ms interrupt }
 begin
   TL0 :=  Lo (Const1ms);
   TH0 :=  Hi (Const1ms);

   Inc (BlinkTimer);
   Inc (KeyProcessingTimer);

   If DelayTimer <> 0 then Dec (DelayTimer);

   If RS485_Timer <> 0 then Dec (RS485_Timer) else RS485_TX := False;
   If RX_LedTimer <> 0 then Dec (RX_LedTimer) else RX_Led := False;
   If TX_LedTimer <> 0 then Dec (TX_LedTimer) else TX_Led := False;
 end;

begin
 { Some code }
end.

Compiled program above looks like this:

; Turbo51 version 0.1.3.10, Copyright 2000 - 2011 Igor Funa

$REGISTERBANK (0, 2)

_CODE         SEGMENT  CODE
_DATA         SEGMENT  DATA

              EXTRN    IDATA (StackStart)

; Program InterruptDemo;
; 
; Const

RSEG _CONST

;   Const1ms = - 22118400 div 12 div 1000;
; 
; Var
;   RS485_TX: Boolean absolute P0.3;
RS485_TX                        BIT      P0.3

;   RX_Led:   Boolean absolute P0.4;
RX_Led                          BIT      P0.4

;   TX_Led:   Boolean absolute P0.5;
TX_Led                          BIT      P0.5

; 
;   BlinkTimer:         Word; Volatile;

RSEG _DATA

BlinkTimer:                     DS       2

;   KeyProcessingTimer: Word; Volatile;
KeyProcessingTimer:             DS       2

;   DelayTimer:         Word; Volatile;
DelayTimer:                     DS       2

;   RS485_Timer:        Byte; Volatile;
RS485_Timer:                    DS       1

;   RX_LedTimer:        Byte; Volatile;
RX_LedTimer:                    DS       1

;   TX_LedTimer:        Byte; Volatile;
TX_LedTimer:                    DS       1

; 
; Procedure TimerProc; Interrupt Timer0; Using 2; { 1 ms interrupt }


CSEG AT $000B

USING 2

TimerProc:
;  begin
              PUSH      PSW
              MOV       PSW, #$10
              PUSH      ACC

;    TL0 :=  Lo (Const1ms);
              MOV       TL0, #$CD

;    TH0 :=  Hi (Const1ms);
              MOV       TH0, #$F8

; 
;    Inc (BlinkTimer);
              INC       BlinkTimer
              MOV       A, BlinkTimer
              JNZ       L_0020
              INC       BlinkTimer+1
L_0020:

;    Inc (KeyProcessingTimer);
              INC       KeyProcessingTimer
              MOV       A, KeyProcessingTimer
              JNZ       L_0028
              INC       KeyProcessingTimer+1
L_0028:

; 
;    If DelayTimer <> 0 then Dec (DelayTimer);
              MOV       A, DelayTimer+1
              ORL       A, DelayTimer
              JZ        L_0037
              DEC       DelayTimer
              MOV       A, DelayTimer
              CJNE      A, #-1, L_0037
              DEC       DelayTimer+1
L_0037:

; 
;    If RS485_Timer <> 0 then Dec (RS485_Timer) else RS485_TX := False;
              MOV       A, RS485_Timer
              JZ        L_003F
              DEC       RS485_Timer
              SJMP      L_0041
L_003F:
              CLR       P0.3
L_0041:

;    If RX_LedTimer <> 0 then Dec (RX_LedTimer) else RX_Led := False;
              MOV       A, RX_LedTimer
              JZ        L_0049
              DEC       RX_LedTimer
              SJMP      L_004B
L_0049:
              CLR       P0.4
L_004B:

;    If TX_LedTimer <> 0 then Dec (TX_LedTimer) else TX_Led := False;
              MOV       A, TX_LedTimer
              JZ        L_0053
              DEC       TX_LedTimer
              SJMP      L_0055
L_0053:
              CLR       P0.5
L_0055:

;  end;
              POP       ACC
              POP       PSW
              RETI


CSEG AT $0000

              AJMP     InterruptDemo


RSEG _CODE

InterruptDemo:
; 
; begin
              MOV       SP, #StackStart-1

;  { Some code }
; end.
L_0006:
              SJMP      L_0006

RSEG _CONST


              END

Copyright © 2024 Igor Funa. All Rights Reserved. Terms, Conditions and Privacy policy