Re: Serial out problem..

Jun 15, 2003



#1453 Jun 15, 2003

Hi all.. I'm trying to play wiht some sample kodes on how to use

a PIC port as a serial input/output.

I have now tested some different sample kodes with the same result.

When I try to send "Hello world!" to a port

I end up with &8.....>....8.. in my terminal..

Hmm.. the paste didn't work, but it starts with &8..

I can think of 2 resons causing this problem,

1. The sample code is for the 16f84 but I'm using 16f877

2. The timing is wrong in my hardware, I think im using the inbuilt(?)


What could it be?? How do I solve the problem?

(I'm using CC5x free)

/best regards



#1454 Jun 15, 2003

If you are using C.6/C.7 for serin/serout to a terminal the baud rate must be 84.

The code must be compiled for whatever chip you are using.  A program compiled for an F84 probably will not work verbatim on an F877.

Sid Weaver


Port Richey, FL


#1455 Jun 15, 2003

If you are using C.6/C.7 for serin/serout to a terminal the baud

rate must be > 84.

On the 16F877 I'm trying to use RB1 as TX and RB2 as the pic's RX.

With a sample code "repeat char" the Pic's RX seems to work.

But the TX char does not match with the input one..

> The code must be compiled for whatever chip you are using. A

program > compiled for an F84 probably will not work verbatim on an F877.

I do recompile the code for the F877 but it was created for the




#1456 Jun 15, 2003

Michael, You will never be able to get accurate baud ratesusing the internal RC oscillator.  It's best to use a crystal of at least4.00MHz which will give you accurate serial comms to 9600 baud. The serial routines for bit-banging ports arewidely available from PIC sources on the net and only take about 56 or 60instructions to implement. See below for typical generic routine which can besimplified even more if you just want 1200, 8,N 1 comms: regards,  Ken  INCLUDE "P16f84A.INC" Count   EQU 0X1C  ; Counter for No. of BitsTransmittedDlyCnt  EQU 0X1D  ; Another delaycounterRcvReg   EQU 0X1E  ; Serial Data receiveregisterXmtReg   EQU 0X1F  ; Serial Data to betransmitted    GLOBAL COMMSGLOBAL TRANSMIT 

;******************************************************************************;                      RS-232 Communication With PIC16C5X (or 16C84 );; Half DuplexAsynchronous Communication  - 1200 Baud for 3.579545MHz resonator;Upgraded 12/4/00 for 9600Bd on PIC16F84A running on 16MHzcrystal;****************************************************************************** Same   equ     1MSB    equ     7 ;*****************  CommunicationParameters   ********************************;X_MODE equ     1       ; If (X_MODE==1) Then transmit LSBfirst;                        if ( X_MODE==0) Then transmit MSB first ( CODEC like )R_MODE equ     1       ; If (R_MODE==1) Then receive LSBfirst;                        if ( X_MODE==0) Then receive MSB first ( CODEC like )X_Nbit equ     1       ; if(X_Nbit==1) # of data bits ( Transmission ) is 8 else 7R_Nbit equ     1       ; if(R_Nbit==1) # of data bits ( Reception ) is 8 else 7;Sbit2  equ     0       ; if Sbit2 = 0then 1 Stop Bit else 2 StopBits;;*************************************************************************   ;X_flag equ     PA0     ; Bit 5 of F3 ( PA0)   ;R_flag  equ    PA1     ; Bit 6 of F3 ( PA1);DX      equ    1        ; Transmit Pin ( Bit 1 of PortA )DR      equ    0        ; Receive Pin ( Bit 0 of Port A);; Following code sets the delay times for the selectedbaudrate; X is the unknown delay; Values below are for 9600bdon a 16.000MHz crystal; See H:\Excel Files\PICBauudratecalc.xls fordelay calculator; BAUD_4 is half the reqd 1.25B delay so delay4 isrepeated  BAUD_1  equ    .138      ; 3+3X = CLKOUT/BaudBAUD_2 equ     .137      ; 6+3X =CLKOUT/BaudBAUD_3  equ    .68       ; 3+3X =0.5*CLKOUT/BaudBAUD_4  equ    .173      ; 3+3X = 1.25*CLKOUT/BaudBAUD_X  equ    .135      ; 1+3X = CLKOUT/BaudBAUD_Y equ     .136      ; 9 +3X =CLKOUT/Baud 

;****************************************************************;*Serial Communications;* Code space requirement 56locations;**************************************************************** ;*Talk routine waits for low start bit on PORTA,1 before dropping into receiverroutine talk       clrf   RcvReg          ; Clear all bits ofRcvReg  btfsc  PORTA,DR        ; check for a Start Bit onlocal RX pin  goto   User            ; delayfor B  (833uS for 1200Bd)  call   Delay4          ; delay for 1.25B  call Delay4  ;

;***************************************************************;      Receiver;Rcvr IF     R_Nbit movlw  8              ; 8 Data bits ELSE movlw  7              ; 7 data bits ENDIF; movwf  CountR_next  bcf    STATUS,C IF     R_MODE rrf     RcvReg,Same    ; to set if MSB first or LSBfirst ELSE rlf    RcvReg,Same ENDIF btfsc  PORTA,DR; IF      R_MODE  IF      R_Nbit  bsf     RcvReg,MSB       ;Conditional Assembly   ELSE  bsf     RcvReg,MSB-1  ENDIF ELSE bsf    RcvReg,LSB ENDIF; call   DelayY decfsz  Count,Same goto   R_next     ;**************************************************** ;      Transmitter TRANSMIT MOVWF XmtRegXmtr IF     X_Nbit movlw   8 ELSE movlw  7 ENDIF movwf  Count; IF     X_MODE ELSE   IF    X_Nbit  ELSE   rlf   XmtReg,Same  ENDIF ENDIF; bcf    PORTA,DX       ; Send StartBit call    Delay1X_next bcf    STATUS,C; IF     X_MODE rrf     XmtReg,Same    ; ConditionalAssembly ELSE                   ; to set if MSB first or LSB first rlf    XmtReg,Same ENDIF; btfsc  STATUS,C bsf    PORTA,DX btfss  STATUS,C bcf    PORTA,DX call    DelayX decfsz Count,Same goto   X_next bsf    PORTA,DX       ; Send StopBit call   Delay1; IF     Sbit2 bsf    PORTA,DX call   Delay1 ENDIF; RETURN ; goto   talk            ; Back ToReception & Transmision;;   End ofTransmission; User    movlw  BAUD_3 movwf   DlyCntredo_2  decfsz DlyCnt,Same goto    redo_2 

 goto   talk            ; LoopUntil Start Bit Found   ;****************************************************************************************;*Various Delays for serialtiming       *;* For variable delays, wcan be loaded with delay constant and then call routine "save"* ;*Subroutine returns after given delay of 5 + 3N cycles    *;**************************************************************************************** DelayY  movlw  BAUD_Y goto    saveDelayX  movlw  BAUD_X goto    saveDelay4  movlw  BAUD_4 goto    saveDelay1  movlw  BAUD_1            ;833uSfor 1200Bd  goto    saveDelay2 movlw   BAUD_2save    movwf  DlyCntredo_1  decfsz  DlyCnt,Same goto   redo_1 retlw   0 



#1460 Jun 16, 2003

You will never be able to get accurate baud rates using the

internal RC oscillator. It's best to use a crystal of at least

4.00MHz which will give you accurate serial comms to 9600 baud. >

I have now replaced the RC oscillator with a crystal but it seems to

still be somekind of problem with ma bit-bang com test.

I'm using the 16F877 with the RB1 as a TX and RB2 as RX.

Replacing the RC did do something, the transmitting chars is

different know.

What could it be more?

I suppose I might be using the TMR0 wrong, hope you can explain

how it should be used.

The example I'm trying to get to work is for a 16F84 while i'm using

the 16F877.. Could it be a TMR0 differense?

The code I'm using is attached below:




Using 9600 baud, one stop bit, no parity.

Baudrate 9600 baud => 104.167 microsec. per bit

TMR0 counts each 8th microsec. => 13.02 steps per bit


#include "16f877.h"

#define _4_MHz /* 4 MHz system clock */

#pragma bit RS232_out @ PORTB.1

#pragma bit RS232_in @ PORTB.2

#pragma bit knapp @ PORTB.0

#ifdef _4_MHz

#define TimeStartbit 4

#define BitTimeIncr 13


char bitCount, limit;

char serialData;

#ifdef _4_MHz

#ifdef UseTMR0

#define delayStart limit = TMR0;

#define delayOneBit \

limit += BitTimeIncr; \

while ( limit != TMR0) \



#define delayStart /* empty */

#define delayOneBit { \

char ti; \

ti = 30; \

do ; while( --ti > 0); \

nop(); \

} /* total: 5 + 30*3 - 1 + 1 + 9 \

= 104 microsec. at 4 MHz */



