; File: Baud_2nd.A51 Date: 11/05/92 ; ; /* (c) Copyright BLUE EARTH RESEARCH, MANKATO, MN 1992 */ ; /* All rights reserved. */ $ ERRORPRINT PAGELENGTH (60) PAGEWIDTH (110) ; Assembler controls $ XREF TITLE (Serial Port Baud Rate Converter) $ DATE (11/05/92) NOGEN NOMOD51 ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º º ; º PCA SERIAL PORT DRIVER ROUTINE º ; º WITH 8051 SERIAL INPUT BUFFER ROUTINE º ; º º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ; ----------------------------------------------------------------------------- ; Written by Tom Bachmann, Blue Earth Research, Mankato, MN 56001 ; ----------------------------------------------------------------------------- ; This program combines the main functions of the Serial Input Buffer program ; BUFFER.A51 and the PCA-driven 2nd Serial Port program PCA_PORT.A51 to ; provide a means of implementing a baud rate converter. Only the transmit ; portion of the PCA serial port is implemented here. The program assumes ; that the primary serial port is properly set up and that the secondary port ; is initialized similar to the BASIC program shown below. ; IMPORTANT NOTE: If characters are being received at 2400 Baud and then ; transmitted at 4800 Baud, the 256-byte circular receive buffer will never ; overflow. However, if characters are received at 9600 and transmitted at ; 2400, it is possible for the buffer to overflow, resulting in the loss of ; 256 received characters. ; For more details on how the Serial Input Buffer and PCA Serial Port work, ; refer to the source files mentioned above. $ EJECT ; ------------------------- BASIC LANGUAGE PROGRAM ---------------------------- ; 1 REM Baud Rate Converter ; ; REM DEFINE THE SYSTEM'S SECOND SERIAL PORT BAUD RATE ; REM AND CALCULATE TIMING PARAMETERS ; 20 BPS=2400 : FULLBIT=1E+6/BPS ; 30 DBY(19H)=INT(FULLBIT/256+0.5) : DBY(18H)=FULLBIT.AND.255 ; ; 50 CALL 7F00H ; ------------------------ ASSEMBLY LANGUAGE PROGRAM -------------------------- ; For each serial character received, the Buffer "Head" address pointer is ; bumped and the received character stored into that location. Reading the ; buffer is accomplished by bumping the Buffer "Tail" address pointer and then ; reading that location into the accumulator. If the Head & Tail pointers are ; equal, then the Buffer is considered empty. Trying to read an empty Buffer ; will produce a NULL code (0) in the accumulator and will not advance the ; Tail pointer. ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ SYMBOL DEFINITIONS ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ $ NOLIST ; DON'T SHOW IN LIST FILE $ INCLUDE(REGFX.INC) ; INCLUDE 83C51FB REGISTERS $ LIST ; SHOW THE REST IN THE LIST FILE ; ----------------------------- EQUATE TABLE ---------------------------------- PCAAddress EQU 4033H ; PCA Interrupt Vector SerAddress EQU 4023H ; Serial Interrupt Vector SoftTimer EQU 049H CodeAddr EQU 7F00H ; Locate this program at top of ; write protectable memory space $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ INTERNAL DATA SEGMENT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ DSEG AT 18H LoFullBitTime: DS 1 ; Hold the reload values for the HiFullBitTime: DS 1 ; PCA Serial Port Timing TxmCounter: DS 1 ; Counter for sending bits TxmTemp: DS 1 ; Software Transmit SBUF Head: DS 1 ; Pointer to last character stuffed Tail: DS 1 ; Pointer to last character read ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ INTERNAL BIT SEGMENT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ BSEG AT 0 TxmStart: DBIT 1 ; Transmit Bits InProgress: DBIT 1 NextReady: DBIT 1 ; Set when a character is received ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ EXTERNAL DATA SEGMENT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ XSEG AT 5000H Buffer: DS 256 ; Where circular receive Buffer starts $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ EXTERNAL CODE SEGMENT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CSEG AT CodeAddr ; ---------------------- INITIALIZE PCA INTERRUPT ----------------------------- MOV DPTR,#PCAAddress ; Stuff "LJMP PCAINT" into MOV A,#2 ; mirrored PCA interrupt MOVX @DPTR,A ; vector at address 4033H. INC DPTR MOV A,#HIGH PCAINT ; Location of PCA MOVX @DPTR,A ; interrupt routine. INC DPTR MOV A,#LOW PCAINT MOVX @DPTR,A ; ------------------------INITIALIZE SERIAL INTERRUPT ------------------------- MOV DPTR,#SerAddress ; Write LJMP code to serial MOV A,#2 ; interrupt vector location. MOVX @DPTR,A INC DPTR MOV A,#HIGH SerialInt MOVX @DPTR,A INC DPTR MOV A,#LOW SerialInt MOVX @DPTR,A ; Now initialize Head and Tail pointers so that the first byte received is ; stored in (and read from) location 0 MOV Head,#0FFH ; Initialize Buffer pointers MOV Tail,#0FFH CLR NextReady ; No characters received yet ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ INITIALIZE TRANSMIT MODE ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CLR TxmStart CLR InProgress MOV TxmTemp,#0 MOV CCAP4L,LoFullBitTime MOV CCAP4H,HiFullBitTime $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ INITIALIZE CPU FUNCTIONS ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ MOV CL,#0 ; CLEAR PCA TIMER REGISTERS MOV CH,#0 ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; IE = ³ EA ³ EC ³ ET2 ³ ES ³ ET1 ³ EX1 ³ ET0 ³ EX0 ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; 1 1 0 1 0 0 0 0 MOV IE,#0D0H ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; IP = ³ -- ³ PPC ³ PT2 ³ PS ³ PT1 ³ PX1 ³ PT0 ³ PX0 ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; 0 1 0 0 0 0 0 0 MOV IP,#40H ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; CCAPM = ³ -- ³ ECOM ³ CAPP ³ CAPN ³ MAT ³ TOG ³ PWM ³ ECCF ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; Module 4 -> 0 1 0 0 1 0 0 1 MOV CCAPM4,#SoftTimer ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; CMOD = ³ CIDL ³ WDTE ³ -- ³ -- ³ -- ³ CPS1 ³ CPS0 ³ ECF ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; 0 0 0 0 0 0 0 0 MOV CMOD,#0 ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; CCON = ³ CF ³ CR ³ -- ³ CCF4 ³ CCF3 ³ CCF2 ³ CCF1 ³ CCF0 ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; 0 1 0 0 0 0 0 0 MOV CCON,#40H ClearTI: JNB TI,$ ; Normally set by BASIC. CLR TI ; We want it cleared. $ EJECT ; ----------------------------- MAIN PROGRAM ---------------------------------- Loop: JNB NextReady,Loop ; No characters received yet CLR NextReady ; ---------------------- READ CHARACTER FROM BUFFER --------------------------- MoreChars: MOV A,Head ; If Head & Tail are the same, XRL A,Tail ; the Buffer is considered empty. JZ Loop GetChar: INC Tail MOV DPH,#HIGH Buffer MOV DPL,Tail MOVX A,@DPTR ; Read the Buffer ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ SET UP TO TRANSMIT A CHARACTER ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ SendChar: CLR TxmStart ; Clear status flag MOV TxmTemp,A ; Load "SBUF" with data byte MOV TxmCounter,#9 ; 8 data bits + 1 stop bit SETB InProgress JB InProgress,$ ; Wait until character is transmitted SJMP MoreChars ; Since this program only echos characters, it will stay here forever. RET ; Back to BASIC?? NO!! ; ------------------------- DISABLE SERIAL INTERRUPT -------------------------- ; May want to load SBUF with 1st character of an output string instead of a ; NULL and let BASIC take care of sending the rest of them. StopSerial: CLR ES ; Disable serial interrupt WriteCR: MOV SBUF,#0DH ; Write to set TI bit RET Write??: MOV SBUF,A RET $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ PCA INTERRUPT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ PCAINT: JNB CCF4,NoMore ; Check for receive Interrupt ; ---------------------------- TRANSMIT INTERRUPT ----------------------------- TransmitInt: CLR CCF4 PUSH ACC PUSH PSW JNB InProgress,TxmDone JB TxmStart,SendByte ; See if Start Bit was sent CLR P1.7 ; Otherwise transmit Start bit SETB TxmStart ; Set start bit flag SJMP TxmDone SendByte: DJNZ TxmCounter,TxmNext ; Transmit 8 data bits TxmStop: SETB P1.7 ; Transmit stop bit CLR InProgress ; Transmission Completed! SJMP TxmDone TxmNext: MOV A,TxmTemp ; Transmit one bit at a time RRC A ; through the carry bit MOV P1.7,C MOV TxmTemp,A ; Save for next time TxmDone: MOV A,LoFullBitTime ; Setup for next PCA int. ADD A,CCAP4L MOV CCAP4L,A MOV A,HiFullBitTime ADDC A,CCAP4H MOV CCAP4H,A POP PSW POP ACC NoMore: RETI $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ SERIAL INTERRUPT ROUTINE ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ SerialInt: JNB RI,NotRecv ; Not a receive interrupt ? PUSH PSW ; Save registers PUSH ACC PUSH DPH PUSH DPL SETB NextReady ; Set Next Character Ready flag INC Head ; Point to next storage location MOV DPH,#HIGH Buffer ; Page pointer always the same. MOV DPL,Head MOV A,SBUF ; Get serial input character CLR RI ; and reenable interrupt. MOVX @DPTR,A ; Store character in Buffer POP DPL ; Restore registers POP DPH POP ACC POP PSW NotRecv: RETI END ; Following is the HEX file derived from the assembled source ; file. This can be used for directly loading the program via ; MONITOR-51 and almost any terminal program. :107F00009040337402F0A3747FF0A37477F0904034 :107F1000237402F0A3747FF0A374ADF0751CFF7599 :107F20001DFFC202C200C201751B008518EE851933 :107F3000FE75E90075F90075A8D075B84075DE4981 :107F400075D90075D8403099FDC2993002FDC20242 :107F5000E51C651D60F5051D758350851D82E0C219 :107F600000F51B751A09D2012001FD80E322C2AC85 :107F700075990D22F5992230DC32C2DCC0E0C0D008 :107F8000300119200006C297D2008010D51A06D2FF :107F900097C2018007E51B139297F51BE51825EEA4 :107FA000F5EEE51935FEF5FED0D0D0E03230981F61 :107FB000C0D0C0E0C083C082D202051C758350854A :107FC0001C82E599C298F0D082D083D0E0D0D03224 :00000001FF