Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

HELP with PIC16F88 serial communication

Status
Not open for further replies.

mzd2

New Member
I am working on a project based around a PIC16F88, and am currently trying to get the PIC to talk to the computer's serial port. I will put my code at the bottom of this post. As far as I can tell, I have all the hardware connected properly, yet I have been unable to get the PIC to send even a single character to the computer. I am using an ICL3232 (with all the required caps) to invert the signal and bring it to RS-232 levels. As you will see in the code, I have 3 LED's that I am lighting up to see if the program is hanging up somewhere. All 3 light up properly, so it seems to be making it through the program.

Do I have the UART initialized incorrectly? Any suggestions or tips?

Code:
	radix	dec
	
#include <p16f88.inc>
	__CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _XT_OSC
	__CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

#DEFINE	TRASET	b'10000000'  ;these are values that will be moved to TRISA and TRISB
#DEFINE TRBSET	b'00100100' ;bits 5 and 2 must be set according to datasheet

;registers
TMP	EQU	h'20'	;scratch

org 0

RVECTOR	goto INIT

;SEND subroutine
;======================================================
SEND	movwf	TXREG
	bsf		STATUS,5	;bank 1
WAIT    btfss   TXSTA,1		;loop until this bit gets set
        goto    WAIT		;when the shift register has been emptied 
	bcf		STATUS,5	;bank 0
	return
;======================================================

;Initializations
;======================================================
INIT	      clrf	PORTA		;clear port a
		clrf	PORTB		;clear port b
		bsf	STATUS,5	;select bank 1
		clrf	ANSEL
		movlw	TRASET
		movwf	TRISA
		movlw	TRBSET
		movwf	TRISB
		bcf	STATUS,5	;bank 0
;======================================================
		bsf	PORTA,1		;pull RA1 high, big LED should turn on

;Set up serial port
;======================================================
SERIAL	BSF 	STATUS,RP0 	; Go to Bank1
		MOVLW 	25 		; Set Baud rate
		MOVWF 	SPBRG
		MOVLW 	b'00100100'	;8-bit transmit, transmitter enabled,
		MOVWF 	TXSTA 		;asynchronous mode, high speed mode
		bcf 	PIE1,TXIE 	;disable transmit interrupts
		bcf 	PIE1,RCIE 	;disable receive interrupts
		BCF	STATUS,RP0 	;Go to Bank 0
		MOVLW 	b'10010000'	;8-bit receive, receiver enabled,
		MOVWF	RCSTA 		;serial port enabled
;======================================================
		bsf 	PORTA,4		;turn on small red LED, RA4

;Delay to let things settle
;======================================================
SETTLE	clrf	TMP
SLOOP	decfsz	TMP,1		;decrement TMP, store in TMP
	goto	SLOOP
;======================================================
	bsf 	PORTB,0		;turn on yellow LED, RB0

;Test serial port
;======================================================
MESSAGE	movlw	'1'			;send: 16F88 alive	
        call	SEND
        movlw	'6'
        call	SEND
        movlw	'F'
        call	SEND
        movlw	'8'
        call	SEND
        movlw	'8'
        call	SEND
	movlw	' '
        call	SEND
        movlw	'a'
        call	SEND
        movlw	'l'
        call	SEND
        movlw	'i'
        call	SEND
        movlw	'v'
        call	SEND
        movlw	'e'
        call	SEND
        movlw	h'0D' ; CR
	call	SEND
;======================================================
	bsf 	PORTB,0 ;turn on yellow LED, RB0

	end
 
Last edited:
Not sure if this might be your problem but I usually test for "ok to send" as shown in the Put232 routine below.

Have you tried simply echoing characters typed into Hyperterminal?

Code:
Loop
        call    Get232          ; get character               |B0
        call    Put232          ; echo back to Hyperterminal  |B0
        goto    Loop            ;                             |B0
Get232
        btfss   PIR1,RCIF       ; character available?        |B0
        goto    Get232          ; no, branch, else            |B0
        movf    RCREG,W         ; get character               |B0
        return                  ;                             |B0
Put232
        btfss   PIR1,TXIF       ; transmit buffer empty?      |B0
        goto    Put232          ; no, branch, else            |B0
        movwf   TXREG           ; send character              |B0
        return                  ;                             |B0
 
mzd2 said:
Do I have the UART initialized incorrectly? Any suggestions or tips?
I'm too lazy to read thru your code just now, but here's some very simple working 16F88 serial code that may help.
Code:
	list	p=16F88
	include	<p16f88.inc>
	__CONFIG _CONFIG1,_INTRC_IO & _WDT_OFF & _LVP_OFF & _MCLR_ON & _BODEN_OFF
	ERRORLEVEL 0, -302

	cblock	0x20
		d1,d2,d3,dec1,dec2,count,num
	endc

	org	0x0000
	goto	init

text	addwf	PCL,F
	retlw	'F'
	retlw	'i'
	retlw	'r'
	retlw	'e'
	retlw	'f'
	retlw	'l'
	retlw	'y'
	retlw	' '
	retlw	'1'
	retlw	'6'
	retlw	'F'
	retlw	'8'
	retlw	'8'
	retlw	0x0d
	retlw	0x0a
	retlw	0x00

init
	banksel	OSCCON		;bank 1
	movlw	b'01110110'	;internal 8mhz osc
	movwf	OSCCON
stable	btfss	OSCCON,IOFS	;oscillator stable?
	goto	stable		;no, wait
	movlw	b'00100100'	;set portb for serial I/O
	movwf	TRISB
	banksel	PORTA		;bank 0
	clrf	count
	call	rs_init

main	movf	count,W
	call	text
	andlw	0xff
next_ch	btfsc	STATUS,Z
	goto	done
	call	rs_send
	incf	count,F
	goto	main
