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