void sendData( char dout)

/* sends one byte */


RS232_out = 0; /* startbit */


for ( bitCount = 9; ; bitCount--) {


if ( bitCount == 0)


Carry = 1; /* incl. stopbit */

dout = rr( dout);

RS232_out = Carry;



#define NText 12

char text( char W)



#pragma return[NText] = "Hello world!"


void main( void)


char i;

PORTB = 0b00000111;

TRISB = 0b11111101;

OPTION = 2; // prescaler divide by 8

for ( i = 0; i NText; i++)

sendData( text(i)); /* text string */


while ( RS232_in == 1)



/* sampling once per bit */

TMR0 = 0;

limit = TimeStartbit;

while ( limit != TMR0)


if ( RS232_in == 1)

goto StartBitError;

bitCount = 8;

do {

limit += BitTimeIncr;

while ( limit != TMR0)


Carry = RS232_in;

serialData = rr( serialData); /* rotate carry */

} while ( -- bitCount > 0);

limit += BitTimeIncr;

while ( limit != TMR0)


if ( RS232_in == 0)

goto StopBitError;

/* 'serialData' can be processed here */

/* NOTE: limited time (40 - 50 microsec.) */

goto WaitNextIO;


/* RS232 stopbit error,

waiting while line is low */

while ( RS232_in == 0)



goto WaitNextIO;