; File: PCA_Port.A51 Date: 07/10/92 ; ; /* (c) Copyright BLUE EARTH RESEARCH, MANKATO, MN 1992. */ ; /* All rights reserved. */ ; ; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ; º º ; º PCA FULL DUPLEX SERIAL PORT DRIVER ROUTINE º ; º º ; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; PROGRAM ADAPTED FROM MCS(R)-51 REFERENCE MANUAL PAGE 6-63 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ BLUE EARTH RESEARCH ³ ; ³ MANKATO, MN 56001 ³ ; ³ Author: Tom Hiniker ³ ; ³ Revised 7/10/92 by Tom Bachmann ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ $ TITLE (FULL DUPLEX SERIAL PORT USING PCA) $ DATE (07/10/92) NOGEN NOMOD51 $ XREF DEBUG ERRORPRINT $ PAGELENGTH (60) PAGEWIDTH (110) ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ EXAMPLE BASIC PROGRAM ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ; I connected the second serial port lines on the Micro-440 and used the ; following BASIC program to check out operation of this assembly language ; program. Characters entered on the keyboard are stored in a circular buffer ; located at 5000H and echoed back to the console. Characters are ; transmitted by writing them to DBY(1FH) and then CALLing 7841H. ; 10 CALL 7800H ; 20 DO : A=DBY(18H) : UNTIL A ; 30 DBY(18H)=0 : DBY(1FH)=A : CALL 7841H : GOTO 20 ; IMPORTANT NOTE: This software assumes that you are using the second serial ; port on the Micro. This requires that the P1.6 and P1.7 I/O lines not be ; connected to anything. Any external devices connected directly to P1.6 & ; P1.7 may prevent the serial driver from asserting the proper signals to the ; CPU on these I/O lines. This also means that the P1.6 I/O circuitry on the ; standard ST-I/O module and applications module may prevent the second ; serial port from functioning properly. $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ SYMBOL DEFINITIONS ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ $ NOLIST ; DON'T SHOW IN LIST FILE $ INCLUDE(REGFX.INC) ; INCLUDE 83C51FB REGISTERS $ LIST ; SHOW THE REST IN THE LIST FILE DSEG AT 18H RecvSBUF: DS 1 ; Software Receive SBUF BitCounter: DS 1 ; Counter for receiving bits RecvTemp: DS 1 BuffPoint: DS 1 ; Buffer location pointer Spare: DS 1 ; Not used TxmCounter: DS 1 ; Counter for sending bits TxmTemp: DS 1 TxmSBUF: DS 1 ; Software Transmit SBUF BSEG AT 0 StartBit: DBIT 1 ; Receive Flags DoneBit: DBIT 1 TxmStart: DBIT 1 ; Transmit Bits InProgress: DBIT 1 PCAAddress EQU 4033H ; PCA Interrupt Vector NegEdge EQU 011H SoftTimer EQU 049H ; NOTE: The serial port Baud Rate can be changed by editing the following ; program variable and then assembling the source file. Baud EQU 24 ; Baud Rate in 00's (2400) FullBitTime EQU 10000/Baud ; 417uS is the bit period HalfBitTime EQU FullBitTime/2 ; for 2400 baud. (12 Mhz) $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ EXTERNAL DATA SEGMENT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ XSEG AT 5000H ; This memory page is used to accumulate the characters received on P1.6. RecvBuffer: DS 256 ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ CODE SEGMENT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CSEG AT 7800H 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 RECEIVE MODE ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CLR StartBit CLR DoneBit MOV BuffPoint,#0 MOV RecvTemp,#0 MOV RecvSBUF,#0 ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ INITIALIZE TRANSMIT MODE ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ CLR TxmStart CLR InProgress MOV TxmTemp,#0 MOV TxmSBUF,#0 MOV CCAP4L,#LOW FullBitTime MOV CCAP4H,#HIGH FullBitTime ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ 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 0 0 0 0 0 MOV IE,#0C0H ; ÚÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄÂÄÄÄÄÄÄ¿ ; CCAPM = ³ -- ³ ECOM ³ CAPP ³ CAPN ³ MAT ³ TOG ³ PWM ³ ECCF ³ ; ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÁÄÄÄÄÄÄÙ ; Module 3 -> 0 0 0 1 0 0 0 1 ; Module 4 -> 0 1 0 0 1 0 0 1 MOV CCAPM3,#NegEdge 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 RET ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ SET UP TO TRANSMIT A CHARACTER ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ SendChar: CLR TxmStart ; Clear status flag MOV TxmTemp,TxmSBUF ; Load "SBUF" with data byte MOV TxmCounter,#9 ; 8 data bits + 1 stop bit SETB InProgress RET $ EJECT ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ; ³ PCA INTERRUPT ³ ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ PCAINT: JBC CCF3,ReceiveInt ; Check for receive Interrupt JNB CCF4,NoMore ; Not a valid 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,#LOW FullBitTime ; Setup for next PCA int. ADD A,CCAP4L MOV CCAP4L,A MOV A,#HIGH FullBitTime ADDC A,CCAP4H MOV CCAP4H,A JBC CCF3,ReceiveNow ; Also Check for receive POP PSW POP ACC NoMore: RETI $ EJECT ; ---------------------------- RECEIVE INTERRUPT ------------------------------ ReceiveInt: PUSH ACC PUSH PSW ReceiveNow: MOV A,CCAPM3 ANL A,#7FH CJNE A,#NegEdge,CheckStart MOV A,#LOW HalfBitTime ; Setup for next PCA int. ADD A,CCAP3L MOV CCAP3L,A MOV A,#HIGH HalfBitTime ADDC A,CCAP3H MOV CCAP3H,A MOV CCAPM3,#SoftTimer POP PSW POP ACC RETI CheckStart: CJNE A,#SoftTimer,Error JB StartBit,DecrBitCtr JB P1.6,Error SETB StartBit MOV BitCounter,#9 SetUpFull: MOV A,#LOW FullBitTime ; Setup for next PCA int. ADD A,CCAP3L MOV CCAP3L,A MOV A,#HIGH FullBitTime ADDC A,CCAP3H MOV CCAP3H,A POP PSW POP ACC RETI $ EJECT DecrBitCtr: DJNZ BitCounter,RotateBit CheckStop: JNB P1.6,Error CLR StartBit MOV CCAPM3,#NegEdge SETB DoneBit MOV RecvSBUF,RecvTemp ; Got the character! PUSH DPH ; Save DPTR PUSH DPL MOV DPH,#HIGH RecvBuffer ; Store received character MOV DPL,BuffPoint ; in next buffer location. MOV A,RecvTemp MOVX @DPTR,A POP DPL POP DPH ; Restore DPTR INC BuffPoint ; Increment buffer pointer POP PSW POP ACC RETI RotateBit: MOV C,P1.6 ; Shift in next data bit. MOV A,RecvTemp RRC A MOV RecvTemp,A SJMP SetUpFull Error: MOV CCAPM3,#NegEdge ; Receive error. CLR StartBit POP PSW POP ACC 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. :107800009040337402F0A37478F0A3744CF0C2007B :10781000C201751B00751A00751800C202C20375FB :107820001E00751F0075EEA075FE0175E90075F963 :107830000075A8C075DD1175DE4975D90075D84091 :1078400022C202851F1E751D09D2032210DB3930AA :10785000DC35C2DCC0E0C0D0300319200206C2977C :10786000D2028010D51D06D297C2038007E51E13F1 :107870009297F51E74A025EEF5EE740135FEF5FE27 :1078800010DB09D0D0D0E032C0E0C0D0E5DD547FBD :10789000B4111474D025EDF5ED740035FDF5FD75CA :1078A000DD49D0D0D0E032B4494D200019209647B0 :1078B000D20075190974A025EDF5ED740135FDF5BB :1078C000FDD0D0D0E032D5192530962BC20075DD21 :1078D00011D201851A18C083C082758350851B821E :1078E000E51AF0D082D083051BD0D0D0E032A2962A :1078F000E51A13F51A80BE75DD11C200D0D0D0E0B4 :017900003254 :00000001FF