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.

PIC16F88 usart troubles: WVProfessor

Status
Not open for further replies.

WVProfessor

New Member
Pic16f88

Is anyone around? Is this the only thread this year?
I need help with a PIC16F88 usart firmware in receive mode.

As for all the switches and the A/D, I am prejudiced. I think digital stuff like switches should use digital I/O lines, and use A/D for analog things like the battery voltage and my temperature sensor. I have never used the A/D circuit yet. I am having enough trouble with the usart receiver. Then when that works I will try the I2C circuit to talk to a flash eeprom.
I have some code here that fails.
 
WVProfessor is too new to post his own thread so I've posted on his behalf:
WVProfessor said:
Is anyone around? Is this the only thread this month?
I need help with a PIC16F88 usart firmware in receive mode.
I got the usart to transmit easily (compared to this problem).
I am having trouble with the usart receiver. Then when that works I will try the I2C circuit to talk to a flash eeprom.
I wrote some code that fails.

WVProfessor, attach your PIC code in a reply to this post and we'll try and help you out. Use the code tags by highlighting your code and clicking the # icon in the reply window. This will preserve the code formatting making it easier for us to read.
 
kchriste said:
Use the code tags by highlighting your code and clicking the # icon in the reply window. This will preserve the code formatting making it easier for us to read.
Those instructions might be a bit confusing. To clarify: Before pasting your code, click the # icon in the menu above the reply text window. Then paste.

If you paste first, highlight and click #, as kchriste suggests, your code will already have lost its formatting before being wrapped by code tags.
 
Last edited:
I need help with a PIC16F88 usart firmware in receive mode. I got the usart to transmit easily (compared to this problem). I am having trouble with the usart receiver.
EDIT: This morning I pulled out my Blueroom **broken link removed** and wrote a RS232 receive routine to go with the init and transmit routines already in the code below. Init, transmit and receive routines are in bold blue. It's tested and works fine at 9600-8-N-1.
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'01110010'		;internal 8mhz osc
	movwf	OSCCON
stable	btfss	OSCCON,IOFS		;oscillator stable?
	goto	stable			;no, wait
	movlw	b'10111110'
	movwf	TRISA
	movlw	b'00100100'		;set portb for serial I/O
	movwf	TRISB
	clrf	ANSEL			;all digital input
	banksel	PORTA			;bank 0
	clrf	count
	call	rs_init

main	movf	count,W
	call	text
	andlw	0xff
next_ch	btfsc	STATUS,Z
	goto	recv
	call	rs_send
	incf	count,F
	goto	main
recv	call	receive			;get a byte
	movwf	num
	btfss	num,5
	goto	recv
red1	movlw	b'01000000'
	movwf	PORTA
	call	delay
green1	movlw	b'00000001'
	movwf	PORTA
	call	delay
	clrf	count
	goto	main
	
[B][COLOR="Blue"];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

;* Wait for a char from RS232 - return in W
receive	btfss	PIR1,RCIF	;wait for a byte from RS232 
	goto	receive
	movf	RCREG,W		;return received byte in W
	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
	nop
	bsf	RCSTA,CREN	;enable receive
	return[/COLOR][/B]

delay	movlw	0xff
	movwf	d1
	movlw	0x80
	movwf	d2
delay_0	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	delay_0
	return

	end
If you have a Firefly, what the program does is transmit "Firefly 16F88" and blink LED1 from red to green and back each time you hit any key with bit 5 set (almost all of them). Bit 5 is cleared on capitalized letters, so nothing happens when you hold down the shift key and hit letters.
 
Last edited:
My bad code:

Sorry about the multiple post. You folks are fast. Thanks.
Only the receive part fails. It hangs up at the XXX.
Extra storage and equates are for the thing this came from.
Some lines from McGahee and Prof. Walker.

Code:
LIST	p=16F88
	ERRORLEVEL -302
	__CONFIG	H'2007', B'11111100110000'  ; 3F30H the _CONFIG 1 directive.
	__CONFIG	H'2008', B'00000000000011'  ; 0003H