done	goto	done

;Sends byte in W to RS232
rs_send	movwf	TXREG
	banksel	TRISA		;bank 1
sdloop	btfss	TXSTA,TRMT
	goto	sdloop
	banksel	PORTA		;bank 0
	return

rs_init
	banksel	TRISB		;bank 1
	movlw	.12		;set for 9600 baud @ 8MHz clock
	movwf	SPBRG
	bcf	TXSTA,BRGH	;clear Baud Rate Select Bit (low speed)
	bcf	TXSTA,SYNC	;asynchronous mode
	bsf	TXSTA,TXEN	;transmit enable
	banksel	PORTA		;bank 0
	bsf	RCSTA,SPEN	;serial port enable
	return

	end
 
mzd2 said:
Do I have the UART initialized incorrectly? Any suggestions or tips?
You're very very close. I cleaned up your code (to suit me, and to suit my slightly different hardware setup (Firefly board)) and it works fine.

Here's my comments:

--------------------

Programming assembly in decimal radix is just... wrong. :D If you work in assembler you think in hex and binary. Only occasionally is decimal useful. I changed it. You can change it back if you can't deal with it.

--------------------

This is silly
Code:
#DEFINE	TRASET	b'10000000'  ;these are values that will be moved to TRISA and TRISB
#DEFINE TRBSET	b'00100100' ;bits 5 and 2 must be set according to datasheet
Just do it right in the code like this
Code:
	movlw	b'10000000'
	movwf	TRISA
	movlw	b'00100100'
	movwf	TRISB

--------------------

This
Code:
;registers
TMP	EQU	h'20'	;scratch
is better done in a cblock directive like this
Code:
	cblock	0x20
	tmp
	endc
Put all your variables in the cblock.

--------------------

You're directly diddling bits to change banks, like this
Code:
	bsf		STATUS,5	;bank 1
Though that's not incorrect, I prefer to use banksel directives to make bank changes like this
Code:
	banksel	TXSTA		;bank 1
See code below for more examples.

--------------------

At the end of sending your text you send a CR ($0d). You should also send a linefeed ($0a). CR moves the cursor to the start of the line, but doesn't move it down a line as you might expect. Linefeed does that. Send both.

--------------------

At the end of your code there's nothing to catch it from running on into empty memory (NOPs). Confusing things will happen. The program will run over and over and over and... because it burns thru all those NOPs and wraps around and starts at the beginning of memory again. I put this line to stop it
Code:
the_end	goto	the_end

--------------------

You don't have to disable the interrupts explicitly
Code:
		bcf 	PIE1,TXIE 	;disable transmit interrupts
		bcf 	PIE1,RCIE 	;disable receive interrupts
They're disabled by default.

--------------------

Be sure you have the correct baud rate set for your clock rate. Set Hyperterminal to match. Set the baud rate and use 8-N-1 and NO flow control.

--------------------

Here's the neatened up version. I'm pretty sure I changed all the necessary settings back to work with your hardware after modding it to work with mine. A quick assemble and test and you'll know:
Code:
	list	p=16F88
	#include <p16f88.inc>
	__CONFIG _CONFIG1,_XT_OSC & _WDT_OFF & _LVP_OFF & _MCLR_ON & _BODEN_OFF
	ERRORLEVEL 0, -302
	
	cblock	0x20
	tmp
	endc

	org	0x0000
	goto	init

send	movwf	TXREG
	banksel	TXSTA		;bank 1
wait    btfss   TXSTA,TRMT	;loop until this bit gets set
        goto    wait		;when the shift register has been emptied 
	banksel	PORTA		;bank 0
	return

init	clrf	PORTA		;clear port a
	clrf	PORTB		;clear port b
	banksel	TRISA		;bank 1
	clrf	ANSEL
	movlw	b'10000000'
	movwf	TRISA
	movlw	b'00100100'
	movwf	TRISB
	banksel	PORTA		;bank 0
	bsf	PORTA,1		;pull RA1 high, big LED should turn on

serial
	banksel	SPBRG		;bank 1
	movlw 	.25 		;set baud rate
	movwf 	SPBRG
	movlw 	b'00100100'	;8-bit transmit, transmitter enabled,
	movwf 	TXSTA 		;asynchronous mode, high speed mode
	banksel	PORTA		;bank 0
	movlw 	b'10010000'	;8-bit receive, receiver enabled,
	movwf	RCSTA 		;serial port enabled
	bsf 	PORTA,4		;turn on small red LED, RA4

settle	clrf	tmp
sloop	decfsz	tmp,1		;decrement TMP, store in TMP
	goto	sloop
	bsf	PORTB,0		;turn on yellow LED, RB0

message	movlw	'1'		;send: 16F88 alive	
        call	send
        movlw	'6'
        call	send
        movlw	'F'
        call	send
        movlw	'8'
        call	send
        movlw	'8'
        call	send
	movlw	' '
        call	send
        movlw	'a'
        call	send
        movlw	'l'
        call	send
        movlw	'i'
        call	send
        movlw	'v'
        call	send
        movlw	'e'
        call	send
        movlw	0x0d		;CR
	call	send
	movlw	0x0a		;linefeed
	call	send
	bsf 	PORTB,0		;turn on yellow LED, RB0
	
the_end	goto	the_end

	end
 
Last edited:
Futz-
Thank you for the tips. I now have the program working and have cleaned it up per your suggestions.
 
Also, about the traset and trbset- that's just in there while I'm in the testing phase. I'm gradually adding things to the circuit/program and testing each addition, so I wanted to have the values for TRISA and TRISB up at the top of the program so I could easily change them in each version.
 
Status
Not open for further replies.

Latest threads

Back
Top