;----------------------------------------------------------------------; ;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 ; supress 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