; Storage
	CBLOCK 20h		; bank 0 storage
        tick                    ; delay counter
	char                    ; char to transmit
        bitctr                  ; bit counter 
	ENDC

	CBLOCK 0A0h		; bank 1 storage
	GenCount		; generic counter/temp register 
	Mem_Loc_high		; EEPROM high memory address
	Mem_Loc_low		; EEPROM low memory address
	Data_Buf		; EEPROM data buffer
	OutputByte		; EEPROM output byte
	flags			; flag bit register
	inx			; message index
	ENDC

; Defines
#define	SDA	86h,2		; SDA = data = RB2
#define	SCL	86h,1		; SCL = clock = RB1
#define BANK0	BCF 3,5		; Select bank 0
#define BANK1	BSF 3,5		; Select bank 1

;Equates
status	EQU	03h		; status register (duplicated all banks)
PORTA	EQU	05h		; port A register
PORTB	EQU	06h		; port B register
PIR1	EQU	0Ch		; flags
sspcon	EQU	14h		;*I2C control
RCSTA	EQU	18h		; in bank0
TXREG	EQU	19h		; Transmit data
RCREG	EQU	1AH		; Receive data
adcon0	EQU	1Fh		;*A/D channel control
TRISA	EQU	85h		; data direction A
TRISB	EQU	86h		; data direction B
INTCON	EQU	0Bh		;*Interrupt control
OSCON	EQU	8Fh		; OSCCON controls clock speed
OSCTUNE	EQU	90h		; Frequency control
TXSTA	EQU	98h		; in bank1
SPBRG	EQU	99h		; in bank1
ANSEL	EQU	9Bh		; a/d line property
adcon1	EQU	9Fh		;*A/D format control
c	EQU	0		; carry bit
z	EQU	2		; zero bit
rp0	EQU	5		; 0,1 bank select bit
rp1     EQU     6               ; 2,3 bank select bit
pcl	EQU	2		; program counter low byte	
WRITE	EQU	0A0h		; EEPROM write command
READ	EQU	0A1h		; EEPROM read command
xmit    EQU     0               ; RA0 is COM1 transmit pin
NULL    EQU     0		; null byte, message terminator
EOF	EQU	0		; also using 0 as end of file here
CR      EQU     d'13'           ; carriage return
LF      EQU     d'10'           ; line feed

;*******
; Main *
;*******
	ORG	0000h
Start	BCF     status,rp1	; banks 0 & 1 only
	BANK0			
kilint	bcf	INTCON,7	;*turn gie off 
	btfsc	INTCON,7	;*MicroChip recommends this check!
	goto 	kilint		;*!!! GOTCHA !!! without this check
				;*you are not sure gie is cleared!
	clrf	sspcon		;*I2C control
	clrf	0Ch		;*pir1 clear peripheral flags
	clrf	0Dh		;*pir2 all of them
 	clrf	PORTA		;*clear all i/o registers...
	clrf	PORTB
	movlw	00h	;*set all i/o as digital. no analog.
	movwf	adcon0

	BANK1			
	clrf	8Ch		;*pie1 disable peripheral interrupts
	clrf	8Dh		;*pie2 all of them
	movlw	b'10001111'	;*set right justified
	movwf	adcon1
	MOVLW	24h	;set portb direction for i/o pins
	MOVWF	TRISB	;*0=output  1=input
			;* rB5 output _uart_TX
	;*!!! rB5 output _uart_tx. Actually an output,
	;*!!! BUT for UART use rB5 MUST be programmed
	;*!!! as an INPUT! (How wonderfully counter-intuitive!)
	MOVLW	0x43
	MOVWF	81h		;*Option register p18
	CLRF	8Bh		;*intcon no interrupts used.
	MOVLW	0x26		;was 04 set BRGH clear SYNC
	MOVWF	TXSTA 
	MOVLW	0x19	;Set SPBRG to 25d=19h	d'25' or .25
	MOVWF	SPBRG
	MOVLW	60h		; speed up clock  0110 0000=60h 
	MOVWF	OSCON		; OSCCON= H'8F' makes 4MHz
	MOVLW	01h		; speed up clock 00 0001 =0.00375
	MOVWF	OSCTUNE		; OSCTUNE=90h

	BANK0			
	MOVLW	0x43		; A
	MOVWF	char 		; is in BANK0
