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
