Turbo51 Files

Pascal Compiler for 8051 Microcontrollers

Turbo51 supports files - a general framework for IO handling. However, you have to provide the low level IO procedures. Files can be untyped, typed (File of SomeType) and of type Text (ASCII text terminated with line feed #10 character). The following procedures support files:

  • Assign
  • Read
  • ReadLn
  • Write
  • WriteLn
  • BlockRead
  • BlockWrite

Here is a simple example of calculator using files:

Program Files;

// Should work on any 8051 microcontroller

Const
 Oscillator = 22118400;
 BaudRate   = 19200;
 BaudRateTimerValue = Byte (- Oscillator div 12 div 32 div BaudRate);

Var SerialPort: Text;
    Num1, Num2: LongInt;

Procedure WriteToSerialPort; Assembler;
Asm
  CLR   TI
  MOV   SBUF, A
@WaitLoop:
  JNB   TI, @WaitLoop
end;

Function ReadFromSerialPort: Char;
Var ByteResult: Byte absolute Result;
begin
  While not RI do;
  RI := False;
  ByteResult := SBUF;

{ Echo character }

  Asm
    MOV    A, Result
    LCALL  WriteToSerialPort
  end;
end;


Procedure Init;
begin
  TL1  := BaudRateTimerValue;
  TH1  := BaudRateTimerValue;
  TMOD := %00100001;    { Timer1: no GATE, 8 bit timer, autoreload }
  SCON := %01010000;    { Serial Mode 1, Enable Reception }
  TI   := True;         { Indicate TX ready }
  TR1  := True;         { Enable timer 1 }
end;

begin
  Init;
  Assign (SerialPort, ReadFromSerialPort, WriteToSerialPort);

  Writeln (SerialPort, 'Turbo51 IO file demo');
  Repeat
    Write   (SerialPort, 'Enter first number: ');
    Readln  (SerialPort, Num1);
    Write   (SerialPort, 'Enter second number: ');
    Readln  (SerialPort, Num2);
    Writeln (SerialPort, Num1, ' + ', Num2, ' = ', Num1 + Num2);
  until False;
end.

Compiled code looks like this:

; Turbo51 version 0.1.3.10, Copyright 2000 - 2011 Igor Funa

$REGISTERBANK (0)

_CODE         SEGMENT  CODE
_CONST        SEGMENT  CODE
_DATA         SEGMENT  DATA

              EXTRN    DATA  (CurrentIO)
              EXTRN    IDATA (StackStart)

              EXTRN    CODE  (sysWriteStr_CODE)
              EXTRN    CODE  (sysWriteLine)
              EXTRN    CODE  (sysReadLongInt)
              EXTRN    CODE  (sysStore_Long0_To_IDATA)
              EXTRN    CODE  (sysReadLine)
              EXTRN    CODE  (sysLoad_Long0_From_IDATA)
              EXTRN    CODE  (sysPushLongIntBCD)
              EXTRN    CODE  (sysWriteDecimalPushedBytes)
              EXTRN    CODE  (sysLoad_Long1_From_IDATA)
              EXTRN    CODE  (sysLongAddition)

; Program Files;
; 
; // Should work on any 8051 microcontroller
; 
; Const

RSEG _CONST

;  Oscillator = 22118400;
;  BaudRate   = 19200;
;  BaudRateTimerValue = Byte (- Oscillator div 12 div 32 div BaudRate);
; 
; Var SerialPort: Text;

RSEG _DATA

SerialPort:                     DS       4

;     Num1, Num2: LongInt;
Num1:                           DS       4
Num2:                           DS       4

; 
; Procedure WriteToSerialPort; Assembler;


RSEG _CODE

USING 0

WriteToSerialPort:
; Asm
;   CLR   TI
              CLR       SCON.1

;   MOV   SBUF, A
              MOV       SBUF, A

; @WaitLoop:
L_00B0:
;   JNB   TI, @WaitLoop
              JNB       SCON.1, L_00B0

; end;
              RET

; 
; Function ReadFromSerialPort: Char;

RSEG _DATA

ReadFromSerialPort_Result:      DS       1

; Var ByteResult: Byte absolute Result;
ByteResult                      EQU      ReadFromSerialPort_Result


RSEG _CODE

ReadFromSerialPort:
; begin
;   While not RI do;
L_00B4:
              JNB       SCON.0, L_00B4

;   RI := False;
              CLR       SCON.0

;   ByteResult := SBUF;
              MOV       ReadFromSerialPort_Result, SBUF

; 
; { Echo character }
; 
;   Asm
;     MOV    A, Result
              MOV       A, ReadFromSerialPort_Result

;     LCALL  WriteToSerialPort
              LCALL     WriteToSerialPort

;   end;
; end;
              MOV       A, ReadFromSerialPort_Result
              RET

; 
; 
; Procedure Init;

Init:
; begin
;   TL1  := BaudRateTimerValue;
              MOV       TL1, #$FD

;   TH1  := BaudRateTimerValue;
              MOV       TH1, #$FD

;   TMOD := %00100001;    { Timer1: no GATE, 8 bit timer, autoreload }
              MOV       TMOD, #$21

;   SCON := %01010000;    { Serial Mode 1, Enable Reception }
              MOV       SCON, #$50

;   TI   := True;         { Indicate TX ready }
              SETB      SCON.1

;   TR1  := True;         { Enable timer 1 }
              SETB      TCON.6

; end;
              RET

RSEG _CONST

C_0354:                         DB        20, 'Turbo51 IO file demo'
C_0369:                         DB        20, 'Enter first number: '
C_037E:                         DB        21, 'Enter second number: '
C_0394:                         DB        3, ' + '
C_0398:                         DB        3, ' = '


CSEG AT $0000

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

;   Init;
              LCALL     Init

;   Assign (SerialPort, ReadFromSerialPort, WriteToSerialPort);
              MOV       SerialPort, #LOW  (WriteToSerialPort)
              MOV       SerialPort+1, #HIGH (WriteToSerialPort)
              MOV       SerialPort+2, #LOW  (ReadFromSerialPort)
              MOV       SerialPort+3, #HIGH (ReadFromSerialPort)

; 
;   Writeln (SerialPort, 'Turbo51 IO file demo');
              MOV       CurrentIO, #LOW  (WriteToSerialPort)
              MOV       CurrentIO+1, #HIGH (WriteToSerialPort)
              MOV       DPTR, #C_0354
              MOV       R6, #0
              LCALL     sysWriteStr_CODE
              LCALL     sysWriteLine

;   Repeat
L_0023:
;     Write   (SerialPort, 'Enter first number: ');
              MOV       CurrentIO, SerialPort
              MOV       CurrentIO+1, SerialPort+1
              MOV       DPTR, #C_0369
              MOV       R6, #0
              LCALL     sysWriteStr_CODE

;     Readln  (SerialPort, Num1);
              MOV       CurrentIO+2, SerialPort+2
              MOV       CurrentIO+3, SerialPort+3
              LCALL     sysReadLongInt
              MOV       R0, #Num1
              LCALL     sysStore_Long0_To_IDATA
              LCALL     sysReadLine

;     Write   (SerialPort, 'Enter second number: ');
              MOV       CurrentIO, SerialPort
              MOV       CurrentIO+1, SerialPort+1
              MOV       DPTR, #C_037E
              MOV       R6, #0
              LCALL     sysWriteStr_CODE

;     Readln  (SerialPort, Num2);
              MOV       CurrentIO+2, SerialPort+2
              MOV       CurrentIO+3, SerialPort+3
              LCALL     sysReadLongInt
              MOV       R0, #Num2
              LCALL     sysStore_Long0_To_IDATA
              LCALL     sysReadLine

;     Writeln (SerialPort, Num1, ' + ', Num2, ' = ', Num1 + Num2);
              MOV       CurrentIO, SerialPort
              MOV       CurrentIO+1, SerialPort+1
              MOV       R0, #Num1
              LCALL     sysLoad_Long0_From_IDATA
              LCALL     sysPushLongIntBCD
              MOV       R6, #0
              LCALL     sysWriteDecimalPushedBytes
              MOV       DPTR, #C_0394
              MOV       R6, #0
              LCALL     sysWriteStr_CODE
              MOV       R0, #Num2
              LCALL     sysLoad_Long0_From_IDATA
              LCALL     sysPushLongIntBCD
              MOV       R6, #0
              LCALL     sysWriteDecimalPushedBytes
              MOV       DPTR, #C_0398
              MOV       R6, #0
              LCALL     sysWriteStr_CODE
              MOV       R0, #Num1
              LCALL     sysLoad_Long0_From_IDATA
              MOV       R0, #Num2
              LCALL     sysLoad_Long1_From_IDATA
              LCALL     sysLongAddition
              LCALL     sysPushLongIntBCD
              MOV       R6, #0
              LCALL     sysWriteDecimalPushedBytes
              LCALL     sysWriteLine

;   until False;
              LJMP      L_0023

; end.

              END

With the Assign statement you assign ReadFromSerialPort and WriteToSerialPort procedures to the File variable SerialPort. Check system procedure Assign for Read and Write procedure special rquirements. Turbo51 before each call to read/write procedure assigns file's read/write procedure to the CurrentIO system variable of type File. CurrentIO file is used by all system procedures which read from or write to actual device. System unit defines another file varable of type Text, SystemIO with aliases Input and Output. This text file is used for Read/ReadLn and Write/WriteLn procedures when no text file is specified. Before SystemIO can be used actual read/write procedures must be be assigend to it.

If there are a lot of read/write calls and we have only one IO device then we can avoid specifying this file and loading of CurrentIO file variable each time we call read/write with the compiler directve DefaultFile set to On (default is Off). Of course, we have to assign our procedures to the CurrentIO file variable with the Assign procedure. Be careful with this directive: any call to read/write with specified file variable (i.e. in other units compiled with DefaultFile set to Off) will overwrite CurrentIO variable. In such case the CurrentIO has to be assigned again. With this directive set to On the previous example would look like this:

Program Files;

{$DefaultFile On }

// Should work on any 8051 microcontroller

Const
 Oscillator = 22118400;
 BaudRate   = 19200;
 BaudRateTimerValue = Byte (- Oscillator div 12 div 32 div BaudRate);

Var SerialPort: Text;
    Num1, Num2: LongInt;

Procedure WriteToSerialPort; Assembler;
Asm
  CLR   TI
  MOV   SBUF, A
@WaitLoop:
  JNB   TI, @WaitLoop
end;

Function ReadFromSerialPort: Char;
Var ByteResult: Byte absolute Result;
begin
  While not RI do;
  RI := False;
  ByteResult := SBUF;

{ Echo character }

  Asm
    MOV    A, Result
    LCALL  WriteToSerialPort
  end;
end;

Procedure Init;
begin
  TL1  := BaudRateTimerValue;
  TH1  := BaudRateTimerValue;
  TMOD := %00100001;    { Timer1: no GATE, 8 bit timer, autoreload }
  SCON := %01010000;    { Serial Mode 1, Enable Reception }
  TI   := True;         { Indicate TX ready }
  TR1  := True;         { Enable timer 1 }
end;

begin
  Init;
  Assign (CurrentIO, ReadFromSerialPort, WriteToSerialPort);

  Writeln ('Turbo51 IO file demo');
  Repeat
    Write   ('Enter first number: ');
    Readln  (Num1);
    Write   ('Enter second number: ');
    Readln  (Num2);
    Writeln (Num1, ' + ', Num2, ' = ', Num1 + Num2);
  until False;
end.

And compiled code would look like this:

; Turbo51 version 0.1.3.10, Copyright 2000 - 2011 Igor Funa

$REGISTERBANK (0)

_CODE         SEGMENT  CODE
_CONST        SEGMENT  CODE
_DATA         SEGMENT  DATA

              EXTRN    DATA  (CurrentIO)
              EXTRN    IDATA (StackStart)

              EXTRN    CODE  (sysWriteStr_CODE)
              EXTRN    CODE  (sysWriteLine)
              EXTRN    CODE  (sysReadLongInt)
              EXTRN    CODE  (sysStore_Long0_To_IDATA)
              EXTRN    CODE  (sysReadLine)
              EXTRN    CODE  (sysLoad_Long0_From_IDATA)
              EXTRN    CODE  (sysPushLongIntBCD)
              EXTRN    CODE  (sysWriteDecimalPushedBytes)
              EXTRN    CODE  (sysLoad_Long1_From_IDATA)
              EXTRN    CODE  (sysLongAddition)

; Program Files;
; 
; {$DefaultFile On }
; 
; // Should work on any 8051 microcontroller
; 
; Const

RSEG _CONST

;  Oscillator = 22118400;
;  BaudRate   = 19200;
;  BaudRateTimerValue = Byte (- Oscillator div 12 div 32 div BaudRate);
; 
; Var SerialPort: Text;
;     Num1, Num2: LongInt;

RSEG _DATA

Num1:                           DS       4
Num2:                           DS       4

; 
; Procedure WriteToSerialPort; Assembler;


RSEG _CODE

USING 0

WriteToSerialPort:
; Asm
;   CLR   TI
              CLR       SCON.1

;   MOV   SBUF, A
              MOV       SBUF, A

; @WaitLoop:
L_008B:
;   JNB   TI, @WaitLoop
              JNB       SCON.1, L_008B

; end;
              RET

; 
; Function ReadFromSerialPort: Char;

RSEG _DATA

ReadFromSerialPort_Result:      DS       1

; Var ByteResult: Byte absolute Result;
ByteResult                      EQU      ReadFromSerialPort_Result


RSEG _CODE

ReadFromSerialPort:
; begin
;   While not RI do;
L_008F:
              JNB       SCON.0, L_008F

;   RI := False;
              CLR       SCON.0

;   ByteResult := SBUF;
              MOV       ReadFromSerialPort_Result, SBUF

; 
; { Echo character }
; 
;   Asm
;     MOV    A, Result
              MOV       A, ReadFromSerialPort_Result

;     LCALL  WriteToSerialPort
              LCALL     WriteToSerialPort

;   end;
; end;
              MOV       A, ReadFromSerialPort_Result
              RET

; 
; Procedure Init;

Init:
; begin
;   TL1  := BaudRateTimerValue;
              MOV       TL1, #$FD

;   TH1  := BaudRateTimerValue;
              MOV       TH1, #$FD

;   TMOD := %00100001;    { Timer1: no GATE, 8 bit timer, autoreload }
              MOV       TMOD, #$21

;   SCON := %01010000;    { Serial Mode 1, Enable Reception }
              MOV       SCON, #$50

;   TI   := True;         { Indicate TX ready }
              SETB      SCON.1

;   TR1  := True;         { Enable timer 1 }
              SETB      TCON.6

; end;
              RET

RSEG _CONST

C_032F:                         DB        20, 'Turbo51 IO file demo'
C_0344:                         DB        20, 'Enter first number: '
C_0359:                         DB        21, 'Enter second number: '
C_036F:                         DB        3, ' + '
C_0373:                         DB        3, ' = '


CSEG AT $0000

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

;   Init;
              LCALL     Init

;   Assign (CurrentIO, ReadFromSerialPort, WriteToSerialPort);
              MOV       CurrentIO, #LOW  (WriteToSerialPort)
              MOV       CurrentIO+1, #HIGH (WriteToSerialPort)
              MOV       CurrentIO+2, #LOW  (ReadFromSerialPort)
              MOV       CurrentIO+3, #HIGH (ReadFromSerialPort)

; 
;   Writeln ('Turbo51 IO file demo');
              MOV       DPTR, #C_032F
              MOV       R6, #0
              LCALL     sysWriteStr_CODE
              LCALL     sysWriteLine

;   Repeat
L_001D:
;     Write   ('Enter first number: ');
              MOV       DPTR, #C_0344
              MOV       R6, #0
              LCALL     sysWriteStr_CODE

;     Readln  (Num1);
              LCALL     sysReadLongInt
              MOV       R0, #Num1
              LCALL     sysStore_Long0_To_IDATA
              LCALL     sysReadLine

;     Write   ('Enter second number: ');
              MOV       DPTR, #C_0359
              MOV       R6, #0
              LCALL     sysWriteStr_CODE

;     Readln  (Num2);
              LCALL     sysReadLongInt
              MOV       R0, #Num2
              LCALL     sysStore_Long0_To_IDATA
              LCALL     sysReadLine

;     Writeln (Num1, ' + ', Num2, ' = ', Num1 + Num2);
              MOV       R0, #Num1
              LCALL     sysLoad_Long0_From_IDATA
              LCALL     sysPushLongIntBCD
              MOV       R6, #0
              LCALL     sysWriteDecimalPushedBytes
              MOV       DPTR, #C_036F
              MOV       R6, #0
              LCALL     sysWriteStr_CODE
              MOV       R0, #Num2
              LCALL     sysLoad_Long0_From_IDATA
              LCALL     sysPushLongIntBCD
              MOV       R6, #0
              LCALL     sysWriteDecimalPushedBytes
              MOV       DPTR, #C_0373
              MOV       R6, #0
              LCALL     sysWriteStr_CODE
              MOV       R0, #Num1
              LCALL     sysLoad_Long0_From_IDATA
              MOV       R0, #Num2
              LCALL     sysLoad_Long1_From_IDATA
              LCALL     sysLongAddition
              LCALL     sysPushLongIntBCD
              MOV       R6, #0
              LCALL     sysWriteDecimalPushedBytes
              LCALL     sysWriteLine

;   until False;
              SJMP      L_001D

; end.

              END

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