;	CLRF	PORTA		; Why?
;	CLRF	ANSEL		; ANSEL is at 9B default 1 is analog
	MOVLW	90h		;Set SPEN and set CREN in RCSTA
	MOVWF	RCSTA
	movf	RCREG,w		;*clear uart receiver
	movf	RCREG,w		;* including fifo
	movf	RCREG,w		;* which is three deep.
	movlw	0		;*any character will do.
	movwf	TXREG		;*send out dummy character
				;* to get transmit flag valid!

	
LOOP	CALL	RX
	CALL	TX
	GOTO	LOOP

;******************************************
; My replacement for RecvPC is RX	  *
; Received character is put in char.	  *
;******************************************
RX	BANK0
	BTFSC	RCSTA,1	; OERR is overrun error
	CALL	err	; error routine 
	BTFSC	RCSTA,2	; FERR is framing error ignore
	CALL	err
	BTFSS	PIR1,5	; Test RCIF to see if a word is in.
XXX     GOTO	RX	; 1 means full=received
	MOVF	RCREG,w	; Get receive data 0 goes to w, 1 goes to f
	MOVWF	char
	RETURN

err	BCF	RCSTA,4	;clear CREN in RCSTA
	movf	RCREG,w		;flush fifo
	movf	RCREG,w		; all three elements.
	movf	RCREG,w
	BSF	RCSTA,4	; set CREN in RCSTA
	RETURN

;******************************************
; My replacement for SendPC is TX	   *
; The ASCII term to transmit is in char *
; 4MHz and 9.6 means SPBRG = 25. *
; No interrupts so check every millisecond if max speed  *
; Send a character to the PC com port     *
;******************************************
TX	BANK0
	BTFSS	PIR1,4	;check the TXIF bit in PIR1 (1 means empty)
	GOTO	$-1	
	MOVF	char,w	; get char
;	MOVLW	0X41  It sends the letter A just fine when this is swapped in.
	MOVWF	TXREG	; Put char in TXREG
	RETURN	; wait 1 clock before checking PIR1

	END
 
WVProfessor said:
Code:
LIST	p=16F88
	ERRORLEVEL -302
	__CONFIG	H'2007', B'11111100110000'  ; 3F30H the _CONFIG 1 directive.
	__CONFIG	H'2008', B'00000000000011'  ; 0003H
If you add this line:
Code:
	include	<p16f88.inc>
just below your LIST directive, you don't need all this stuff
Code:
;Equates
status	EQU	03h		; status register (duplicated all banks)
PORTA	EQU	05h		; port A register
PORTB	EQU	06h		; port B register
PIR1	EQU	0Ch		; flags
sspcon	EQU	14h		;*I2C control
RCSTA	EQU	18h		; in bank0
TXREG	EQU	19h		; Transmit data
RCREG	EQU	1AH		; Receive data
adcon0	EQU	1Fh		;*A/D channel control
TRISA	EQU	85h		; data direction A
TRISB	EQU	86h		; data direction B
INTCON	EQU	0Bh		;*Interrupt control
OSCON	EQU	8Fh		; OSCCON controls clock speed
OSCTUNE	EQU	90h		; Frequency control
TXSTA	EQU	98h		; in bank1
SPBRG	EQU	99h		; in bank1
ANSEL	EQU	9Bh		; a/d line property
adcon1	EQU	9Fh		;*A/D format control


You can use the banksel directive to change this:
Code:
	ORG	0000h
Start	BCF     status,rp1	; banks 0 & 1 only
to this:
Code:
	ORG	0000h
Start
	banksel	PORTA	;bank 0
