

;registers
        CHARBUF                 EQU     0C                              ;receive
 and transmit shift register
        BITCOUNT                        EQU     0D
        ;bit counter
        BAUDCOUNT               EQU     0E
;bit delay loop counter
        RECCHAR                 EQU     0F
;received character register

;variables
        OSCCLOCK                EQU     .4000000                        ;define
external crystal frequency
        BAUDRATE                EQU     .9600                           ;define
desired baud rate here
        TX                              EQU     3
        ;RA3 software UART transmit pin
        RX                              EQU     2
        ;RA2 software UART receive pin
        OVERHEAD                EQU     .11
;number of instructions for routine
        INSTPERBIT              EQU     ((2*OSCCLOCK/(4*BAUDRATE))+1)/2
;instruction/bit
time
        INSTPERHALFBIT          EQU     ((2*OSCCLOCK/(8*BAUDRATE))+1)/2
;instruction/bit
time
        DELAYBAUD               EQU     (INSTPERBIT-OVERHEAD)/3
        NUMBAUDNOPS             EQU     INSTPERBIT-(3*DELAYBAUD)-OVERHEAD
        DELAYHALFBAUD           EQU     (INSTPERHALFBIT-OVERHEAD)/3
        NUMHALFBAUDNOPS         EQU     INSTPERHALFBIT-(3*DELAYHALFBAUD)-OVERHEA
D

;main routine
MAIN    CALL    INITUART                ;setup UART ports
        etc.

NOTE:   ****to transmit a character, place it in the work register (W) and
CALL UARTTX
        ****to receive a character, CALL UARTRX and the received character will
be
in the CHARBUF register

;macro for delaying one bit time interval
DELAYBIT MACRO
        LOCAL   DLYLABELS
        MOVLW   DELAYBAUD               ;place baud delay value into W
        MOVWF   BAUDCOUNT               ;move baud delay value into BAUDCOUNT
        VARIABLE NOPCOUNT
NOPCOUNT = NUMBAUDNOPS
        WHILE NOPCOUNT > 0              ;add correct number of NOPs
        NOP                             ;delay one additional cycle
NOPCOUNT--
        ENDW
DLYLABELS
        DECFSZ  BAUDCOUNT,F             ;decrement baud delay counter, skip
                                        ;when zero
        GOTO    DLYLABELS               ;jump back and delay for another
                                        ;count cycle
        ENDM

;macro for delaying one half bit time interval
DELAYHALFBIT MACRO
        MOVLW   DELAYHALFBAUD           ;place half baud delay value into W
        MOVWF   BAUDCOUNT               ;move baud delay value into BAUDCOUNT
        VARIABLE NOPCOUNT
NOPCOUNT = NUMHALFBAUDNOPS
        WHILE NOPCOUNT > 0
        NOP                             ;delay one additional cycle
NOPCOUNT--
        ENDW
DLYHALFLABELS
        DECFSZ  BAUDCOUNT,F             ;decrement baud delay counter, skip
                                        ;when zero
        GOTO    DLYHALFLABELS           ;jump back and delay for another
                                        ;count cycle
        ENDM

;RS-232 port initialization routine
INITUART MOVLW  B'00001100'             ;set porta RA3,2
        MOVWF   PORTA                   ;
        BSF     STATUS,RP0              ;page 1
        MOVLW   B'00000111'             ;set RA3 as output
        MOVWF   TRISA                   ;
        BCF     STATUS,RP0              ;page 0
        RETURN

;uarttx RS-232 character output routine.
UARTTX  MOVWF   CHARBUF                 ;place output char into CHARBUF reg
        MOVLW   .10                     ;total number of bits to send
        MOVWF   BITCOUNT                ;move this to BITCOUNT reg
        BSF     STATUS,C                ;init carry with stop bit
        BCF     PORTA,TX                ;send a start bit
        GOTO    LOOPDELAY               ;jump to send the start bit
SENDBIT RRF     CHARBUF,F               ;place next bit for tx into carry bit
        BTFSC   STATUS,C                ;skip if next bit is zero
        GOTO    SETTXOUT                ;sending a one, jump to setoutput code
        NOP                             ;add one cycle so set and clear of
                                        ;output synch up
        BCF     PORTA,TX                ;transmit a 1
        GOTO    LOOPDELAY               ;done updating tx output,goto next bit
SETTXOUT
        BSF     PORTA,TX                ;transmit a 0
        GOTO    $+1                     ;add 2 cycles so timing synchs up
LOOPDELAY
        DELAYBIT                        ;delay for one bit time
        DECFSZ  BITCOUNT,F              ;decrement bit counter, skip when done
        GOTO    SENDBIT                 ;jump back to put_bit to tx next bit
        RETURN

;uartrx RS-232 character input routine
UARTRX  MOVLW   .09                     ;set input bit counter
        MOVWF   BITCOUNT                ;place bit counter into BITCOUNT
GETWAIT BTFSC   PORTA,RX                ;skip when receive a start bit
        GOTO    GETWAIT                 ;go back and wait for a start bit
        DELAYHALFBIT                    ;delay for one half bit time
        BTFSC   PORTA,RX                ;skip if still have the start bit
        GOTO    GETWAIT                 ;noise - go back and wait for start
GETLOOP DELAYBIT                        ;delay for one bit time
        BCF     STATUS,C                ;clear carry bit to shift in zero
        BTFSC   PORTA,RX                ;skip if the next bit is a zero
        BSF     STATUS,C                ;set the carry bit
        GOTO    $+1                     ;delay 2 cycles
        NOP                             ;delay 1 cycle
        RRF     CHARBUF,F               ;shift the next received bit into temp
        DECFSZ  BITCOUNT,F              ;decrement the bit count and skip when
                                        ;finished
        GOTO    GETLOOP                 ;go back if still have more bits
        RLF     CHARBUF,F               ;restore buffer after shifting in stop b
it
        RETURN

        END

