;----------------------------------------------------------------------;
;ALPHA4M.ASM Sends and receives characters serially 4800 baud with PC ;
;----------------------------------------------------------------------;
; A terminal program runs on the PC set to 4800 baud, 8 bit, no parity
; 1 stop bit no handshaking. When a character is typed on the keyboard
; it is sent to the PIC and the PIC returns the next 3 ASCII characters
; .-----------.
; -|RA2 RA1|--------[DB9S pin 2]
; -|RA3 RA0|----{R}--[DB9S pin 3]
; -|RA4 OSC1|--|X|___ gnd
; V+ ---|MCLR OSC2|--|X|
; gnd ---|Vss Vdd|--- V+ -{R}- = 22 K resistor
; -|RB0 RB7|- X = 4 MHz cer. res.
; -|RB1 RB6|- V+ = 4.5 or 5 Volts
; -|RB2 RB5|-
; -|RB3 RB4|-
; '-----------'
; PIC16F84
; DB9S female com port connections:
; pins 1, 4 and 6 connected together (DCD,DTR & DSR)
; pins 7 and 8 connected together (RTS & CTS)
; pin 5 to gnd
; pin 2 to PIC pin 18 (RA1)
; pin 3 to 22 K resistor to PIC pin 17 (RA0)
LIST P=16F84 ; tells which processor is used
INCLUDE "p16f84.inc" ; defines various registers etc. Look
ERRORLEVEL -224 ; suppress annoying message from tris
__CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF ; config. switches
#DEFINE incom PORTA, 0 ; input port
#DEFINE outcom PORTA, 1 ; output port
CBLOCK H'0C'
txreg ; holds byte to be transmitted
rxreg ; holds byte received
char ; holds character to be transmitted
bitcount ; holds count of bits when transmitting
cntmsec ; holds counter for milliseconds
ENDC
ORG 0 ; start a program memory location zero
goto main ; skip over subroutines
;----------------------------------------------------------------------;
; initialization - set up ports and timer options ;
;----------------------------------------------------------------------;
init:
movlw B'00000001' ; RA0 to input
tris PORTA ; contents of W copied to PORT A ...
movlw B'0000000' ; all of PORT B outputs
tris PORTB
return
;----------------------------------------------------------------------;
; time delay routines ;
;----------------------------------------------------------------------;
bitdelay movlw D'51' ; one bit period at 4800 baud
; 50 * 4 + 5 + 1 + 2 = 208 usec
; for 'call bitdelay'
; Timing is determined by counting instruction cycles.
; micro4 is a loop that take 4 microseconds each time through,
; (4 mhz crystal). By using W, you save a general register.
; The last time through take 5 microseconds, including the return.
; If W is 248 on entry the total time is 247 * 4 + 5 = 993 usec.
; An additional 2 usec for the call gives 995 microseconds.
; The instruction 'call micro4' in this case represents 995 usec.
micro4 addlw H'FF' ; subtract 1 from 'W'
btfss STATUS,Z ; skip when you reach zero
goto micro4 ; more loops
return
;*** N millisecond delay routine ***
msec250: movlw D'250' ; 250 millisecond delay
nmsec: movwf cntmsec ; delay for N (in W) millisec
msecloop: movlw D'248' ; 1 usec for load
call micro4 ; this instruction is 995 usec
nop ; 1 usec
decfsz cntmsec,f ; 1 usec, (2 if skip taken)
goto msecloop ; 2 usec, loop = 995+5 = 1 msec
return
;----------------------------------------------------------------------;
; the main program ;
;----------------------------------------------------------------------;
main: ; this is the main program
call init ; set up ports
call msec250 ; let things settle
loop:
call rx
movwf char
incf char, f
movf char, W
call tx
incf char, f
movf char, W
call tx
incf char, f
movf char, W
call tx
goto loop
;----------------------------------------------------------------------;
; transmit byte in W at 4800 baud to PC ;
;----------------------------------------------------------------------;
; normal rs232 is -V for a high, +V for a low
; this would translate to 0V for high +5 for low
; a bit length at 4800 baud is 208 microseconds
; this is made up of a delay of 199 microseconds, (call micro4), plus
; 9 or 10 microseconds taken up with instructions in each txloop
tx: movwf txreg ; put W into transmit register
movlw D'08' ; eight bits of data
movwf bitcount ; a counter for bits
bsf outcom ; start bit (flipped remember)
txloop: movlw D'49' ; delay time
call micro4 ; wait 48*4+5+2 = 199 microsec
rrf txreg, f ; roll rightmost bit into carry
btfsc STATUS, C ; if carry 0, set bit (a low)
goto clrbit ; else clear bit, (a high)
bsf outcom ; +5V on output pin
goto testdone ; are we finished?
clrbit: bcf outcom ; 0 volts on output pin
testdone: decfsz bitcount, f ; one less data bit, skip when 0
goto txloop ; more bits left, delay this one
call bitdelay ; delay for last data bit
bcf outcom ; 0V, ( a high ) for stop bits
call bitdelay ; 2 stop bits
call bitdelay
return
;----------------------------------------------------------------------;
; receive byte at 4800 baud from PC, put in W ;
;----------------------------------------------------------------------;
rx:
startbit:
btfss incom ; goes high for start, (reversed)
goto startbit ; not yet wait some more
movlw D'24' ; wait half a bit time
call micro4 ;
btfss incom ; check if still high
goto startbit ; no, start again
movlw D'8' ; 8 bits
movwf bitcount ; into counter
clrf rxreg ; clear out register
receive:
movlw D'49' ; makes call micro4 = 199 usec
call micro4 ; wait one bit length (- instr.)
bsf STATUS, C ; start with high to shift in
btfsc incom ; if pin low, shift in high (rev)
bcf STATUS, C ; else change to low
rrf rxreg, f ; shift bit in
decfsz bitcount, f ; last bit collected?
goto receive ; not yet, get more, 8 usec+call
call bitdelay ; stop bit
movf rxreg, W ; result into W
return
end