[COLOR="Red"]or[/COLOR]
	banksel	TRISA	;bank 1
[COLOR="Red"]and so on...[/COLOR]
 
Is this a code list or is it buried in an application?
I use gpasm.
It looks like a code list and it looks like I had it yesterday.
Give me some time to think and go play. Thanks.
 
WVProfessor said:
Wow, this is almost real time.
Where can I get the file <p16f88.inc>?
I looked all over the Microchip site.
Include files come with MPLAB. Navigate to (typically) c:\program files\microchip\mpasm suite, open the p16f88.inc file and have a look (there's an include file for every model of PIC - use the appropriate one for your PIC). Get in the habit of using those equate symbols (they match the ones you see in the datasheet) instead of the actual hex numbers in your code. Makes the code much more readable and less prone to errors. You'll spend much less time trying to remember what the numbers are and be able to tell at a glance what registers you're manipulating.
 
Mplab/mpasm

I have a bad feeling about MPLAB following me from my Pentium 1 to the old '486.
I am an old analog electronic engineer. I made a ratty looking circuit on protoboard for the PIC88. Sometimes the connections hold together and it works.
 
Sucess

Silly me. It can't find p16F88.inc because I changed the name. That was before I knew what it was.

Now I see the error of my ways. This is what I get for moving the scope into the other room so I can't see the waveform. I thought maybe the input pin was shot by static and tested the pin with a logic probe. It was low all the time. It was supposed to be high. The output pin was high. I tried a 10k pullup. Now everything works. The Motorola MC145407P is not supposed to be open collector. I'll check the part.

The MPLAB/MPASM stuff requires a modern computer like an XP machine. I have only a Pentium II.

My next problem is using the I2C hardware to talk to a 24LC512. Has this been done?
 
WVProfessor said:
The MPLAB/MPASM stuff requires a modern computer like an XP machine. I have only a Pentium II.

Pentium II is fine, you could always just use MPASMWIN rather than the full MPLAB, which has even less requirements - or even use MPASM which is a DOS application.
 
WVProfessor said:
The MPLAB/MPASM stuff requires a modern computer like an XP machine. I have only a Pentium II.
Computers are cheap these days. For $300ish you can have a new "package" machine that, while not any kind of speed demon by today's standards, is perfectly capable of running just about anything you can throw at it.

Examples:
**broken link removed**
**broken link removed**
**broken link removed**

Chuck in another hundred bucks for an XP Home license. You don't need Pro.

EDIT: Keep your eyes open too. I've picked up perfectly good chucked out computers (yes, more than one) sitting by (or in) garbage dumpsters that needed nothing but a little TLC and maybe a bit of parts swapping from other junkers to get working. One little Celeron 1.7MHz box that I dug out from under three feet of mud and leaves even had an XP license sticker still on it. I put a new cheapy mainboard in it (old one was fried) and replaced the tiny hard drive with a used one I had kickin around and it runs like a top. Free XP! Gotta love it!
 
Last edited:
The plot thickens

Good catch. I'll see if I can play with it.

I compared my code to the code that works and found the part that makes the difference.
Look at the commented out lines and the three below them that make it work. This piece of code changes the input characteristics of the PIC16F88 so that it can go high. I even tried taking out the 10k pullup but that made the good code fail. I read the data sheet but it just, almost accidently, did these things serially. I wonder what is going on here, why the delay is needed?

; MOVLW 90h ;Set SPEN and set CREN in RCSTA
; MOVWF RCSTA
bsf RCSTA,7 ;SPEN serial port enable
nop
bsf RCSTA,4 ;CREN enable receive
 
Nigel Goodwin said:
No need for it to, I2C master is simple in software - you only need hardware support for slave.

I looked at the code under Tutorial6 and it is software control of the signal lines without using the specialized internal hardware. I have a much smaller instruction list that does the same thing, more or less.

All these "bit banging" techniques have critical timing intervals that cannot be used for some other purpose. I want to use the hardware if at all possible.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top