> From: Claudio Rachiele IW0DZG <75805312@IT.IBM.COM> > To: > Subject: rs232 routines > Date: Monday, September 20, 1999 11:27 AM > > Hello piclister, I'm looking for a RS232 bitbanging routine with programmable > baudrate working with different xtals. > I have seen something on the Net but I forgot where. I have used the following code on a PIC16F84 for 9600 baud with a 4MHz crystal (it's 3-wire serial not real RS232). You can change the baud rate as well as the crystal you use. I have even run this routine for 19200 buad, but the reliability is not so good. With 9600 and this routine I have found 100% reliability of the received and transmitted data. If this is unclear, plaese e-mail me privately. Cheers Etienne NOTE: Program starts here: ;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